diff options
author | Gian Marco Iodice <gianmarco.iodice@arm.com> | 2022-11-17 11:03:39 +0000 |
---|---|---|
committer | Gian Marco Iodice <gianmarco.iodice@arm.com> | 2022-11-25 11:11:17 +0000 |
commit | 5d01681fe9aa8a04bd5431db9b2866b8d538dbae (patch) | |
tree | 61e0de777285662dbaf7e2e1e0aed003b77bded9 /tests | |
parent | e112ef1cc70bcdc52ded44350e61eb16d74559b3 (diff) | |
download | ComputeLibrary-5d01681fe9aa8a04bd5431db9b2866b8d538dbae.tar.gz |
Implement address precalculation for indirect conv2d - OpenCL
- Implement kernel (ClIndirectConv2dAddressPrecalculationKernel)
- Implement OpenCL kernel (indirect_convolution.cl)
- Add test
Resolves COMPMID-5708
Change-Id: If7408e37cbc6f9ad8506ff3334bc574e5d6763fb
Signed-off-by: Gian Marco Iodice <gianmarco.iodice@arm.com>
Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/8661
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Viet-Hoa Do <viet-hoa.do@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Benchmark: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'tests')
4 files changed, 355 insertions, 0 deletions
diff --git a/tests/validation/CL/IndirectConv2dAddressPrecalculation.cpp b/tests/validation/CL/IndirectConv2dAddressPrecalculation.cpp new file mode 100644 index 0000000000..67f70685d1 --- /dev/null +++ b/tests/validation/CL/IndirectConv2dAddressPrecalculation.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022 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/Types.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLTensorAllocator.h" +#include "src/gpu/cl/kernels/ClIndirectConv2dAddressPrecalculationKernel.h" +#include "tests/CL/CLAccessor.h" +#include "tests/CL/Helper.h" +#include "tests/PaddingCalculator.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/IndirectConv2dAddressPrecalculationFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +using namespace arm_compute::misc::shape_calculator; +using namespace arm_compute::opencl::kernels; + +using CLIndirectConv2dAddressPrecalculation = CLSynthetizeOperator<ClIndirectConv2dAddressPrecalculationKernel>; + +using CLIndirectConv2dAddressPrecalculationFixture = IndirectConv2dAddressPrecalculationValidationFixture<CLTensor, CLAccessor, CLIndirectConv2dAddressPrecalculation>; + +// *INDENT-OFF* +// clang-format off +/** Data types */ + +namespace +{ +const auto src_w_values = framework::dataset::make("src_w", {91}); +const auto src_h_values = framework::dataset::make("src_h", {103}); +const auto src_b_values = framework::dataset::make("src_b", {1, 2}); +const auto wei_w_values = framework::dataset::make("wei_w", {3, 5}); +const auto wei_h_values = framework::dataset::make("wei_h", {1, 6}); +const auto pad_values = framework::dataset::make("pad", {1, 2, 3}); +const auto stride_values = framework::dataset::make("stride", {1, 2}); +const auto m0_values = framework::dataset::make("M0", { 1, 2, 4, 5, 7 }); +} // namespace + +TEST_SUITE(CL) +TEST_SUITE(IndirectConv2dAddressPrecalculation) + +FIXTURE_DATA_TEST_CASE(RunSmall, CLIndirectConv2dAddressPrecalculationFixture, framework::DatasetMode::ALL, + combine(combine(combine(combine(combine(combine(combine(src_w_values, + src_h_values), + src_b_values), + wei_w_values), + wei_h_values), + pad_values), + stride_values), + m0_values)) +{ + // Validate output + validate(CLAccessor(_target), _reference); +} + +TEST_SUITE_END() // IndirectConv2dAddressPrecalculation +TEST_SUITE_END() // CL +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/fixtures/IndirectConv2dAddressPrecalculationFixture.h b/tests/validation/fixtures/IndirectConv2dAddressPrecalculationFixture.h new file mode 100644 index 0000000000..f595a8663d --- /dev/null +++ b/tests/validation/fixtures/IndirectConv2dAddressPrecalculationFixture.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2022 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_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_FIXTURE +#define ARM_COMPUTE_TEST_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "tests/Globals.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/reference/IndirectConv2dAddressPrecalculation.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +using namespace arm_compute::misc::shape_calculator; + +template <typename TensorType, typename AccessorType, typename OperatorType> +class IndirectConv2dAddressPrecalculationValidationFixture : public framework::Fixture +{ +public: + template <typename...> + void setup(unsigned int src_w, + unsigned int src_h, + unsigned int src_b, + unsigned int wei_w, + unsigned int wei_h, + unsigned int pad, + unsigned int stride, + unsigned int m0) + { + DirectConvComputeKernelInfo desc; + desc.m0 = m0; + desc.n0 = 1; // Not used by the kernel + desc.k0 = 1; // Not used by the kernel + desc.export_weights_to_cl_image = false; // Not used by the kernel + + const PadStrideInfo conv_info(stride, stride, pad, pad); + + const TensorShape shape_conv_src(23, // The input channels are not used by the kernel + src_w, + src_h, + src_b); + + const TensorShape shape_conv_wei(23, // The input channels are not used by the kernel + wei_w, + wei_h, + 23 // The output channels are not used by the kernel + ); + + // The result of the kernel does not change with the datatype. Hence, we can fix it to Fp16 for validation purposes + const DataType data_type = DataType::F16; + + _target = compute_target(shape_conv_src, shape_conv_wei, data_type, conv_info, desc); + _reference = compute_reference(shape_conv_src, shape_conv_wei, data_type, conv_info, desc); + } + +protected: + TensorType compute_target(TensorShape shape_conv_src, TensorShape shape_conv_wei, DataType data_type, const PadStrideInfo &conv_info, const DirectConvComputeKernelInfo &desc) + { + TensorInfo src_conv_info(shape_conv_src, 1, data_type, DataLayout::NHWC); + TensorInfo wei_conv_info(shape_conv_wei, 1, data_type, DataLayout::NHWC); + TensorType dst; + + // The output tensor will be auto-initialized within the function + + // Create and configure function + OperatorType func; + func.configure(&src_conv_info, &wei_conv_info, dst.info(), conv_info, desc); + + add_padding_x({ &dst }); + + // Allocate tensors + dst.allocator()->allocate(); + + // Compute GEMM LHS matrix reshape function + ITensorPack tensors = { { ACL_DST, &dst } }; + func.run(tensors); + + return dst; + } + + SimpleTensor<int32_t> compute_reference(TensorShape shape_conv_src, TensorShape shape_conv_wei, DataType data_type, const PadStrideInfo &conv_info, const DirectConvComputeKernelInfo &desc) + { + ARM_COMPUTE_UNUSED(data_type); + TensorShape shape_out = compute_indirect_buffer_shape(shape_conv_src, DataLayout::NHWC, shape_conv_wei, conv_info, desc); + TensorShape output_conv_shape = compute_deep_convolution_shape(shape_conv_src, DataLayout::NHWC, shape_conv_wei, conv_info); + + return reference::indirect_conv2d_addr_precalculation(shape_conv_src, shape_conv_wei, output_conv_shape, shape_out, conv_info); + } + + TensorType _target{}; + SimpleTensor<int32_t> _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_FIXTURE */
\ No newline at end of file diff --git a/tests/validation/reference/IndirectConv2dAddressPrecalculation.cpp b/tests/validation/reference/IndirectConv2dAddressPrecalculation.cpp new file mode 100644 index 0000000000..240dcb686c --- /dev/null +++ b/tests/validation/reference/IndirectConv2dAddressPrecalculation.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 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 "IndirectConv2dAddressPrecalculation.h" + +#include "arm_compute/core/Types.h" + +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +SimpleTensor<int32_t> indirect_conv2d_addr_precalculation(const TensorShape &shape_conv_src, const TensorShape &shape_conv_wei, const TensorShape &shape_conv_dst, const TensorShape &shape_dst, + const PadStrideInfo &conv_info) +{ + SimpleTensor<int32_t> out{ shape_dst, DataType::S32 }; + + constexpr unsigned int width_idx = 1; + constexpr unsigned int heigh_idx = 2; + + const int src_conv_width = static_cast<int32_t>(shape_conv_src[width_idx]); // NHWC + const int src_conv_height = static_cast<int32_t>(shape_conv_src[heigh_idx]); // NHWC + const int dst_conv_width = static_cast<int32_t>(shape_conv_dst[width_idx]); // NHWC + const int wei_conv_width = static_cast<int32_t>(shape_conv_wei[width_idx]); // NHWC + const int wei_conv_height = static_cast<int32_t>(shape_conv_wei[heigh_idx]); // NHWC + const int dst_width = static_cast<int32_t>(shape_dst[0]); + const int dst_height = static_cast<int32_t>(shape_dst[1]); + const int dst_batch = static_cast<int32_t>(shape_dst[2]); + const int ks = wei_conv_width * wei_conv_height; + const int stride_x = static_cast<int32_t>(conv_info.stride().first); + const int stride_y = static_cast<int32_t>(conv_info.stride().second); + const int pad_left = static_cast<int32_t>(conv_info.pad_left()); + const int pad_top = static_cast<int32_t>(conv_info.pad_top()); + + const int m0 = dst_width / ks; + + for(int z = 0; z < dst_batch; ++z) + { + for(int y = 0; y < dst_height; ++y) + { + const int mout = y * m0; + for(int ki = 0; ki < ks; ++ki) + { + const int xk = ki % wei_conv_width; + const int yk = ki / wei_conv_width; + for(int mi = 0; mi < m0; ++mi) + { + int xi = ((mout + mi) % dst_conv_width) * stride_x; + int yi = ((mout + mi) / dst_conv_width) * stride_y; + xi -= pad_left; + yi -= pad_top; + const int x_s = xi + xk; + const int y_s = yi + yk; + int my = x_s + y_s * src_conv_width; + my = my + z * src_conv_width * src_conv_height; + my = x_s >= 0 ? my : -1; + my = x_s < src_conv_width ? my : -1; + my = y_s >= 0 ? my : -1; + my = y_s < src_conv_height ? my : -1; + + const unsigned int addr_out = mi + ki * m0 + y * (dst_width) + z * (dst_width * dst_height); + + out[addr_out] = my; + } + } + } + } + + return out; +} +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute
\ No newline at end of file diff --git a/tests/validation/reference/IndirectConv2dAddressPrecalculation.h b/tests/validation/reference/IndirectConv2dAddressPrecalculation.h new file mode 100644 index 0000000000..f4a90dfd9f --- /dev/null +++ b/tests/validation/reference/IndirectConv2dAddressPrecalculation.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_H +#define ARM_COMPUTE_TEST_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_H + +#include "tests/SimpleTensor.h" +#include "tests/validation/Helpers.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +SimpleTensor<int32_t> indirect_conv2d_addr_precalculation(const TensorShape &shape_conv_src, const TensorShape &shape_conv_wei, const TensorShape &shape_conv_out, const TensorShape &shape_out, + const PadStrideInfo &conv_info); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_INDIRECT_CONV2D_ADDRESS_PRECALCULATION_H */
\ No newline at end of file |