aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoritz Pflanzer <moritz.pflanzer@arm.com>2017-09-08 09:53:14 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:35:24 +0000
commitcde1e8adeacea5c33a1682ef7b05a0ef643463b8 (patch)
tree47e58abdf5bb6ef39db362a2ac777c93b3f76666
parent86b53339679e12c952a24a8845a5409ac3d52de6 (diff)
downloadComputeLibrary-cde1e8adeacea5c33a1682ef7b05a0ef643463b8.tar.gz
COMPMID-415: Add tests for ConvolutionLayer reshaped weights
Change-Id: I6c1209a2afafccba2cbdbcda16aceb3ae0cc7b4b Reviewed-on: http://mpd-gerrit.cambridge.arm.com/87000 Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com> Reviewed-by: Gian Marco Iodice <gianmarco.iodice@arm.com>
-rw-r--r--tests/RawTensor.h38
-rw-r--r--tests/SimpleTensor.h4
-rw-r--r--tests/validation/CL/ConvolutionLayer.cpp30
-rw-r--r--tests/validation/CPP/Utils.cpp28
-rw-r--r--tests/validation/CPP/Utils.h2
-rw-r--r--tests/validation/NEON/ConvolutionLayer.cpp46
-rw-r--r--tests/validation/fixtures/ConvolutionLayerFixture.h125
-rw-r--r--tests/validation/fixtures/DirectConvolutionLayerFixture.h87
-rw-r--r--tests/validation/fixtures/FullyConnectedLayerFixture.h33
9 files changed, 318 insertions, 75 deletions
diff --git a/tests/RawTensor.h b/tests/RawTensor.h
index fd0ab2b9fd..116275d617 100644
--- a/tests/RawTensor.h
+++ b/tests/RawTensor.h
@@ -55,6 +55,44 @@ public:
*/
RawTensor(TensorShape shape, DataType data_type, int num_channels = 1, int fixed_point_position = 0);
+ /** Conversion constructor from SimpleTensor.
+ *
+ * The passed SimpleTensor will be destroyed after it has been converted to
+ * a RawTensor.
+ *
+ * @param[in,out] tensor SimpleTensor to be converted to a RawTensor.
+ */
+ template <typename T>
+ RawTensor(SimpleTensor<T> &&tensor)
+ {
+ _buffer = std::unique_ptr<uint8_t[]>(reinterpret_cast<uint8_t *>(tensor._buffer.release()));
+ _shape = std::move(tensor._shape);
+ _format = tensor._format;
+ _data_type = tensor._data_type;
+ _num_channels = tensor._num_channels;
+ _fixed_point_position = tensor._fixed_point_position;
+ }
+
+ /** Conversion operator to SimpleTensor.
+ *
+ * The current RawTensor must not be used after the conversion.
+ *
+ * @return SimpleTensor of the given type.
+ */
+ template <typename T>
+ operator SimpleTensor<T>()
+ {
+ SimpleTensor<T> cast;
+ cast._buffer = std::unique_ptr<T[]>(reinterpret_cast<T *>(_buffer.release()));
+ cast._shape = std::move(_shape);
+ cast._format = _format;
+ cast._data_type = _data_type;
+ cast._num_channels = _num_channels;
+ cast._fixed_point_position = _fixed_point_position;
+
+ return cast;
+ }
+
/** Create a deep copy of the given @p tensor.
*
* @param[in] tensor To be copied tensor.
diff --git a/tests/SimpleTensor.h b/tests/SimpleTensor.h
index ea955fa730..0f79a3899a 100644
--- a/tests/SimpleTensor.h
+++ b/tests/SimpleTensor.h
@@ -44,6 +44,8 @@ namespace arm_compute
{
namespace test
{
+class RawTensor;
+
/** Simple tensor object that stores elements in a consecutive chunk of memory.
*
* It can be created by either loading an image from a file which also
@@ -94,6 +96,8 @@ public:
using value_type = T;
using Buffer = std::unique_ptr<value_type[]>;
+ friend class RawTensor;
+
/** Return value at @p offset in the buffer.
*
* @param[in] offset Offset within the buffer.
diff --git a/tests/validation/CL/ConvolutionLayer.cpp b/tests/validation/CL/ConvolutionLayer.cpp
index 6ae992b83b..860b92bb3c 100644
--- a/tests/validation/CL/ConvolutionLayer.cpp
+++ b/tests/validation/CL/ConvolutionLayer.cpp
@@ -103,14 +103,16 @@ using CLConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAcces
TEST_SUITE(Float)
TEST_SUITE(FP16)
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::F16)))
{
// Validate output
validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::F16)))
{
@@ -120,14 +122,18 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<half_float::half>, fr
TEST_SUITE_END()
TEST_SUITE(FP32)
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType",
- DataType::F32)))
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType",
+ DataType::F32)))
{
// Validate output
validate(CLAccessor(_target), _reference, tolerance_f32);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType",
- DataType::F32)))
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType",
+ DataType::F32)))
{
// Validate output
validate(CLAccessor(_target), _reference, tolerance_f32);
@@ -141,7 +147,8 @@ using CLConvolutionLayerFixedPointFixture = ConvolutionValidationFixedPointFixtu
TEST_SUITE(Quantized)
TEST_SUITE(QS8)
// We test for fixed point precision [4,6]
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::QS8)),
framework::dataset::make("FractionalBits", 4, 7)))
@@ -149,7 +156,8 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int8_t>, fr
// Validate output
validate(CLAccessor(_target), _reference, tolerance_q);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::QS8)),
framework::dataset::make("FractionalBits", 4, 7)))
@@ -161,7 +169,8 @@ TEST_SUITE_END()
TEST_SUITE(QS16)
// Testing for fixed point position [1,14)
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::QS16)),
framework::dataset::make("FractionalBits", 1, 14)))
@@ -169,7 +178,8 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture<int16_t>, f
// Validate output
validate(CLAccessor(_target), _reference, tolerance_q);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
framework::dataset::make("DataType",
DataType::QS16)),
framework::dataset::make("FractionalBits", 1, 14)))
diff --git a/tests/validation/CPP/Utils.cpp b/tests/validation/CPP/Utils.cpp
index 03d4eb7405..15e9fc3138 100644
--- a/tests/validation/CPP/Utils.cpp
+++ b/tests/validation/CPP/Utils.cpp
@@ -125,6 +125,34 @@ template void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor<uint
BorderMode border_mode,
uint8_t constant_border_value);
+RawTensor transpose(const RawTensor &src, int chunk_width)
+{
+ // Create reference
+ TensorShape dst_shape(src.shape());
+ dst_shape.set(0, src.shape().y() * chunk_width);
+ dst_shape.set(1, std::ceil(src.shape().x() / static_cast<float>(chunk_width)));
+
+ RawTensor dst{ dst_shape, src.data_type() };
+
+ // Compute reference
+ uint8_t *out_ptr = dst.data();
+
+ for(int i = 0; i < dst.num_elements(); i += chunk_width)
+ {
+ Coordinates coord = index2coord(dst.shape(), i);
+ size_t coord_x = coord.x();
+ coord.set(0, coord.y() * chunk_width);
+ coord.set(1, coord_x / chunk_width);
+
+ const int num_elements = std::min<int>(chunk_width, src.shape().x() - coord.x());
+
+ std::copy_n(static_cast<const uint8_t *>(src(coord)), num_elements * src.element_size(), out_ptr);
+
+ out_ptr += chunk_width * dst.element_size();
+ }
+
+ return dst;
+}
} // namespace validation
} // namespace test
} // namespace arm_compute
diff --git a/tests/validation/CPP/Utils.h b/tests/validation/CPP/Utils.h
index a1de4636ce..34ba60bed6 100644
--- a/tests/validation/CPP/Utils.h
+++ b/tests/validation/CPP/Utils.h
@@ -50,6 +50,8 @@ T bilinear_policy(const SimpleTensor<T> &in, Coordinates id, float xn, float yn,
template <typename T1, typename T2, typename T3>
void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor<T1> &in, SimpleTensor<T3> &out, const TensorShape &filter_shape, const T2 *filter_itr, float scale, BorderMode border_mode,
T1 constant_border_value = 0);
+
+RawTensor transpose(const RawTensor &src, int chunk_width = 1);
} // namespace validation
} // namespace test
} // namespace arm_compute
diff --git a/tests/validation/NEON/ConvolutionLayer.cpp b/tests/validation/NEON/ConvolutionLayer.cpp
index 7a3306d232..5880a7eda2 100644
--- a/tests/validation/NEON/ConvolutionLayer.cpp
+++ b/tests/validation/NEON/ConvolutionLayer.cpp
@@ -107,16 +107,16 @@ using NEConvolutionLayerFixture = ConvolutionValidationFixture<Tensor, Accessor,
TEST_SUITE(Float)
#ifdef ARM_COMPUTE_ENABLE_FP16
TEST_SUITE(FP16)
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::F16)))
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::F16)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_f16);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::F16)))
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::F16)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_f16);
@@ -125,14 +125,16 @@ TEST_SUITE_END()
#endif /* ARM_COMPUTE_ENABLE_FP16 */
TEST_SUITE(FP32)
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType",
- DataType::F32)))
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::F32)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_f32);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType",
- DataType::F32)))
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::F32)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_f32);
@@ -146,17 +148,17 @@ using NEConvolutionLayerFixedPointFixture = ConvolutionValidationFixedPointFixtu
TEST_SUITE(Quantized)
TEST_SUITE(QS8)
// We test for fixed point precision [4,6]
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::QS8)),
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::QS8)),
framework::dataset::make("FractionalBits", 4, 7)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_q);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::QS8)),
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::QS8)),
framework::dataset::make("FractionalBits", 4, 7)))
{
// Validate output
@@ -166,17 +168,17 @@ TEST_SUITE_END()
TEST_SUITE(QS16)
// Testing for fixed point position [1,14)
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::QS16)),
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::QS16)),
framework::dataset::make("FractionalBits", 1, 14)))
{
// Validate output
validate(Accessor(_target), _reference, tolerance_q);
}
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(),
- framework::dataset::make("DataType",
- DataType::QS16)),
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
+ framework::dataset::make("ReshapeWeights", { true, false })),
+ framework::dataset::make("DataType", DataType::QS16)),
framework::dataset::make("FractionalBits", 1, 14)))
{
// Validate output
diff --git a/tests/validation/fixtures/ConvolutionLayerFixture.h b/tests/validation/fixtures/ConvolutionLayerFixture.h
index 87b11ac130..dd2df727e9 100644
--- a/tests/validation/fixtures/ConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/ConvolutionLayerFixture.h
@@ -32,6 +32,7 @@
#include "tests/framework/Asserts.h"
#include "tests/framework/Fixture.h"
#include "tests/validation/CPP/ConvolutionLayer.h"
+#include "tests/validation/CPP/Utils.h"
#include "tests/validation/Helpers.h"
#include <random>
@@ -47,12 +48,12 @@ class ConvolutionValidationFixedPointFixture : public framework::Fixture
{
public:
template <typename...>
- void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, DataType data_type, int fractional_bits)
+ void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, bool reshape_weights, DataType data_type, int fractional_bits)
{
_fractional_bits = fractional_bits;
_data_type = data_type;
- _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits);
+ _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, reshape_weights, data_type, fractional_bits);
_reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits);
}
@@ -75,17 +76,45 @@ protected:
}
TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
- DataType data_type, int fixed_point_position)
+ bool reshape_weights, DataType data_type, int fixed_point_position)
{
+ WeightsInfo weights_info(!reshape_weights, weights_shape.x(), weights_shape.y(), weights_shape[3]);
+ TensorShape reshaped_weights_shape(weights_shape);
+
+ if(!reshape_weights)
+ {
+ // Check if its a "fully connected" convolution
+ const bool is_fully_connected_convolution = (output_shape.x() == 1 && output_shape.y() == 1);
+ reshaped_weights_shape.collapse(3);
+
+ if(bias_shape.total_size() > 0)
+ {
+ reshaped_weights_shape.set(0, reshaped_weights_shape.x() + 1);
+ }
+
+ if(is_fully_connected_convolution)
+ {
+ const size_t shape_x = reshaped_weights_shape.x();
+ reshaped_weights_shape.set(0, reshaped_weights_shape.y());
+ reshaped_weights_shape.set(1, shape_x);
+ }
+ else
+ {
+ const int interleave_width = 16 / data_size_from_type(data_type);
+ reshaped_weights_shape.set(0, reshaped_weights_shape.x() * interleave_width);
+ reshaped_weights_shape.set(1, static_cast<unsigned int>(std::ceil(reshaped_weights_shape.y() / static_cast<float>(interleave_width))));
+ }
+ }
+
// Create tensors
TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, fixed_point_position);
- TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, fixed_point_position);
+ TensorType weights = create_tensor<TensorType>(reshaped_weights_shape, data_type, 1, fixed_point_position);
TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1, fixed_point_position);
TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, fixed_point_position);
// Create and configure function
FunctionType conv;
- conv.configure(&src, &weights, &bias, &dst, info);
+ conv.configure(&src, &weights, &bias, &dst, info, weights_info);
ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
@@ -105,8 +134,41 @@ protected:
// Fill tensors
fill(AccessorType(src), 0);
- fill(AccessorType(weights), 1);
- fill(AccessorType(bias), 2);
+
+ if(!reshape_weights)
+ {
+ const bool is_fully_connected_convolution = (output_shape.x() == 1 && output_shape.y() == 1);
+
+ TensorShape tmp_weights_shape(weights_shape);
+ SimpleTensor<T> tmp_weights(tmp_weights_shape, data_type, 1, fixed_point_position);
+ SimpleTensor<T> tmp_bias(bias_shape, data_type, 1, fixed_point_position);
+
+ // Fill with original shape
+ fill(tmp_weights, 1);
+ fill(tmp_bias, 2);
+
+ tmp_weights = linearise_weights(tmp_weights, &tmp_bias);
+
+ if(!is_fully_connected_convolution)
+ {
+ // Transpose with interleave
+ const int interleave_size = 16 / tmp_weights.element_size();
+ tmp_weights = transpose(std::move(tmp_weights), interleave_size);
+ }
+
+ AccessorType weights_accessor(weights);
+
+ for(int i = 0; i < tmp_weights.num_elements(); ++i)
+ {
+ Coordinates coord = index2coord(tmp_weights.shape(), i);
+ std::copy_n(static_cast<const T *>(tmp_weights(coord)), 1, static_cast<T *>(weights_accessor(coord)));
+ }
+ }
+ else
+ {
+ fill(AccessorType(weights), 1);
+ fill(AccessorType(bias), 2);
+ }
// Compute NEConvolutionLayer function
conv.run();
@@ -134,6 +196,51 @@ protected:
SimpleTensor<T> _reference{};
int _fractional_bits{};
DataType _data_type{};
+
+private:
+ template <typename U>
+ SimpleTensor<U> linearise_weights(const SimpleTensor<U> &weights, const SimpleTensor<U> *biases = nullptr)
+ {
+ TensorShape dst_shape(weights.shape());
+ dst_shape.collapse(3);
+
+ if(biases != nullptr)
+ {
+ dst_shape.set(0, dst_shape.x() + 1);
+ }
+
+ const size_t shape_x = dst_shape.x();
+ dst_shape.set(0, dst_shape.y());
+ dst_shape.set(1, shape_x);
+
+ SimpleTensor<U> dst(dst_shape, weights.data_type());
+
+ // Don't iterate over biases yet
+ for(int weights_idx = 0; weights_idx < weights.num_elements(); ++weights_idx)
+ {
+ Coordinates weights_coord = index2coord(weights.shape(), weights_idx);
+ const int dst_row = weights_idx % weights.shape().total_size_lower(3);
+ Coordinates dst_coord{ weights_coord[3], dst_row, weights_coord[4] };
+ const int dst_idx = coord2index(dst.shape(), dst_coord);
+
+ dst[dst_idx] = weights[weights_idx];
+ }
+
+ if(biases != nullptr)
+ {
+ // Fill last row with biases
+ for(int bias_idx = 0; bias_idx < biases->num_elements(); ++bias_idx)
+ {
+ Coordinates bias_coord = index2coord(biases->shape(), bias_idx);
+ Coordinates dst_coord{ bias_coord.x(), static_cast<int>(dst.shape().y()) - 1, bias_coord.y() };
+ int dst_idx = coord2index(dst.shape(), dst_coord);
+
+ dst[dst_idx] = (*biases)[bias_idx];
+ }
+ }
+
+ return dst;
+ }
};
template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
@@ -141,9 +248,9 @@ class ConvolutionValidationFixture : public ConvolutionValidationFixedPointFixtu
{
public:
template <typename...>
- void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, DataType data_type)
+ void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, bool reshape_weights, DataType data_type)
{
- ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, 0);
+ ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, reshape_weights, data_type, 0);
}
};
} // namespace validation
diff --git a/tests/validation/fixtures/DirectConvolutionLayerFixture.h b/tests/validation/fixtures/DirectConvolutionLayerFixture.h
index 6ffebce108..a709157c7b 100644
--- a/tests/validation/fixtures/DirectConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DirectConvolutionLayerFixture.h
@@ -41,20 +41,103 @@ namespace test
namespace validation
{
template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
-class DirectConvolutionValidationFixedPointFixture : public ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>
+class DirectConvolutionValidationFixedPointFixture : public framework::Fixture
{
public:
template <typename...>
void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, DataType data_type, int fractional_bits)
{
+ _fractional_bits = fractional_bits;
+ _data_type = data_type;
+
const TensorShape weights_shape(kernel_size, kernel_size, input_shape.z(), num_kernels);
const TensorShape bias_shape(num_kernels);
const PadStrideInfo info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);
const TensorShape output_shape = get_output_shape(input_shape, weights_shape, info);
- ConvolutionValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits);
+ _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits);
+ _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, fractional_bits);
+ }
+
+protected:
+ template <typename U>
+ void fill(U &&tensor, int i)
+ {
+ switch(tensor.data_type())
+ {
+ case DataType::F16:
+ case DataType::F32:
+ {
+ std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
+ library->fill(tensor, distribution, i);
+ break;
+ }
+ default:
+ library->fill_tensor_uniform(tensor, i);
+ }
+ }
+
+ TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
+ DataType data_type, int fixed_point_position)
+ {
+ // Create tensors
+ TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, fixed_point_position);
+ TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, fixed_point_position);
+ TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1, fixed_point_position);
+ TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, fixed_point_position);
+
+ // Create and configure function
+ FunctionType conv;
+ conv.configure(&src, &weights, &bias, &dst, info);
+
+ ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Allocate tensors
+ src.allocator()->allocate();
+ weights.allocator()->allocate();
+ bias.allocator()->allocate();
+ dst.allocator()->allocate();
+
+ ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!bias.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Fill tensors
+ fill(AccessorType(src), 0);
+ fill(AccessorType(weights), 1);
+ fill(AccessorType(bias), 2);
+
+ // Compute NEConvolutionLayer function
+ conv.run();
+
+ return dst;
+ }
+
+ SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
+ DataType data_type, int fixed_point_position)
+ {
+ // Create reference
+ SimpleTensor<T> src{ input_shape, data_type, 1, fixed_point_position };
+ SimpleTensor<T> weights{ weights_shape, data_type, 1, fixed_point_position };
+ SimpleTensor<T> bias{ bias_shape, data_type, 1, fixed_point_position };
+
+ // Fill reference
+ fill(src, 0);
+ fill(weights, 1);
+ fill(bias, 2);
+
+ return reference::convolution_layer<T>(src, weights, bias, output_shape, info);
}
+ TensorType _target{};
+ SimpleTensor<T> _reference{};
+ int _fractional_bits{};
+ DataType _data_type{};
+
private:
TensorShape get_output_shape(TensorShape in_shape, TensorShape kernel_shape, const PadStrideInfo &info)
{
diff --git a/tests/validation/fixtures/FullyConnectedLayerFixture.h b/tests/validation/fixtures/FullyConnectedLayerFixture.h
index d4d68f1af8..b19c40d5ea 100644
--- a/tests/validation/fixtures/FullyConnectedLayerFixture.h
+++ b/tests/validation/fixtures/FullyConnectedLayerFixture.h
@@ -34,6 +34,7 @@
#include "tests/framework/Asserts.h"
#include "tests/framework/Fixture.h"
#include "tests/validation/CPP/FullyConnectedLayer.h"
+#include "tests/validation/CPP/Utils.h"
#include "tests/validation/Helpers.h"
#include <random>
@@ -44,38 +45,6 @@ namespace test
{
namespace validation
{
-namespace
-{
-RawTensor transpose(const RawTensor &src, int interleave = 1)
-{
- // Create reference
- TensorShape dst_shape(src.shape());
- dst_shape.set(0, src.shape().y() * interleave);
- dst_shape.set(1, std::ceil(src.shape().x() / static_cast<float>(interleave)));
-
- RawTensor dst{ dst_shape, src.data_type() };
-
- // Compute reference
- uint8_t *out_ptr = dst.data();
-
- for(int i = 0; i < dst.num_elements(); i += interleave)
- {
- Coordinates coord = index2coord(dst.shape(), i);
- size_t coord_x = coord.x();
- coord.set(0, coord.y() * interleave);
- coord.set(1, coord_x / interleave);
-
- const int num_elements = std::min<int>(interleave, src.shape().x() - coord.x());
-
- std::copy_n(static_cast<const uint8_t *>(src(coord)), num_elements * src.element_size(), out_ptr);
-
- out_ptr += interleave * dst.element_size();
- }
-
- return dst;
-}
-} // namespace
-
template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool run_interleave>
class FullyConnectedLayerValidationFixedPointFixture : public framework::Fixture
{