From cde1e8adeacea5c33a1682ef7b05a0ef643463b8 Mon Sep 17 00:00:00 2001 From: Moritz Pflanzer Date: Fri, 8 Sep 2017 09:53:14 +0100 Subject: COMPMID-415: Add tests for ConvolutionLayer reshaped weights Change-Id: I6c1209a2afafccba2cbdbcda16aceb3ae0cc7b4b Reviewed-on: http://mpd-gerrit.cambridge.arm.com/87000 Tested-by: Kaizen Reviewed-by: Gian Marco Iodice --- tests/RawTensor.h | 38 +++++++ tests/SimpleTensor.h | 4 + tests/validation/CL/ConvolutionLayer.cpp | 30 +++-- tests/validation/CPP/Utils.cpp | 28 +++++ tests/validation/CPP/Utils.h | 2 + tests/validation/NEON/ConvolutionLayer.cpp | 46 ++++---- .../validation/fixtures/ConvolutionLayerFixture.h | 125 +++++++++++++++++++-- .../fixtures/DirectConvolutionLayerFixture.h | 87 +++++++++++++- .../fixtures/FullyConnectedLayerFixture.h | 33 +----- 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 + RawTensor(SimpleTensor &&tensor) + { + _buffer = std::unique_ptr(reinterpret_cast(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 + operator SimpleTensor() + { + SimpleTensor cast; + cast._buffer = std::unique_ptr(reinterpret_cast(_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; + 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, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture, 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, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture, 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, fr TEST_SUITE_END() TEST_SUITE(FP32) -FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixture, 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, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixture, 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, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture, 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, fr // Validate output validate(CLAccessor(_target), _reference, tolerance_q); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture, 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, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionLayerFixedPointFixture, 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, f // Validate output validate(CLAccessor(_target), _reference, tolerance_q); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), +FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionLayerFixedPointFixture, 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(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(chunk_width, src.shape().x() - coord.x()); + + std::copy_n(static_cast(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 &in, Coordinates id, float xn, float yn, template void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor &in, SimpleTensor &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, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::F16))) +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture, 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, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::F16))) +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture, 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, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallConvolutionLayerDataset(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixture, 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, framework::DatasetMode::NIGHTLY, combine(datasets::LargeConvolutionLayerDataset(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixture, 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, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::QS8)), +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture, 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, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::QS8)), +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture, 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, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::QS16)), +FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionLayerFixedPointFixture, 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, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeConvolutionLayerDataset(), - framework::dataset::make("DataType", - DataType::QS16)), +FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionLayerFixedPointFixture, 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 @@ -47,12 +48,12 @@ class ConvolutionValidationFixedPointFixture : public framework::Fixture { public: template - 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(std::ceil(reshaped_weights_shape.y() / static_cast(interleave_width)))); + } + } + // Create tensors TensorType src = create_tensor(input_shape, data_type, 1, fixed_point_position); - TensorType weights = create_tensor(weights_shape, data_type, 1, fixed_point_position); + TensorType weights = create_tensor(reshaped_weights_shape, data_type, 1, fixed_point_position); TensorType bias = create_tensor(bias_shape, data_type, 1, fixed_point_position); TensorType dst = create_tensor(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 tmp_weights(tmp_weights_shape, data_type, 1, fixed_point_position); + SimpleTensor 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(tmp_weights(coord)), 1, static_cast(weights_accessor(coord))); + } + } + else + { + fill(AccessorType(weights), 1); + fill(AccessorType(bias), 2); + } // Compute NEConvolutionLayer function conv.run(); @@ -134,6 +196,51 @@ protected: SimpleTensor _reference{}; int _fractional_bits{}; DataType _data_type{}; + +private: + template + SimpleTensor linearise_weights(const SimpleTensor &weights, const SimpleTensor *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 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(dst.shape().y()) - 1, bias_coord.y() }; + int dst_idx = coord2index(dst.shape(), dst_coord); + + dst[dst_idx] = (*biases)[bias_idx]; + } + } + + return dst; + } }; template @@ -141,9 +248,9 @@ class ConvolutionValidationFixture : public ConvolutionValidationFixedPointFixtu { public: template - 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::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, 0); + ConvolutionValidationFixedPointFixture::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 -class DirectConvolutionValidationFixedPointFixture : public ConvolutionValidationFixedPointFixture +class DirectConvolutionValidationFixedPointFixture : public framework::Fixture { public: template 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::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 + 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(input_shape, data_type, 1, fixed_point_position); + TensorType weights = create_tensor(weights_shape, data_type, 1, fixed_point_position); + TensorType bias = create_tensor(bias_shape, data_type, 1, fixed_point_position); + TensorType dst = create_tensor(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 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 src{ input_shape, data_type, 1, fixed_point_position }; + SimpleTensor weights{ weights_shape, data_type, 1, fixed_point_position }; + SimpleTensor bias{ bias_shape, data_type, 1, fixed_point_position }; + + // Fill reference + fill(src, 0); + fill(weights, 1); + fill(bias, 2); + + return reference::convolution_layer(src, weights, bias, output_shape, info); } + TensorType _target{}; + SimpleTensor _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 @@ -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(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(interleave, src.shape().x() - coord.x()); - - std::copy_n(static_cast(src(coord)), num_elements * src.element_size(), out_ptr); - - out_ptr += interleave * dst.element_size(); - } - - return dst; -} -} // namespace - template class FullyConnectedLayerValidationFixedPointFixture : public framework::Fixture { -- cgit v1.2.1