aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiorgio Arena <giorgio.arena@arm.com>2018-04-30 17:29:41 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:51:17 +0000
commit563494c2f447e201e88e6d7133a41e12971777eb (patch)
tree716ae5e4978ce378ad14f53591087a7a42f6fe58
parentb7f5d172ccdb1d884388dd6e0e54f74241afca67 (diff)
downloadComputeLibrary-563494c2f447e201e88e6d7133a41e12971777eb.tar.gz
COMPMID-1084 Rework the way validation is performed for NHWC data layout
Change-Id: I00b95f560548da76718298b642c8166f92421097 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/129520 Tested-by: Jenkins <bsgcomp@arm.com> Reviewed-by: Michele DiGiorgio <michele.digiorgio@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
-rw-r--r--arm_compute/core/Helpers.h4
-rw-r--r--arm_compute/core/TensorShape.h12
-rw-r--r--tests/AssetsLibrary.h17
-rw-r--r--tests/SimpleTensor.h6
-rw-r--r--tests/validation/Validation.h72
-rw-r--r--tests/validation/fixtures/BatchNormalizationLayerFixture.h18
-rw-r--r--tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h27
-rw-r--r--tests/validation/fixtures/DirectConvolutionLayerFixture.h55
-rw-r--r--tests/validation/fixtures/Im2ColFixture.h2
-rw-r--r--tests/validation/fixtures/PoolingLayerFixture.h20
-rw-r--r--tests/validation/reference/BatchNormalizationLayer.cpp20
-rw-r--r--tests/validation/reference/DepthwiseConvolutionLayer.cpp39
-rw-r--r--tests/validation/reference/PoolingLayer.cpp36
13 files changed, 158 insertions, 170 deletions
diff --git a/arm_compute/core/Helpers.h b/arm_compute/core/Helpers.h
index 4acb176250..21f3c38116 100644
--- a/arm_compute/core/Helpers.h
+++ b/arm_compute/core/Helpers.h
@@ -527,11 +527,11 @@ inline void permute(Dimensions<T> &dimensions, const PermutationVector &perm)
*/
inline void permute(TensorShape &shape, const PermutationVector &perm)
{
- auto shape_copy = utility::make_array<TensorShape::num_max_dimensions>(shape.begin(), shape.end());
+ TensorShape shape_copy = shape;
for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
{
size_t dimension_val = (perm[i] < shape.num_dimensions()) ? shape_copy[perm[i]] : 1;
- shape.set(i, dimension_val);
+ shape.set(i, dimension_val, false); // Avoid changes in _num_dimension
}
}
diff --git a/arm_compute/core/TensorShape.h b/arm_compute/core/TensorShape.h
index d5532e8a6a..0c3d9414e1 100644
--- a/arm_compute/core/TensorShape.h
+++ b/arm_compute/core/TensorShape.h
@@ -69,12 +69,13 @@ public:
/** Accessor to set the value of one of the dimensions.
*
- * @param[in] dimension Dimension for which the value is set.
- * @param[in] value Value to be set for the dimension.
+ * @param[in] dimension Dimension for which the value is set.
+ * @param[in] value Value to be set for the dimension.
+ * @param[in] apply_dim_correction Flag to state whether apply dimension correction after setting one dimension. E.g. when permuting NCHW -> NHWC, 1x1x2 would become 2x1x1, but _num_dimensions should be 3 rather than 1.
*
* @return *this.
*/
- TensorShape &set(size_t dimension, size_t value)
+ TensorShape &set(size_t dimension, size_t value, bool apply_dim_correction = true)
{
// Clear entire shape if one dimension is zero
if(value == 0)
@@ -92,7 +93,10 @@ public:
Dimensions::set(dimension, value);
// Correct number dimensions to ignore trailing dimensions of size 1
- apply_dimension_correction();
+ if(apply_dim_correction)
+ {
+ apply_dimension_correction();
+ }
}
return *this;
}
diff --git a/tests/AssetsLibrary.h b/tests/AssetsLibrary.h
index 4bbe4c56f6..1fba3d4b46 100644
--- a/tests/AssetsLibrary.h
+++ b/tests/AssetsLibrary.h
@@ -456,10 +456,25 @@ void AssetsLibrary::fill(T &&tensor, D &&distribution, std::random_device::resul
std::mt19937 gen(_seed + seed_offset);
+ const bool is_nhwc = tensor.data_layout() == DataLayout::NHWC;
+ TensorShape shape(tensor.shape());
+
+ if(is_nhwc)
+ {
+ // Ensure that the equivalent tensors will be filled for both data layouts
+ permute(shape, PermutationVector(1U, 2U, 0U));
+ }
+
// Iterate over all elements
for(int element_idx = 0; element_idx < tensor.num_elements(); ++element_idx)
{
- const Coordinates id = index2coord(tensor.shape(), element_idx);
+ Coordinates id = index2coord(shape, element_idx);
+
+ if(is_nhwc)
+ {
+ // Write in the correct id for permuted shapes
+ permute(id, PermutationVector(2U, 0U, 1U));
+ }
// Iterate over all channels
for(int channel = 0; channel < tensor.num_channels(); ++channel)
diff --git a/tests/SimpleTensor.h b/tests/SimpleTensor.h
index cfd13832fb..8b3b37010e 100644
--- a/tests/SimpleTensor.h
+++ b/tests/SimpleTensor.h
@@ -235,7 +235,8 @@ SimpleTensor<T>::SimpleTensor(TensorShape shape, Format format, int fixed_point_
_shape(shape),
_format(format),
_fixed_point_position(fixed_point_position),
- _quantization_info()
+ _quantization_info(),
+ _data_layout(DataLayout::NCHW)
{
_num_channels = num_channels();
_buffer = support::cpp14::make_unique<T[]>(num_elements() * _num_channels);
@@ -262,7 +263,8 @@ SimpleTensor<T>::SimpleTensor(const SimpleTensor &tensor)
_data_type(tensor.data_type()),
_num_channels(tensor.num_channels()),
_fixed_point_position(tensor.fixed_point_position()),
- _quantization_info(tensor.quantization_info())
+ _quantization_info(tensor.quantization_info()),
+ _data_layout(tensor.data_layout())
{
_buffer = support::cpp14::make_unique<T[]>(tensor.num_elements() * num_channels());
std::copy_n(tensor.data(), num_elements() * num_channels(), _buffer.get());
diff --git a/tests/validation/Validation.h b/tests/validation/Validation.h
index 508fb027ca..ac3643ea4a 100644
--- a/tests/validation/Validation.h
+++ b/tests/validation/Validation.h
@@ -137,19 +137,45 @@ inline ::std::ostream &operator<<(::std::ostream &os, const RelativeTolerance<T>
}
template <typename T>
-bool compare_dimensions(const Dimensions<T> &dimensions1, const Dimensions<T> &dimensions2)
+bool compare_dimensions(const Dimensions<T> &dimensions1, const Dimensions<T> &dimensions2, const DataLayout &data_layout = DataLayout::NCHW)
{
- if(dimensions1.num_dimensions() != dimensions2.num_dimensions())
+ ARM_COMPUTE_ERROR_ON(data_layout == DataLayout::UNKNOWN);
+
+ if(data_layout == DataLayout::NCHW)
{
- return false;
- }
+ if(dimensions1.num_dimensions() != dimensions2.num_dimensions())
+ {
+ return false;
+ }
- for(unsigned int i = 0; i < dimensions1.num_dimensions(); ++i)
+ for(unsigned int i = 0; i < dimensions1.num_dimensions(); ++i)
+ {
+ if(dimensions1[i] != dimensions2[i])
+ {
+ return false;
+ }
+ }
+ }
+ else
{
- if(dimensions1[i] != dimensions2[i])
+ // In case a 2D shape becomes 3D after permutation, the permuted tensor will have one dimension more and the first value will be 1
+ if((dimensions1.num_dimensions() != dimensions2.num_dimensions()) && ((dimensions1.num_dimensions() != (dimensions2.num_dimensions() + 1)) || (dimensions1.x() != 1)))
+ {
+ return false;
+ }
+
+ if((dimensions1[0] != dimensions2[2]) || (dimensions1[1] != dimensions2[0]) || (dimensions1[2] != dimensions2[1]))
{
return false;
}
+
+ for(unsigned int i = 3; i < dimensions1.num_dimensions(); ++i)
+ {
+ if(dimensions1[i] != dimensions2[i])
+ {
+ return false;
+ }
+ }
}
return true;
@@ -342,14 +368,14 @@ template <typename T, typename U>
void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, U tolerance_value, float tolerance_number, float absolute_tolerance_value)
{
// Validate with valid region covering the entire shape
- validate(tensor, reference, shape_to_valid_region(tensor.shape()), tolerance_value, tolerance_number, absolute_tolerance_value);
+ validate(tensor, reference, shape_to_valid_region(reference.shape()), tolerance_value, tolerance_number, absolute_tolerance_value);
}
template <typename T, typename U, typename = typename std::enable_if<std::is_integral<T>::value>::type>
void validate_wrap(const IAccessor &tensor, const SimpleTensor<T> &reference, U tolerance_value, float tolerance_number)
{
// Validate with valid region covering the entire shape
- validate_wrap(tensor, reference, shape_to_valid_region(tensor.shape()), tolerance_value, tolerance_number);
+ validate_wrap(tensor, reference, shape_to_valid_region(reference.shape()), tolerance_value, tolerance_number);
}
template <typename T, typename U>
@@ -367,7 +393,7 @@ void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const V
}
ARM_COMPUTE_EXPECT_EQUAL(tensor.num_channels(), reference.num_channels(), framework::LogLevel::ERRORS);
- ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape()), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape(), tensor.data_layout()), framework::LogLevel::ERRORS);
const int min_elements = std::min(tensor.num_elements(), reference.num_elements());
const int min_channels = std::min(tensor.num_channels(), reference.num_channels());
@@ -377,12 +403,18 @@ void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const V
{
const Coordinates id = index2coord(reference.shape(), element_idx);
+ Coordinates target_id(id);
+ if(tensor.data_layout() == DataLayout::NHWC)
+ {
+ permute(target_id, PermutationVector(2U, 0U, 1U));
+ }
+
if(is_in_valid_region(valid_region, id))
{
// Iterate over all channels within one element
for(int c = 0; c < min_channels; ++c)
{
- const T &target_value = reinterpret_cast<const T *>(tensor(id))[c];
+ const T &target_value = reinterpret_cast<const T *>(tensor(target_id))[c];
const T &reference_value = reinterpret_cast<const T *>(reference(id))[c];
if(!compare<U>(target_value, reference_value, tolerance_value))
@@ -436,7 +468,7 @@ void validate_wrap(const IAccessor &tensor, const SimpleTensor<T> &reference, co
}
ARM_COMPUTE_EXPECT_EQUAL(tensor.num_channels(), reference.num_channels(), framework::LogLevel::ERRORS);
- ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape()), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape(), tensor.data_layout()), framework::LogLevel::ERRORS);
const int min_elements = std::min(tensor.num_elements(), reference.num_elements());
const int min_channels = std::min(tensor.num_channels(), reference.num_channels());
@@ -446,12 +478,18 @@ void validate_wrap(const IAccessor &tensor, const SimpleTensor<T> &reference, co
{
const Coordinates id = index2coord(reference.shape(), element_idx);
+ Coordinates target_id(id);
+ if(tensor.data_layout() == DataLayout::NHWC)
+ {
+ permute(target_id, PermutationVector(2U, 0U, 1U));
+ }
+
if(is_in_valid_region(valid_region, id))
{
// Iterate over all channels within one element
for(int c = 0; c < min_channels; ++c)
{
- const T &target_value = reinterpret_cast<const T *>(tensor(id))[c];
+ const T &target_value = reinterpret_cast<const T *>(tensor(target_id))[c];
const T &reference_value = reinterpret_cast<const T *>(reference(id))[c];
bool equal = compare<U>(target_value, reference_value, tolerance_value);
@@ -518,7 +556,7 @@ void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const S
}
ARM_COMPUTE_EXPECT_EQUAL(tensor.num_channels(), reference.num_channels(), framework::LogLevel::ERRORS);
- ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape()), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(compare_dimensions(tensor.shape(), reference.shape(), tensor.data_layout()), framework::LogLevel::ERRORS);
const int min_elements = std::min(tensor.num_elements(), reference.num_elements());
const int min_channels = std::min(tensor.num_channels(), reference.num_channels());
@@ -528,12 +566,18 @@ void validate(const IAccessor &tensor, const SimpleTensor<T> &reference, const S
{
const Coordinates id = index2coord(reference.shape(), element_idx);
+ Coordinates target_id(id);
+ if(tensor.data_layout() == DataLayout::NHWC)
+ {
+ permute(target_id, PermutationVector(2U, 0U, 1U));
+ }
+
if(valid_mask[element_idx] == 1)
{
// Iterate over all channels within one element
for(int c = 0; c < min_channels; ++c)
{
- const T &target_value = reinterpret_cast<const T *>(tensor(id))[c];
+ const T &target_value = reinterpret_cast<const T *>(tensor(target_id))[c];
const T &reference_value = reinterpret_cast<const T *>(reference(id))[c];
if(!compare<U>(target_value, reference_value, tolerance_value))
diff --git a/tests/validation/fixtures/BatchNormalizationLayerFixture.h b/tests/validation/fixtures/BatchNormalizationLayerFixture.h
index 7e072e7023..b7e32a6f37 100644
--- a/tests/validation/fixtures/BatchNormalizationLayerFixture.h
+++ b/tests/validation/fixtures/BatchNormalizationLayerFixture.h
@@ -52,13 +52,8 @@ public:
_use_beta = use_beta;
_use_gamma = use_gamma;
- if(data_layout == DataLayout::NHWC)
- {
- permute(shape0, PermutationVector(2U, 0U, 1U));
- }
-
_target = compute_target(shape0, shape1, epsilon, act_info, dt, data_layout, fractional_bits);
- _reference = compute_reference(shape0, shape1, epsilon, act_info, dt, data_layout, fractional_bits);
+ _reference = compute_reference(shape0, shape1, epsilon, act_info, dt, fractional_bits);
}
protected:
@@ -125,8 +120,13 @@ protected:
}
}
- TensorType compute_target(const TensorShape &shape0, const TensorShape &shape1, float epsilon, ActivationLayerInfo act_info, DataType dt, DataLayout data_layout, int fixed_point_position)
+ TensorType compute_target(TensorShape shape0, const TensorShape &shape1, float epsilon, ActivationLayerInfo act_info, DataType dt, DataLayout data_layout, int fixed_point_position)
{
+ if(data_layout == DataLayout::NHWC)
+ {
+ permute(shape0, PermutationVector(2U, 0U, 1U));
+ }
+
// Create tensors
TensorType src = create_tensor<TensorType>(shape0, dt, 1, fixed_point_position, QuantizationInfo(), data_layout);
TensorType dst = create_tensor<TensorType>(shape0, dt, 1, fixed_point_position, QuantizationInfo(), data_layout);
@@ -172,10 +172,10 @@ protected:
return dst;
}
- SimpleTensor<T> compute_reference(const TensorShape &shape0, const TensorShape &shape1, float epsilon, ActivationLayerInfo act_info, DataType dt, DataLayout data_layout, int fixed_point_position)
+ SimpleTensor<T> compute_reference(const TensorShape &shape0, const TensorShape &shape1, float epsilon, ActivationLayerInfo act_info, DataType dt, int fixed_point_position)
{
// Create reference
- SimpleTensor<T> ref_src{ shape0, dt, 1, fixed_point_position, QuantizationInfo(), data_layout };
+ SimpleTensor<T> ref_src{ shape0, dt, 1, fixed_point_position };
SimpleTensor<T> ref_mean{ shape1, dt, 1, fixed_point_position };
SimpleTensor<T> ref_var{ shape1, dt, 1, fixed_point_position };
SimpleTensor<T> ref_beta{ shape1, dt, 1, fixed_point_position };
diff --git a/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h b/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
index b7bca8dbf3..2f01f43d8b 100644
--- a/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
@@ -70,15 +70,8 @@ public:
weights_shape.set(2, out_shape.z());
const TensorShape biases_shape(weights_shape[2]);
- if(data_layout == DataLayout::NHWC)
- {
- permute(in_shape, PermutationVector(2U, 0U, 1U));
- permute(weights_shape, PermutationVector(2U, 0U, 1U));
- permute(out_shape, PermutationVector(2U, 0U, 1U));
- }
-
_target = compute_target(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info, depth_multiplier, data_type, bias_data_type, quantization_info, data_layout);
- _reference = compute_reference(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info, depth_multiplier, data_type, bias_data_type, quantization_info, data_layout);
+ _reference = compute_reference(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info, depth_multiplier, data_type, bias_data_type, quantization_info);
}
protected:
@@ -111,10 +104,16 @@ protected:
}
}
- TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &biases_shape, const TensorShape &output_shape, PadStrideInfo &pad_stride_info,
- unsigned int depth_multiplier,
+ TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, TensorShape biases_shape, TensorShape output_shape, PadStrideInfo &pad_stride_info, unsigned int depth_multiplier,
const DataType data_type, const DataType bias_data_type, const QuantizationInfo quantization_info, const DataLayout data_layout)
{
+ if(data_layout == DataLayout::NHWC)
+ {
+ permute(input_shape, PermutationVector(2U, 0U, 1U));
+ permute(weights_shape, PermutationVector(2U, 0U, 1U));
+ permute(output_shape, PermutationVector(2U, 0U, 1U));
+ }
+
// Create tensors
TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, 0, quantization_info, data_layout);
TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, 0, quantization_info, data_layout);
@@ -154,11 +153,11 @@ protected:
SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &weights_shape, const TensorShape &biases_shape, const TensorShape &out_shape, const PadStrideInfo &pad_stride_info,
unsigned int depth_multiplier,
- const DataType data_type, const DataType bias_data_type, const QuantizationInfo quantization_info, const DataLayout data_layout)
+ const DataType data_type, const DataType bias_data_type, const QuantizationInfo quantization_info)
{
- SimpleTensor<T> src{ in_shape, data_type, 1, 0, quantization_info, data_layout };
- SimpleTensor<T> weights{ weights_shape, data_type, 1, 0, quantization_info, data_layout };
- SimpleTensor<TBias> biases{ biases_shape, bias_data_type, 1, 0, quantization_info, data_layout };
+ SimpleTensor<T> src{ in_shape, data_type, 1, 0, quantization_info };
+ SimpleTensor<T> weights{ weights_shape, data_type, 1, 0, quantization_info };
+ SimpleTensor<TBias> biases{ biases_shape, bias_data_type, 1, 0, quantization_info };
fill(src, 0);
fill(weights, 1);
diff --git a/tests/validation/fixtures/DirectConvolutionLayerFixture.h b/tests/validation/fixtures/DirectConvolutionLayerFixture.h
index 9ea4061e53..38ddf33e24 100644
--- a/tests/validation/fixtures/DirectConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DirectConvolutionLayerFixture.h
@@ -67,22 +67,13 @@ public:
const PadStrideInfo info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);
const DataType bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type;
- if(data_layout == DataLayout::NHWC)
- {
- permute(input_shape, PermutationVector(2U, 0U, 1U));
- permute(weights_shape, PermutationVector(2U, 0U, 1U));
- }
-
TensorInfo input_info = TensorInfo(input_shape, 1, data_type, _fractional_bits);
TensorInfo weights_info = TensorInfo(weights_shape, 1, data_type, _fractional_bits);
- input_info.set_data_layout(data_layout);
- weights_info.set_data_layout(data_layout);
-
const TensorShape output_shape = compute_deep_convolution_shape(input_info, weights_info, info);
_target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info, data_layout);
- _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info, data_layout);
+ _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info);
}
template <typename...>
@@ -98,15 +89,8 @@ public:
const DataType bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type;
- if(data_layout == DataLayout::NHWC)
- {
- permute(input_shape, PermutationVector(2U, 0U, 1U));
- permute(weights_shape, PermutationVector(2U, 0U, 1U));
- permute(output_shape, PermutationVector(2U, 0U, 1U));
- }
-
_target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info, data_layout);
- _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info, data_layout);
+ _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, fractional_bits, quantization_info, act_info);
}
protected:
@@ -139,9 +123,16 @@ protected:
}
}
- TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
+ TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, const TensorShape &bias_shape, TensorShape output_shape, const PadStrideInfo &info,
DataType data_type, DataType bias_data_type, int fixed_point_position, QuantizationInfo quantization_info, ActivationLayerInfo act_info, const DataLayout &data_layout)
{
+ if(data_layout == DataLayout::NHWC)
+ {
+ permute(input_shape, PermutationVector(2U, 0U, 1U));
+ permute(weights_shape, PermutationVector(2U, 0U, 1U));
+ permute(output_shape, PermutationVector(2U, 0U, 1U));
+ }
+
// Create tensors
TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, fixed_point_position, quantization_info, data_layout);
TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, fixed_point_position, quantization_info, data_layout);
@@ -180,13 +171,11 @@ protected:
}
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, DataType bias_data_type, int fixed_point_position, QuantizationInfo quantization_info, ActivationLayerInfo act_info, const DataLayout &data_layout)
+ DataType data_type, DataType bias_data_type, int fixed_point_position, QuantizationInfo quantization_info, ActivationLayerInfo act_info)
{
- ARM_COMPUTE_ERROR_ON(data_layout == DataLayout::UNKNOWN);
-
// Create reference
- SimpleTensor<T> src{ input_shape, data_type, 1, fixed_point_position, quantization_info, data_layout };
- SimpleTensor<T> weights{ weights_shape, data_type, 1, fixed_point_position, quantization_info, data_layout };
+ SimpleTensor<T> src{ input_shape, data_type, 1, fixed_point_position, quantization_info };
+ SimpleTensor<T> weights{ weights_shape, data_type, 1, fixed_point_position, quantization_info };
SimpleTensor<TBias> bias{ bias_shape, bias_data_type, 1, fixed_point_position, quantization_info };
// Fill reference
@@ -194,23 +183,7 @@ protected:
fill(weights, 1);
fill(bias, 2);
- SimpleTensor<T> dst;
-
- // FIXME: move to reference once all functions that call reference::convolution_layer<>() support NHWC
- if(src.data_layout() == DataLayout::NHWC)
- {
- SimpleTensor<T> src_nchw = reference::permute<T>(src, PermutationVector(1U, 2U, 0U));
- SimpleTensor<T> weights_nchw = reference::permute<T>(weights, PermutationVector(1U, 2U, 0U));
-
- TensorShape output_shape_nchw{ output_shape };
- permute(output_shape_nchw, PermutationVector(1U, 2U, 0U));
-
- dst = reference::permute<T>(reference::convolution_layer<T>(src_nchw, weights_nchw, bias, output_shape_nchw, info), PermutationVector(2U, 0U, 1U));
- }
- else
- {
- dst = reference::convolution_layer<T>(src, weights, bias, output_shape, info);
- }
+ SimpleTensor<T> dst = reference::convolution_layer<T>(src, weights, bias, output_shape, info);
return (act_info.enabled()) ? reference::activation_layer<T>(dst, act_info) : dst;
}
diff --git a/tests/validation/fixtures/Im2ColFixture.h b/tests/validation/fixtures/Im2ColFixture.h
index b6e4cd0023..7ef3cdcdcd 100644
--- a/tests/validation/fixtures/Im2ColFixture.h
+++ b/tests/validation/fixtures/Im2ColFixture.h
@@ -83,7 +83,7 @@ protected:
{
// Create tensors
TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, 0, _quant_info, _data_layout);
- TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, 0, _quant_info, _data_layout);
+ TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, 0, _quant_info);
// Create and configure function
FunctionType im2col_func;
diff --git a/tests/validation/fixtures/PoolingLayerFixture.h b/tests/validation/fixtures/PoolingLayerFixture.h
index a40baf415a..27b033a06c 100644
--- a/tests/validation/fixtures/PoolingLayerFixture.h
+++ b/tests/validation/fixtures/PoolingLayerFixture.h
@@ -53,14 +53,8 @@ public:
_quantization_info = quantization_info;
_pool_info = pool_info;
- // Change shape in case of NHWC.
- if(data_layout == DataLayout::NHWC)
- {
- permute(shape, PermutationVector(2U, 0U, 1U));
- }
-
_target = compute_target(shape, pool_info, data_type, data_layout, fractional_bits, quantization_info);
- _reference = compute_reference(shape, pool_info, data_type, data_layout, fractional_bits, quantization_info);
+ _reference = compute_reference(shape, pool_info, data_type, fractional_bits, quantization_info);
}
protected:
@@ -84,9 +78,15 @@ protected:
}
}
- TensorType compute_target(const TensorShape &shape, PoolingLayerInfo info,
+ TensorType compute_target(TensorShape shape, PoolingLayerInfo info,
DataType data_type, DataLayout data_layout, int fixed_point_position, QuantizationInfo quantization_info)
{
+ // Change shape in case of NHWC.
+ if(data_layout == DataLayout::NHWC)
+ {
+ permute(shape, PermutationVector(2U, 0U, 1U));
+ }
+
// Create tensors
TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position, quantization_info, data_layout);
TensorType dst;
@@ -115,10 +115,10 @@ protected:
}
SimpleTensor<T> compute_reference(const TensorShape &shape, PoolingLayerInfo info,
- DataType data_type, DataLayout data_layout, int fixed_point_position, QuantizationInfo quantization_info)
+ DataType data_type, int fixed_point_position, QuantizationInfo quantization_info)
{
// Create reference
- SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position, quantization_info, data_layout };
+ SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position, quantization_info };
// Fill reference
fill(src);
diff --git a/tests/validation/reference/BatchNormalizationLayer.cpp b/tests/validation/reference/BatchNormalizationLayer.cpp
index ae309d9093..c8badacc79 100644
--- a/tests/validation/reference/BatchNormalizationLayer.cpp
+++ b/tests/validation/reference/BatchNormalizationLayer.cpp
@@ -27,7 +27,6 @@
#include "tests/validation/FixedPoint.h"
#include "tests/validation/Helpers.h"
-#include "tests/validation/reference/Permute.h"
namespace arm_compute
{
@@ -42,7 +41,6 @@ template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::
SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &mean, const SimpleTensor<T> &var, const SimpleTensor<T> &beta, const SimpleTensor<T> &gamma, float epsilon,
ActivationLayerInfo act_info, int fixed_point_position)
{
- ARM_COMPUTE_ERROR_ON_MSG(src.data_layout() == DataLayout::NHWC, "Unsupported NHWC format");
ARM_COMPUTE_UNUSED(act_info);
SimpleTensor<T> result(src.shape(), src.data_type());
@@ -88,14 +86,12 @@ SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const Simp
{
ARM_COMPUTE_UNUSED(fixed_point_position);
- const bool is_nhwc = src.data_layout() == DataLayout::NHWC;
- const SimpleTensor<T> perm_src = (is_nhwc) ? permute(src, PermutationVector(1U, 2U, 0U)) : src;
- SimpleTensor<T> result(perm_src.shape(), perm_src.data_type());
+ SimpleTensor<T> result(src.shape(), src.data_type());
- const auto cols = static_cast<int>(perm_src.shape()[0]);
- const auto rows = static_cast<int>(perm_src.shape()[1]);
- const auto depth = static_cast<int>(perm_src.shape()[2]);
- const int upper_dims = perm_src.shape().total_size() / (cols * rows * depth);
+ const auto cols = static_cast<int>(src.shape()[0]);
+ const auto rows = static_cast<int>(src.shape()[1]);
+ const auto depth = static_cast<int>(src.shape()[2]);
+ const int upper_dims = src.shape().total_size() / (cols * rows * depth);
for(int r = 0; r < upper_dims; ++r)
{
@@ -107,7 +103,7 @@ SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const Simp
{
const int pos = l + k * cols + i * rows * cols + r * cols * rows * depth;
const float denominator = sqrt(var[i] + epsilon);
- const float numerator = perm_src[pos] - mean[i];
+ const float numerator = src[pos] - mean[i];
const float x_bar = numerator / denominator;
result[pos] = beta[i] + x_bar * gamma[i];
}
@@ -120,10 +116,6 @@ SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const Simp
result = activation_layer(result, act_info);
}
- if(is_nhwc)
- {
- result = permute(result, PermutationVector(2U, 0U, 1U));
- }
return result;
}
template SimpleTensor<float> batch_normalization_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &mean, const SimpleTensor<float> &var, const SimpleTensor<float> &beta,
diff --git a/tests/validation/reference/DepthwiseConvolutionLayer.cpp b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
index 207e5fc45c..10c617e953 100644
--- a/tests/validation/reference/DepthwiseConvolutionLayer.cpp
+++ b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
@@ -24,7 +24,6 @@
#include "DepthwiseConvolutionLayer.h"
#include "ConvolutionLayer.h"
-#include "Permute.h"
#include "Utils.h"
#include "tests/validation/FixedPoint.h"
@@ -51,9 +50,11 @@ namespace reference
*
*/
template <typename T, typename TB>
-void depthwise_convolution_nchw(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, SimpleTensor<T> &dst, const PadStrideInfo &conv_info,
- unsigned int depth_multiplier)
+SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info,
+ unsigned int depth_multiplier)
{
+ SimpleTensor<T> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position() };
+
// Compute reference
const int filter_width = weights.shape().x();
const int filter_height = weights.shape().y();
@@ -113,11 +114,16 @@ void depthwise_convolution_nchw(const SimpleTensor<T> &src, const SimpleTensor<T
}
}
}
+
+ return dst;
}
-void depthwise_convolution_nchw(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &biases, SimpleTensor<uint8_t> &dst, const PadStrideInfo &conv_info,
- unsigned int depth_multiplier)
+template <>
+SimpleTensor<uint8_t> depthwise_convolution(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &biases, const TensorShape &dst_shape,
+ const PadStrideInfo &conv_info, unsigned int depth_multiplier)
{
+ SimpleTensor<uint8_t> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position(), src.quantization_info() };
+
// Create reference
const int input_offset = -src.quantization_info().offset;
const float input_scale = src.quantization_info().scale;
@@ -196,33 +202,10 @@ void depthwise_convolution_nchw(const SimpleTensor<uint8_t> &src, const SimpleTe
}
}
}
-}
-
-template <typename T, typename TB>
-SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info,
- unsigned int depth_multiplier)
-{
- SimpleTensor<T> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position(), src.quantization_info() };
-
- if(src.data_layout() == DataLayout::NHWC)
- {
- SimpleTensor<T> src_nchw = reference::permute<T>(src, PermutationVector(1U, 2U, 0U));
- SimpleTensor<T> weights_nchw = reference::permute<T>(weights, PermutationVector(1U, 2U, 0U));
- SimpleTensor<T> dst_nchw = reference::permute<T>(dst, PermutationVector(1U, 2U, 0U));
-
- depthwise_convolution_nchw(src_nchw, weights_nchw, biases, dst_nchw, conv_info, depth_multiplier);
-
- return reference::permute<T>(dst_nchw, PermutationVector(2U, 0U, 1U));
- }
-
- depthwise_convolution_nchw(src, weights, biases, dst, conv_info, depth_multiplier);
return dst;
}
-template SimpleTensor<uint8_t> depthwise_convolution(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &biases, const TensorShape &dst_shape,
- const PadStrideInfo &conv_info, unsigned int depth_multiplier);
-
template SimpleTensor<float> depthwise_convolution(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &biases, const TensorShape &dst_shape,
const PadStrideInfo &conv_info, unsigned int depth_multiplier);
diff --git a/tests/validation/reference/PoolingLayer.cpp b/tests/validation/reference/PoolingLayer.cpp
index f3f456b26e..69734545c9 100644
--- a/tests/validation/reference/PoolingLayer.cpp
+++ b/tests/validation/reference/PoolingLayer.cpp
@@ -23,7 +23,6 @@
*/
#include "PoolingLayer.h"
-#include "Permute.h"
#include "arm_compute/core/Types.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "tests/validation/FixedPoint.h"
@@ -39,11 +38,14 @@ namespace reference
{
using namespace arm_compute::misc::shape_calculator;
-template <typename T>
-SimpleTensor<T> pooling_layer_nchw(const SimpleTensor<T> &src, SimpleTensor<T> &dst, const PoolingLayerInfo &info)
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo &info)
{
ARM_COMPUTE_ERROR_ON(info.is_global_pooling() && (src.shape().x() != src.shape().y()));
+ // Create reference
+ SimpleTensor<T> dst{ compute_pool_shape(TensorInfo(src.shape(), 1, src.data_type(), src.fixed_point_position()), info), src.data_type(), 1, src.fixed_point_position() };
+
const int pool_size_x = info.is_global_pooling() ? src.shape().x() : info.pool_size().width;
const int pool_size_y = info.is_global_pooling() ? src.shape().y() : info.pool_size().height;
PoolingType type = info.pool_type();
@@ -171,10 +173,7 @@ SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo
bool exclude_padding = info.exclude_padding();
// Create reference
- TensorInfo src_info(src.shape(), 1, src.data_type(), src.fixed_point_position());
- src_info.set_data_layout(src.data_layout());
-
- SimpleTensor<T> dst{ compute_pool_shape(src_info, info), src.data_type(), 1, src.fixed_point_position() };
+ SimpleTensor<T> dst{ compute_pool_shape(TensorInfo(src.shape(), 1, src.data_type(), src.fixed_point_position()), info), src.data_type(), 1, src.fixed_point_position() };
const auto w_dst = static_cast<int>(dst.shape()[0]);
const auto h_dst = static_cast<int>(dst.shape()[1]);
@@ -284,29 +283,6 @@ SimpleTensor<uint8_t> pooling_layer<uint8_t>(const SimpleTensor<uint8_t> &src, c
return dst;
}
-template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
-SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, const PoolingLayerInfo &info)
-{
- TensorInfo src_info(src.shape(), 1, src.data_type(), src.fixed_point_position());
- src_info.set_data_layout(src.data_layout());
-
- SimpleTensor<T> dst{ compute_pool_shape(src_info, info), src.data_type(), 1, src.fixed_point_position() };
-
- if(src.data_layout() == DataLayout::NHWC)
- {
- SimpleTensor<T> src_nchw = reference::permute<T>(src, PermutationVector(1U, 2U, 0U));
- SimpleTensor<T> dst_nchw = reference::permute<T>(dst, PermutationVector(1U, 2U, 0U));
-
- pooling_layer_nchw<T>(src_nchw, dst_nchw, info);
-
- return reference::permute<T>(dst_nchw, PermutationVector(2U, 0U, 1U));
- }
- else
- {
- return pooling_layer_nchw<T>(src, dst, info);
- }
-}
-
template SimpleTensor<float> pooling_layer(const SimpleTensor<float> &src, const PoolingLayerInfo &info);
template SimpleTensor<half> pooling_layer(const SimpleTensor<half> &src, const PoolingLayerInfo &info);
template SimpleTensor<qint8_t> pooling_layer(const SimpleTensor<qint8_t> &src, const PoolingLayerInfo &info);