From 1fab09f36bdd1e5473bb019cf9639f4a92b4daa1 Mon Sep 17 00:00:00 2001 From: Isabella Gottardi Date: Thu, 13 Jul 2017 15:55:57 +0100 Subject: COMPMID-424 Implemented reference implementation, new output valid region and validation tests (NEON and CL) for Scale Change-Id: I056fa3588b807a97cacf0b8afaec56e37ffc92af Reviewed-on: http://mpd-gerrit.cambridge.arm.com/83872 Tested-by: Kaizen Reviewed-by: Anthony Barbier --- tests/validation_new/CPP/DepthwiseConvolution.cpp | 2 +- .../CPP/DepthwiseSeparableConvolutionLayer.cpp | 2 +- tests/validation_new/CPP/Scale.cpp | 166 +++++++++++++++++++++ tests/validation_new/CPP/Scale.h | 43 ++++++ tests/validation_new/CPP/TensorElementAt.cpp | 70 --------- tests/validation_new/CPP/TensorElementAt.h | 44 ------ tests/validation_new/CPP/Utils.cpp | 93 ++++++++++++ tests/validation_new/CPP/Utils.h | 54 +++++++ 8 files changed, 358 insertions(+), 116 deletions(-) create mode 100644 tests/validation_new/CPP/Scale.cpp create mode 100644 tests/validation_new/CPP/Scale.h delete mode 100644 tests/validation_new/CPP/TensorElementAt.cpp delete mode 100644 tests/validation_new/CPP/TensorElementAt.h create mode 100644 tests/validation_new/CPP/Utils.cpp create mode 100644 tests/validation_new/CPP/Utils.h (limited to 'tests/validation_new/CPP') diff --git a/tests/validation_new/CPP/DepthwiseConvolution.cpp b/tests/validation_new/CPP/DepthwiseConvolution.cpp index be18ffb911..8c5cec596e 100644 --- a/tests/validation_new/CPP/DepthwiseConvolution.cpp +++ b/tests/validation_new/CPP/DepthwiseConvolution.cpp @@ -24,7 +24,7 @@ #include "DepthwiseConvolution.h" #include "ConvolutionLayer.h" -#include "TensorElementAt.h" +#include "Utils.h" #include "tests/validation_new/Helpers.h" #include "tests/validation_new/half.h" diff --git a/tests/validation_new/CPP/DepthwiseSeparableConvolutionLayer.cpp b/tests/validation_new/CPP/DepthwiseSeparableConvolutionLayer.cpp index 88584275cf..eba0a19189 100644 --- a/tests/validation_new/CPP/DepthwiseSeparableConvolutionLayer.cpp +++ b/tests/validation_new/CPP/DepthwiseSeparableConvolutionLayer.cpp @@ -26,7 +26,7 @@ #include "DepthwiseSeparableConvolutionLayer.h" #include "ConvolutionLayer.h" -#include "TensorElementAt.h" +#include "Utils.h" #include "tests/validation_new/Helpers.h" #include "tests/validation_new/half.h" diff --git a/tests/validation_new/CPP/Scale.cpp b/tests/validation_new/CPP/Scale.cpp new file mode 100644 index 0000000000..a1119f33b9 --- /dev/null +++ b/tests/validation_new/CPP/Scale.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "arm_compute/core/Helpers.h" + +#include "Scale.h" +#include "Utils.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor scale(const SimpleTensor &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value) +{ + TensorShape shape_scaled(in.shape()); + shape_scaled.set(0, in.shape()[0] * scale_x); + shape_scaled.set(1, in.shape()[1] * scale_y); + SimpleTensor out(shape_scaled, in.data_type()); + + // Compute the ratio between source width/height and destination width/height + const auto wr = static_cast(in.shape()[0]) / static_cast(out.shape()[0]); + const auto hr = static_cast(in.shape()[1]) / static_cast(out.shape()[1]); + + const auto width = static_cast(in.shape().x()); + const auto height = static_cast(in.shape().y()); + + // Area interpolation behaves as Nearest Neighbour in case of up-sampling + if(policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f) + { + policy = InterpolationPolicy::NEAREST_NEIGHBOR; + } + + for(int element_idx = 0, count = 0; element_idx < out.num_elements(); ++element_idx, ++count) + { + Coordinates id = index2coord(out.shape(), element_idx); + int idx = id.x(); + int idy = id.y(); + float x_src = (idx + 0.5f) * wr - 0.5f; + float y_src = (idy + 0.5f) * hr - 0.5f; + + switch(policy) + { + case InterpolationPolicy::NEAREST_NEIGHBOR: + { + //Calculate the source coords without -0.5f is equivalent to round the x_scr/y_src coords + x_src = (idx + 0.5f) * wr; + y_src = (idy + 0.5f) * hr; + id.set(0, x_src); + id.set(1, y_src); + + // If coordinates in range of tensor's width or height + if(x_src >= -1 || y_src >= -1 || x_src <= width || y_src <= height) + { + out[element_idx] = tensor_elem_at(in, id, border_mode, constant_border_value); + } + else + { + if(border_mode == BorderMode::CONSTANT) + { + out[element_idx] = constant_border_value; + } + else if(border_mode == BorderMode::REPLICATE) + { + id.set(0, clamp(static_cast(x_src), 0, width - 1)); + id.set(1, clamp(static_cast(y_src), 0, height - 1)); + out[element_idx] = in[coord2index(in.shape(), id)]; + } + } + break; + } + case InterpolationPolicy::BILINEAR: + { + id.set(0, std::floor(x_src)); + id.set(1, std::floor(y_src)); + if(x_src >= -1 || y_src >= -1 || x_src <= width || y_src <= height) + { + out[element_idx] = bilinear_policy(in, id, x_src, y_src, border_mode, constant_border_value); + } + else + { + if(border_mode == BorderMode::CONSTANT) + { + out[element_idx] = constant_border_value; + } + else if(border_mode == BorderMode::REPLICATE) + { + id.set(0, clamp(static_cast(x_src), 0, width - 1)); + id.set(1, clamp(static_cast(y_src), 0, height - 1)); + out[element_idx] = in[coord2index(in.shape(), id)]; + } + } + break; + } + case InterpolationPolicy::AREA: + { + int x_from = std::floor(idx * wr - 0.5f - x_src); + int y_from = std::floor(idy * hr - 0.5f - y_src); + int x_to = std::ceil((idx + 1) * wr - 0.5f - x_src); + int y_to = std::ceil((idy + 1) * hr - 0.5f - y_src); + const int xi = std::floor(x_src); + const int yi = std::floor(y_src); + + // Clamp position to borders + x_src = std::max(-1.f, std::min(x_src, static_cast(width))); + y_src = std::max(-1.f, std::min(y_src, static_cast(height))); + + // Clamp bounding box offsets to borders + x_from = ((x_src + x_from) < -1) ? -1 : x_from; + y_from = ((y_src + y_from) < -1) ? -1 : y_from; + x_to = ((x_src + x_to) > width) ? (width - x_src) : x_to; + y_to = ((y_src + y_to) > height) ? (height - y_src) : y_to; + ARM_COMPUTE_ERROR_ON((x_to - x_from + 1) == 0 || (y_to - y_from + 1) == 0); + + float sum = 0; + for(int j = yi + y_from, je = yi + y_to; j <= je; ++j) + { + for(int i = xi + x_from, ie = xi + x_to; i <= ie; ++i) + { + id.set(0, static_cast(i)); + id.set(1, static_cast(j)); + sum += tensor_elem_at(in, id, border_mode, constant_border_value); + } + } + out[element_idx] = sum / ((x_to - x_from + 1) * (y_to - y_from + 1)); + + break; + } + default: + ARM_COMPUTE_ERROR("Unsupported interpolation mode"); + } + } + + return out; +} + +template SimpleTensor scale(const SimpleTensor &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute \ No newline at end of file diff --git a/tests/validation_new/CPP/Scale.h b/tests/validation_new/CPP/Scale.h new file mode 100644 index 0000000000..b882915946 --- /dev/null +++ b/tests/validation_new/CPP/Scale.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_TEST_SCALE_H__ +#define __ARM_COMPUTE_TEST_SCALE_H__ + +#include "tests/SimpleTensor.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor scale(const SimpleTensor &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value = 0); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_SCALE_H__ */ diff --git a/tests/validation_new/CPP/TensorElementAt.cpp b/tests/validation_new/CPP/TensorElementAt.cpp deleted file mode 100644 index ca4cca9650..0000000000 --- a/tests/validation_new/CPP/TensorElementAt.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017 ARM Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "TensorElementAt.h" - -#include "tests/validation_new/Helpers.h" -#include "tests/validation_new/half.h" - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace reference -{ -// Return a tensor element at a specified coordinate with different border modes -template -T tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, T constant_border_value) -{ - const int x = coord.x(); - const int y = coord.y(); - const auto width = static_cast(in.shape().x()); - const auto height = static_cast(in.shape().y()); - - // If coordinates beyond range of tensor's width or height - if(x < 0 || y < 0 || x >= width || y >= height) - { - if(border_mode == BorderMode::REPLICATE) - { - coord.set(0, std::max(0, std::min(x, width - 1))); - coord.set(1, std::max(0, std::min(y, height - 1))); - - return in[coord2index(in.shape(), coord)]; - } - else - { - return constant_border_value; - } - } - else - { - return in[coord2index(in.shape(), coord)]; - } -} -template float tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, float constant_border_value); -} // namespace reference -} // namespace validation -} // namespace test -} // namespace arm_compute diff --git a/tests/validation_new/CPP/TensorElementAt.h b/tests/validation_new/CPP/TensorElementAt.h deleted file mode 100644 index d0d68ab6af..0000000000 --- a/tests/validation_new/CPP/TensorElementAt.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017 ARM Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef __ARM_COMPUTE_TEST_TENSOR_ELEMENT_AT_H__ -#define __ARM_COMPUTE_TEST_TENSOR_ELEMENT_AT_H__ - -#include "tests/SimpleTensor.h" -#include "tests/validation_new/Helpers.h" - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace reference -{ -template -T tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, T constant_border_value); -} // namespace reference -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_TENSOR_ELEMENT_AT_H__ */ diff --git a/tests/validation_new/CPP/Utils.cpp b/tests/validation_new/CPP/Utils.cpp new file mode 100644 index 0000000000..c89807b69a --- /dev/null +++ b/tests/validation_new/CPP/Utils.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "Utils.h" + +#include "tests/validation_new/Helpers.h" +#include "tests/validation_new/half.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +// Return a tensor element at a specified coordinate with different border modes +template +T tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, T constant_border_value) +{ + const int x = coord.x(); + const int y = coord.y(); + const auto width = static_cast(in.shape().x()); + const auto height = static_cast(in.shape().y()); + + // If coordinates beyond range of tensor's width or height + if(x < 0 || y < 0 || x >= width || y >= height) + { + if(border_mode == BorderMode::REPLICATE) + { + coord.set(0, std::max(0, std::min(x, width - 1))); + coord.set(1, std::max(0, std::min(y, height - 1))); + } + else + { + return constant_border_value; + } + } + return in[coord2index(in.shape(), coord)]; +} +template float tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, float constant_border_value); +template uint8_t tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, uint8_t constant_border_value); + +// Return the bilinear value at a specified coordinate with different border modes +template +T bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value) +{ + int idx = std::floor(xn); + int idy = std::floor(yn); + + const float dx = xn - idx; + const float dy = yn - idy; + const float dx_1 = 1.0f - dx; + const float dy_1 = 1.0f - dy; + + id.set(0, idx); + id.set(1, idy); + const T tl = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx + 1); + id.set(1, idy); + const T tr = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx); + id.set(1, idy + 1); + const T bl = tensor_elem_at(in, id, border_mode, constant_border_value); + id.set(0, idx + 1); + id.set(1, idy + 1); + const T br = tensor_elem_at(in, id, border_mode, constant_border_value); + + return tl * (dx_1 * dy_1) + tr * (dx * dy_1) + bl * (dx_1 * dy) + br * (dx * dy); +} +template uint8_t bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value); + +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation_new/CPP/Utils.h b/tests/validation_new/CPP/Utils.h new file mode 100644 index 0000000000..4e3deb4d86 --- /dev/null +++ b/tests/validation_new/CPP/Utils.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ +#define __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ + +#include "arm_compute/core/Types.h" +#include "tests/Globals.h" +#include "tests/ILutAccessor.h" +#include "tests/Types.h" +#include "tests/validation/ValidationUserConfiguration.h" +#include "tests/validation/half.h" + +#include +#include +#include +#include +#include + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template +T tensor_elem_at(const SimpleTensor &in, Coordinates coord, BorderMode border_mode, T constant_border_value); + +template +T bilinear_policy(const SimpleTensor &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value); +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ */ -- cgit v1.2.1