From 559d77179bfe8daaeb1f6754ee2287bd12a6aa04 Mon Sep 17 00:00:00 2001 From: Gian Marco Iodice Date: Tue, 8 Aug 2017 08:38:09 +0100 Subject: COMPMID-417 - Fixed auto-config in NEConvolutionLayer and in CLConvolutionLayer Change-Id: Ibfd772200348b326738bb3b8357f0abbb7a583d7 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/82943 Reviewed-by: Georgios Pinitas Reviewed-by: Moritz Pflanzer Tested-by: Kaizen --- arm_compute/core/Helpers.inl | 2 +- arm_compute/core/Types.h | 18 ++++++++++++++---- src/runtime/CL/functions/CLConvolutionLayer.cpp | 9 +++++---- src/runtime/NEON/functions/NEConvolutionLayer.cpp | 9 +++++---- tests/model_objects/AlexNet.h | 16 ++++++++-------- tests/networks_new/AlexNetNetwork.h | 16 ++++++++-------- 6 files changed, 41 insertions(+), 29 deletions(-) diff --git a/arm_compute/core/Helpers.inl b/arm_compute/core/Helpers.inl index d342a60987..78e0c70e1b 100644 --- a/arm_compute/core/Helpers.inl +++ b/arm_compute/core/Helpers.inl @@ -251,8 +251,8 @@ inline bool auto_init_if_empty(ITensorInfo &info, const TensorShape &shape, int if(info.tensor_shape().total_size() == 0) { info.set_data_type(data_type); - info.set_tensor_shape(shape); info.set_num_channels(num_channels); + info.set_tensor_shape(shape); info.set_fixed_point_position(fixed_point_position); return true; } diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 3092976149..1d04f35359 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -607,13 +607,13 @@ private: float _kappa; }; -/** Convolution Layer Weights Information class */ +/** Convolution Layer Weights Information class. This class stores the necessary information to compute convolution layer when the weights are already reshaped */ class WeightsInfo { public: /** Default constructor */ WeightsInfo() - : _are_reshaped(false), _kernel_width(0), _kernel_height(0) + : _are_reshaped(false), _kernel_width(0), _kernel_height(0), _num_kernels(0) { } /** Constructor @@ -621,9 +621,10 @@ public: * @param[in] are_reshaped True if the weights have been reshaped * @param[in] kernel_width Kernel width. * @param[in] kernel_height Kernel height. + * @param[in] num_kernels Number of convolution kernels. */ - WeightsInfo(bool are_reshaped, unsigned int kernel_width, unsigned int kernel_height) - : _are_reshaped(are_reshaped), _kernel_width(kernel_width), _kernel_height(kernel_height) + WeightsInfo(bool are_reshaped, unsigned int kernel_width, unsigned int kernel_height, unsigned int num_kernels) + : _are_reshaped(are_reshaped), _kernel_width(kernel_width), _kernel_height(kernel_height), _num_kernels(num_kernels) { } /** Flag which specifies if the weights tensor has been reshaped. @@ -634,6 +635,14 @@ public: { return _are_reshaped; }; + /** Return the number of convolution kernels + * + * @return The number of convolution kernels + */ + unsigned int num_kernels() const + { + return _num_kernels; + }; /** Return the width and height of the kernel * * @return The width and height of the kernel @@ -647,6 +656,7 @@ private: const bool _are_reshaped; const unsigned int _kernel_width; const unsigned int _kernel_height; + const unsigned int _num_kernels; }; /** IO formatting information class*/ diff --git a/src/runtime/CL/functions/CLConvolutionLayer.cpp b/src/runtime/CL/functions/CLConvolutionLayer.cpp index 4362cfd437..ff94e9d7a2 100644 --- a/src/runtime/CL/functions/CLConvolutionLayer.cpp +++ b/src/runtime/CL/functions/CLConvolutionLayer.cpp @@ -97,8 +97,8 @@ CLConvolutionLayer::CLConvolutionLayer() void CLConvolutionLayer::configure(const ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info) { ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32); - ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights, output); - ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, weights, output); + ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights); + ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, weights); ARM_COMPUTE_ERROR_ON(!weights_info.are_reshaped() && weights->info()->dimension(2) != input->info()->dimension(2)); ARM_COMPUTE_ERROR_ON(weights->info()->num_dimensions() > 4); @@ -132,7 +132,6 @@ void CLConvolutionLayer::configure(const ICLTensor *input, const ICLTensor *weig const unsigned int kernel_height = (_are_weights_reshaped) ? weights_info.kernel_size().second : weights->info()->dimension(1); std::tie(conv_w, conv_h) = scaled_dimensions(input->info()->dimension(0), input->info()->dimension(1), kernel_width, kernel_height, conv_info); - ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(0) != conv_w) || (output->info()->dimension(1) != conv_h), "Output shape does not match the expected one"); // Check if its a "fully connected" convolution _is_fully_connected_convolution = ((conv_w == 1) && (conv_h == 1)); @@ -143,7 +142,7 @@ void CLConvolutionLayer::configure(const ICLTensor *input, const ICLTensor *weig // Reshape weights if needed if(_are_weights_reshaped) { - mat_weights_cols = output->info()->dimension(2); + mat_weights_cols = weights_info.num_kernels(); const unsigned int quarter_reshaped_cols = weights->info()->dimension(0) / 4; mat_weights_rows = (_has_bias ? 1 + quarter_reshaped_cols : quarter_reshaped_cols); } @@ -206,6 +205,8 @@ void CLConvolutionLayer::configure(const ICLTensor *input, const ICLTensor *weig } _output_col2im_kernel.configure(&_gemm_output, output, std::make_pair(conv_w, conv_h)); + ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(0) != conv_w) || (output->info()->dimension(1) != conv_h), "Output shape does not match the expected one"); + // Allocate intermediate tensor if(!_are_weights_reshaped) { diff --git a/src/runtime/NEON/functions/NEConvolutionLayer.cpp b/src/runtime/NEON/functions/NEConvolutionLayer.cpp index f6481f1918..1c87f60a29 100644 --- a/src/runtime/NEON/functions/NEConvolutionLayer.cpp +++ b/src/runtime/NEON/functions/NEConvolutionLayer.cpp @@ -96,8 +96,8 @@ NEConvolutionLayer::NEConvolutionLayer() void NEConvolutionLayer::configure(const ITensor *input, const ITensor *weights, const ITensor *biases, ITensor *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info) { ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QS8, DataType::QS16, DataType::F16, DataType::F32); - ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights, output); - ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, weights, output); + ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights); + ARM_COMPUTE_ERROR_ON_MISMATCHING_FIXED_POINT(input, weights); ARM_COMPUTE_ERROR_ON(!weights_info.are_reshaped() && weights->info()->dimension(2) != input->info()->dimension(2)); ARM_COMPUTE_ERROR_ON(weights->info()->num_dimensions() > 4); @@ -131,7 +131,6 @@ void NEConvolutionLayer::configure(const ITensor *input, const ITensor *weights, const unsigned int kernel_height = (_are_weights_reshaped) ? weights_info.kernel_size().second : weights->info()->dimension(1); std::tie(conv_w, conv_h) = scaled_dimensions(input->info()->dimension(0), input->info()->dimension(1), kernel_width, kernel_height, conv_info); - ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(0) != conv_w) || (output->info()->dimension(1) != conv_h), "Output shape does not match the expected one"); // Check if its a "fully connected" convolution _is_fully_connected_convolution = ((conv_w == 1) && (conv_h == 1)); @@ -142,7 +141,7 @@ void NEConvolutionLayer::configure(const ITensor *input, const ITensor *weights, // Reshape weights if needed if(_are_weights_reshaped) { - mat_weights_cols = output->info()->dimension(2); + mat_weights_cols = weights_info.num_kernels(); const unsigned int quarter_reshaped_cols = weights->info()->dimension(0) / 4; mat_weights_rows = (_has_bias ? 1 + quarter_reshaped_cols : quarter_reshaped_cols); } @@ -205,6 +204,8 @@ void NEConvolutionLayer::configure(const ITensor *input, const ITensor *weights, } _output_col2im_kernel.configure(&_gemm_output, output, std::make_pair(conv_w, conv_h)); + ARM_COMPUTE_ERROR_ON_MSG((output->info()->dimension(0) != conv_w) || (output->info()->dimension(1) != conv_h), "Output shape does not match the expected one"); + // Allocate intermediate tensor if(!_are_weights_reshaped) { diff --git a/tests/model_objects/AlexNet.h b/tests/model_objects/AlexNet.h index dad68324c1..c9fd448d5d 100644 --- a/tests/model_objects/AlexNet.h +++ b/tests/model_objects/AlexNet.h @@ -251,26 +251,26 @@ public: // Configure Layers { // Layer 1 - conv1->configure(&input, w[0].get(), b[0].get(), &conv1_out, PadStrideInfo(4, 4, 0, 0), WeightsInfo(_reshaped_weights, 11U, 11U)); + conv1->configure(&input, w[0].get(), b[0].get(), &conv1_out, PadStrideInfo(4, 4, 0, 0), WeightsInfo(_reshaped_weights, 11U, 11U, 96U)); act1->configure(&conv1_out, &act1_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); norm1->configure(&act1_out, &norm1_out, NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f)); pool1->configure(&norm1_out, &pool1_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 2 - conv21->configure(pool11_out.get(), w21.get(), b21.get(), conv21_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U)); - conv22->configure(pool12_out.get(), w22.get(), b22.get(), conv22_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U)); + conv21->configure(pool11_out.get(), w21.get(), b21.get(), conv21_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U, 128U)); + conv22->configure(pool12_out.get(), w22.get(), b22.get(), conv22_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U, 128U)); act2->configure(&conv2_out, &act2_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); norm2->configure(&act2_out, &norm2_out, NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f)); pool2->configure(&norm2_out, &pool2_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 3 - conv3->configure(&pool2_out, w[2].get(), b[2].get(), &conv3_out, PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv3->configure(&pool2_out, w[2].get(), b[2].get(), &conv3_out, PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 384U)); act3->configure(&conv3_out, &act3_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); // Layer 4 - conv41->configure(act31_out.get(), w41.get(), b41.get(), conv41_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); - conv42->configure(act32_out.get(), w42.get(), b42.get(), conv42_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv41->configure(act31_out.get(), w41.get(), b41.get(), conv41_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 192U)); + conv42->configure(act32_out.get(), w42.get(), b42.get(), conv42_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 192U)); act4->configure(&conv4_out, &act4_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); // Layer 5 - conv51->configure(act41_out.get(), w51.get(), b51.get(), conv51_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); - conv52->configure(act42_out.get(), w52.get(), b52.get(), conv52_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv51->configure(act41_out.get(), w51.get(), b51.get(), conv51_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 128U)); + conv52->configure(act42_out.get(), w52.get(), b52.get(), conv52_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 128U)); act5->configure(&conv5_out, &act5_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); pool5->configure(&act5_out, &pool5_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 6 diff --git a/tests/networks_new/AlexNetNetwork.h b/tests/networks_new/AlexNetNetwork.h index 8c801f70d3..28bcfa1e77 100644 --- a/tests/networks_new/AlexNetNetwork.h +++ b/tests/networks_new/AlexNetNetwork.h @@ -212,27 +212,27 @@ public: // Configure Layers // Layer 1 TensorType *b0 = _reshaped_weights ? nullptr : &b[0]; - conv1.configure(&input, &w[0], b0, &conv1_out, PadStrideInfo(4, 4, 0, 0), WeightsInfo(_reshaped_weights, 11U, 11U)); + conv1.configure(&input, &w[0], b0, &conv1_out, PadStrideInfo(4, 4, 0, 0), WeightsInfo(_reshaped_weights, 11U, 11U, 96U)); act1.configure(&conv1_out, &act1_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); norm1.configure(&act1_out, &norm1_out, NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f)); pool1.configure(&norm1_out, &pool1_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 2 - conv21.configure(pool11_out.get(), w21.get(), b21.get(), conv21_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U)); - conv22.configure(pool12_out.get(), w22.get(), b22.get(), conv22_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U)); + conv21.configure(pool11_out.get(), w21.get(), b21.get(), conv21_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U, 128U)); + conv22.configure(pool12_out.get(), w22.get(), b22.get(), conv22_out.get(), PadStrideInfo(1, 1, 2, 2), WeightsInfo(_reshaped_weights, 5U, 5U, 128U)); act2.configure(&conv2_out, &act2_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); norm2.configure(&act2_out, &norm2_out, NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f)); pool2.configure(&norm2_out, &pool2_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 3 TensorType *b2 = (_reshaped_weights && !_is_direct_conv) ? nullptr : &b[2]; - conv3.configure(&pool2_out, &w[2], b2, &conv3_out, PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv3.configure(&pool2_out, &w[2], b2, &conv3_out, PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 384U)); act3.configure(&conv3_out, &act3_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); // Layer 4 - conv41.configure(act31_out.get(), w41.get(), b41.get(), conv41_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); - conv42.configure(act32_out.get(), w42.get(), b42.get(), conv42_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv41.configure(act31_out.get(), w41.get(), b41.get(), conv41_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 192U)); + conv42.configure(act32_out.get(), w42.get(), b42.get(), conv42_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 192U)); act4.configure(&conv4_out, &act4_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); // Layer 5 - conv51.configure(act41_out.get(), w51.get(), b51.get(), conv51_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); - conv52.configure(act42_out.get(), w52.get(), b52.get(), conv52_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U)); + conv51.configure(act41_out.get(), w51.get(), b51.get(), conv51_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 128U)); + conv52.configure(act42_out.get(), w52.get(), b52.get(), conv52_out.get(), PadStrideInfo(1, 1, 1, 1), WeightsInfo(_reshaped_weights, 3U, 3U, 128U)); act5.configure(&conv5_out, &act5_out, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); pool5.configure(&act5_out, &pool5_out, PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0))); // Layer 6 -- cgit v1.2.1