aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGian Marco Iodice <gianmarco.iodice@arm.com>2018-12-06 17:13:09 +0000
committerGian Marco Iodice <gianmarco.iodice@arm.com>2018-12-10 15:58:54 +0000
commit5ba5e0938e68d4f90f5545a81066d56f022b376a (patch)
treed828f8b3fd52e6d5b8f732a7ec41f832f0b921d8 /tests
parent1d7cbb99d2a34abd15f3b6c2e017115736cd90cc (diff)
downloadComputeLibrary-5ba5e0938e68d4f90f5545a81066d56f022b376a.tar.gz
COMPMID-1774: Implement CLGEMMReshapeLHSMatrixKernel to reshape the LHS matrix of GEMM/GEMMLowp
Change-Id: I8c5fd4c8bcdffda1522c83158981ed92baa045f4 Reviewed-on: https://review.mlplatform.org/364 Reviewed-by: Michele Di Giorgio <michele.digiorgio@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/CL/Helper.h44
-rw-r--r--tests/datasets/ShapeDatasets.h56
-rw-r--r--tests/validation/CL/GEMMReshapeLHSMatrix.cpp335
-rw-r--r--tests/validation/Helpers.cpp8
-rw-r--r--tests/validation/fixtures/GEMMReshapeLHSMatrixFixture.h137
-rw-r--r--tests/validation/reference/GEMMReshapeLHSMatrix.cpp111
-rw-r--r--tests/validation/reference/GEMMReshapeLHSMatrix.h44
7 files changed, 734 insertions, 1 deletions
diff --git a/tests/CL/Helper.h b/tests/CL/Helper.h
index 32f9ca00e3..88e716726a 100644
--- a/tests/CL/Helper.h
+++ b/tests/CL/Helper.h
@@ -24,7 +24,13 @@
#ifndef __ARM_COMPUTE_TEST_CL_HELPER_H__
#define __ARM_COMPUTE_TEST_CL_HELPER_H__
+#include "arm_compute/core/CL/ICLKernel.h"
+#include "arm_compute/core/CL/kernels/CLFillBorderKernel.h"
+#include "arm_compute/core/CL/kernels/CLMemsetKernel.h"
+
+#include "arm_compute/runtime/CL/CLScheduler.h"
#include "arm_compute/runtime/CL/ICLSimpleFunction.h"
+#include "arm_compute/runtime/IFunction.h"
#include "support/ToolchainSupport.h"
namespace arm_compute
@@ -77,6 +83,44 @@ public:
_border_handler.configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue(0));
}
};
+
+/** As above but this also initializes to zero the input tensor */
+template <typename K, int bordersize>
+class CLSynthetizeFunctionInitOutputWithZeroAndWithZeroConstantBorder : public IFunction
+{
+public:
+ /** Configure the kernel.
+ *
+ * @param[in] first First input argument.
+ * @param[in] second Second input argument.
+ * @param[in] args Rest of the configuration arguments.
+ */
+ template <typename T, typename... Args>
+ void configure(T first, T second, Args &&... args)
+ {
+ auto k = arm_compute::support::cpp14::make_unique<K>();
+ k->set_target(CLScheduler::get().target());
+ k->configure(first, second, std::forward<Args>(args)...);
+ _kernel = std::move(k);
+ _border_handler.configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue(0));
+ _memset_kernel.configure(second, PixelValue(0));
+ }
+
+ // Inherited method overridden:
+ void run() override final
+ {
+ ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
+
+ CLScheduler::get().enqueue(_memset_kernel, false);
+ CLScheduler::get().enqueue(_border_handler, false);
+ CLScheduler::get().enqueue(*_kernel);
+ }
+
+private:
+ CLMemsetKernel _memset_kernel{}; /**< Kernel to initialize the tensor */
+ CLFillBorderKernel _border_handler{}; /**< Kernel to handle borders */
+ std::unique_ptr<ICLKernel> _kernel{}; /**< Kernel to run */
+};
} // namespace test
} // namespace arm_compute
#endif /* __ARM_COMPUTE_TEST_CL_HELPER_H__ */
diff --git a/tests/datasets/ShapeDatasets.h b/tests/datasets/ShapeDatasets.h
index f7e7ae26b9..875f7e8ea1 100644
--- a/tests/datasets/ShapeDatasets.h
+++ b/tests/datasets/ShapeDatasets.h
@@ -892,6 +892,62 @@ public:
{
}
};
+
+/** Data set containing small tensor shapes to be used with the GEMM reshaping kernel */
+class SmallGEMMReshape2DShapes final : public ShapeDataset
+{
+public:
+ SmallGEMMReshape2DShapes()
+ : ShapeDataset("Shape",
+ {
+ TensorShape{ 63U, 72U },
+ })
+ {
+ }
+};
+
+/** Data set containing small tensor shapes to be used with the GEMM reshaping kernel when the input has to be reinterpreted as 3D */
+class SmallGEMMReshape3DShapes final : public ShapeDataset
+{
+public:
+ SmallGEMMReshape3DShapes()
+ : ShapeDataset("Shape",
+ {
+ TensorShape{ 63U, 9U, 8U },
+ })
+ {
+ }
+};
+
+/** Data set containing large tensor shapes to be used with the GEMM reshaping kernel */
+class LargeGEMMReshape2DShapes final : public ShapeDataset
+{
+public:
+ LargeGEMMReshape2DShapes()
+ : ShapeDataset("Shape",
+ {
+ TensorShape{ 16U, 27U },
+ TensorShape{ 533U, 171U },
+ TensorShape{ 345U, 612U }
+ })
+ {
+ }
+};
+
+/** Data set containing large tensor shapes to be used with the GEMM reshaping kernel when the input has to be reinterpreted as 3D */
+class LargeGEMMReshape3DShapes final : public ShapeDataset
+{
+public:
+ LargeGEMMReshape3DShapes()
+ : ShapeDataset("Shape",
+ {
+ TensorShape{ 16U, 3U, 9U },
+ TensorShape{ 533U, 19U, 9U },
+ TensorShape{ 345U, 34U, 18U }
+ })
+ {
+ }
+};
} // namespace datasets
} // namespace test
} // namespace arm_compute
diff --git a/tests/validation/CL/GEMMReshapeLHSMatrix.cpp b/tests/validation/CL/GEMMReshapeLHSMatrix.cpp
new file mode 100644
index 0000000000..ea6589df22
--- /dev/null
+++ b/tests/validation/CL/GEMMReshapeLHSMatrix.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2018 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/CL/kernels/CLGEMMReshapeLHSMatrixKernel.h"
+#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 "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/GEMMReshapeLHSMatrixFixture.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace
+{
+// *INDENT-OFF*
+// clang-format off
+/** Data types */
+const auto data_types = framework::dataset::make("DataType", { DataType::QASYMM8, DataType::F16, DataType::F32 });
+
+/** Batch size values to test */
+const auto b_values = framework::dataset::make("batchsize", 1, 3);
+
+/** M0 values to test */
+const auto m0_values = framework::dataset::make("M0", 2, 9);
+
+/** K0 values to test */
+const auto k0_values = framework::dataset::make("K0", { 2, 4, 8, 16 });
+
+/** V0 values to test */
+const auto v0_values = framework::dataset::make("V0", 1, 4);
+
+/** Interleave values to test */
+const auto i_values = framework::dataset::make("interleave", { true, false });
+
+/** Transpose values to test */
+const auto t_values = framework::dataset::make("transpose", { false });
+} // namespace
+
+using namespace arm_compute::misc::shape_calculator;
+
+// Initialize the output tensor with zero and fill the border with zero
+using CLGEMMReshapeLHSMatrix = CLSynthetizeFunctionInitOutputWithZeroAndWithZeroConstantBorder<CLGEMMReshapeLHSMatrixKernel, 16>;
+
+template <typename T>
+using CLGEMMReshapeLHSMatrixFixture = GEMMReshapeLHSMatrixValidationFixture<CLTensor, CLAccessor, CLGEMMReshapeLHSMatrix, T, false>;
+
+// Fixture to use when the input has to be reinterpreted as 3D
+template <typename T>
+using CLGEMMReshapeLHSMatrix3DFixture = GEMMReshapeLHSMatrixValidationFixture<CLTensor, CLAccessor, CLGEMMReshapeLHSMatrix, T, true>;
+
+TEST_SUITE(CL)
+TEST_SUITE(GEMMReshapeLHSMatrix)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape2DShapes(),
+ b_values),
+ data_types),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values),
+shape_in, b_value, data_type, m0_value, k0_value, v0_value, i_value, t_value)
+{
+ GEMMLHSMatrixInfo lhs_info;
+ lhs_info.m0 = m0_value;
+ lhs_info.k0 = k0_value;
+ lhs_info.v0 = v0_value;
+ lhs_info.interleave = i_value;
+ lhs_info.transpose = t_value;
+
+ const TensorShape shape_src(shape_in[0], shape_in[1], b_value);
+ const TensorShape shape_dst = compute_lhs_reshaped_shape(TensorInfo(shape_src, 1, data_type), lhs_info, false);
+
+ // Create tensors
+ CLTensor src = create_tensor<CLTensor>(shape_src, data_type);
+ CLTensor dst = create_tensor<CLTensor>(shape_dst, data_type);
+
+ ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Create and configure function
+ CLGEMMReshapeLHSMatrixKernel reshape_lhs;
+ reshape_lhs.configure(&src, &dst, lhs_info, false);
+}
+
+TEST_SUITE(S32)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrixFixture<int>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S32)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrixFixture<int>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S32)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S32
+
+TEST_SUITE(S16)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrixFixture<short>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S16)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrixFixture<short>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S16)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S16
+
+TEST_SUITE(S8)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrixFixture<char>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S8)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrixFixture<char>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape2DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S8)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S8
+
+TEST_SUITE(REINTERPRET_INPUT_AS_3D)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape3DShapes(),
+ b_values),
+ data_types),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values),
+shape_in, b_value, data_type, m0_value, k0_value, v0_value, i_value, t_value)
+{
+ GEMMLHSMatrixInfo lhs_info;
+ lhs_info.m0 = m0_value;
+ lhs_info.k0 = k0_value;
+ lhs_info.v0 = v0_value;
+ lhs_info.interleave = i_value;
+ lhs_info.transpose = t_value;
+
+ const TensorShape shape_src(shape_in[0], shape_in[1], shape_in[2], b_value);
+ const TensorShape shape_dst = compute_lhs_reshaped_shape(TensorInfo(shape_src, 1, data_type), lhs_info, true);
+
+ // Create tensors
+ CLTensor src = create_tensor<CLTensor>(shape_src, data_type);
+ CLTensor dst = create_tensor<CLTensor>(shape_dst, data_type);
+
+ ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Create and configure function
+ CLGEMMReshapeLHSMatrixKernel reshape_lhs;
+ reshape_lhs.configure(&src, &dst, lhs_info, true);
+}
+
+TEST_SUITE(S32)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrix3DFixture<int>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S32)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrix3DFixture<int>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S32)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S32
+
+TEST_SUITE(S16)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrix3DFixture<short>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S16)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrix3DFixture<short>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S16)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S16
+
+TEST_SUITE(S8)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMReshapeLHSMatrix3DFixture<char>, framework::DatasetMode::ALL,
+ combine(combine(combine(combine(combine(combine(combine(datasets::SmallGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S8)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMReshapeLHSMatrix3DFixture<char>, framework::DatasetMode::NIGHTLY,
+ combine(combine(combine(combine(combine(combine(combine(datasets::LargeGEMMReshape3DShapes(),
+ b_values),
+ framework::dataset::make("DataType", DataType::S8)),
+ m0_values),
+ k0_values),
+ v0_values),
+ i_values),
+ t_values))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference);
+}
+TEST_SUITE_END() // S8
+TEST_SUITE_END() // REINTERPRET_INPUT_AS_3D
+TEST_SUITE_END() // GEMMReshapeLHSMatrix
+TEST_SUITE_END() // CL
+} // namespace validation
+} // namespace test
+} // namespace arm_compute \ No newline at end of file
diff --git a/tests/validation/Helpers.cpp b/tests/validation/Helpers.cpp
index eab6d5629f..11c454ea67 100644
--- a/tests/validation/Helpers.cpp
+++ b/tests/validation/Helpers.cpp
@@ -207,7 +207,7 @@ void transpose_matrix(const SimpleTensor<T> &in, SimpleTensor<T> &out)
{
for(int x = 0; x < width; ++x)
{
- const float val = in[x + y * width];
+ const T val = in[x + y * width];
out[x * height + y] = val;
}
@@ -313,10 +313,16 @@ std::pair<int, int> get_quantized_bounds(const QuantizationInfo &quant_info, flo
template void get_tile(const SimpleTensor<float> &in, SimpleTensor<float> &roi, const Coordinates &coord);
template void get_tile(const SimpleTensor<half> &in, SimpleTensor<half> &roi, const Coordinates &coord);
+template void get_tile(const SimpleTensor<int> &in, SimpleTensor<int> &roi, const Coordinates &coord);
+template void get_tile(const SimpleTensor<short> &in, SimpleTensor<short> &roi, const Coordinates &coord);
+template void get_tile(const SimpleTensor<char> &in, SimpleTensor<char> &roi, const Coordinates &coord);
template void zeros(SimpleTensor<float> &in, const Coordinates &anchor, const TensorShape &shape);
template void zeros(SimpleTensor<half> &in, const Coordinates &anchor, const TensorShape &shape);
template void transpose_matrix(const SimpleTensor<float> &in, SimpleTensor<float> &out);
template void transpose_matrix(const SimpleTensor<half> &in, SimpleTensor<half> &out);
+template void transpose_matrix(const SimpleTensor<int> &in, SimpleTensor<int> &out);
+template void transpose_matrix(const SimpleTensor<short> &in, SimpleTensor<short> &out);
+template void transpose_matrix(const SimpleTensor<char> &in, SimpleTensor<char> &out);
template void matrix_multiply(const SimpleTensor<float> &a, const SimpleTensor<float> &b, SimpleTensor<float> &out);
template void matrix_multiply(const SimpleTensor<half> &a, const SimpleTensor<half> &b, SimpleTensor<half> &out);
diff --git a/tests/validation/fixtures/GEMMReshapeLHSMatrixFixture.h b/tests/validation/fixtures/GEMMReshapeLHSMatrixFixture.h
new file mode 100644
index 0000000000..3a5ab7c5e1
--- /dev/null
+++ b/tests/validation/fixtures/GEMMReshapeLHSMatrixFixture.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018 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_GEMMRESHAPELHSMATRIX_FIXTURE
+#define ARM_COMPUTE_TEST_GEMMRESHAPELHSMATRIX_FIXTURE
+
+#include "arm_compute/core/TensorShape.h"
+#include "arm_compute/core/Types.h"
+#include "arm_compute/core/utils/misc/ShapeCalculator.h"
+#include "tests/AssetsLibrary.h"
+#include "tests/Globals.h"
+#include "tests/IAccessor.h"
+#include "tests/framework/Asserts.h"
+#include "tests/framework/Fixture.h"
+#include "tests/validation/Helpers.h"
+#include "tests/validation/reference/GEMMReshapeLHSMatrix.h"
+#include "tests/validation/reference/Utils.h"
+
+#include <random>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+using namespace arm_compute::misc::shape_calculator;
+
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool reinterpret_input_as_3d = false>
+class GEMMReshapeLHSMatrixValidationFixture : public framework::Fixture
+{
+public:
+ template <typename...>
+ void setup(TensorShape shape_in, unsigned int batch_size, DataType data_type, unsigned int m0, unsigned int k0, unsigned int v0, bool interleave, bool transpose)
+ {
+ GEMMLHSMatrixInfo lhs_info;
+ lhs_info.m0 = m0;
+ lhs_info.k0 = k0;
+ lhs_info.v0 = v0;
+ lhs_info.interleave = interleave;
+ lhs_info.transpose = transpose;
+
+ // Set the tensor shape
+ const TensorShape shape_src(shape_in[0],
+ shape_in[1],
+ reinterpret_input_as_3d ? shape_in[2] : batch_size,
+ reinterpret_input_as_3d ? batch_size : 1);
+
+ _target = compute_target(shape_src, data_type, lhs_info);
+ _reference = compute_reference(shape_src, data_type, lhs_info);
+ }
+
+protected:
+ template <typename U>
+ void fill(U &&tensor)
+ {
+ library->fill_tensor_uniform(tensor, 0);
+ }
+
+ TensorType compute_target(TensorShape input_shape, DataType data_type, const GEMMLHSMatrixInfo &lhs_info)
+ {
+ // Create tensors
+ TensorType src = create_tensor<TensorType>(input_shape, data_type, 1);
+ TensorType dst;
+
+ // The output tensor will be auto-initialized within the function
+
+ // Create and configure function
+ FunctionType gemm_lhs_reshape;
+ gemm_lhs_reshape.configure(&src, &dst, lhs_info, reinterpret_input_as_3d);
+
+ ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Allocate tensors
+ src.allocator()->allocate();
+ dst.allocator()->allocate();
+
+ ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Fill tensors
+ fill(AccessorType(src));
+
+ // Compute GEMM LHS matrix reshape function
+ gemm_lhs_reshape.run();
+
+ return dst;
+ }
+
+ SimpleTensor<T> compute_reference(const TensorShape &input_shape, DataType data_type, const GEMMLHSMatrixInfo &lhs_info)
+ {
+ TensorShape src_shape = input_shape;
+
+ // If the input has to be reinterpreted as 3D, collapse the second dimension with the 3rd
+ if(reinterpret_input_as_3d)
+ {
+ src_shape.collapse(2U, 1U);
+ }
+
+ // Create reference
+ SimpleTensor<T> src{ src_shape, data_type, 1 };
+
+ // Fill reference
+ fill(src);
+
+ TensorShape output_shape = compute_lhs_reshaped_shape(TensorInfo(input_shape, 1, data_type), lhs_info, reinterpret_input_as_3d);
+
+ return reference::gemm_reshape_lhs_matrix<T>(src, output_shape, lhs_info);
+ }
+
+ TensorType _target{};
+ SimpleTensor<T> _reference{};
+};
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_GEMMRESHAPELHSMATRIX_FIXTURE */ \ No newline at end of file
diff --git a/tests/validation/reference/GEMMReshapeLHSMatrix.cpp b/tests/validation/reference/GEMMReshapeLHSMatrix.cpp
new file mode 100644
index 0000000000..431d65696e
--- /dev/null
+++ b/tests/validation/reference/GEMMReshapeLHSMatrix.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018 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 "GEMMReshapeLHSMatrix.h"
+
+#include "arm_compute/core/Types.h"
+
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gemm_reshape_lhs_matrix(const SimpleTensor<T> &in, const TensorShape &output_shape, const GEMMLHSMatrixInfo &lhs_info)
+{
+ ARM_COMPUTE_ERROR_ON(in.shape().num_dimensions() > 3);
+
+ SimpleTensor<T> out{ output_shape, in.data_type() };
+
+ // Initialize the output tensor with zero
+ std::memset(&out[0], 0, out.num_elements() * sizeof(T));
+
+ const unsigned int K = in.shape()[0];
+ const unsigned int M = in.shape()[1];
+ const unsigned int B = in.shape()[2];
+
+ const unsigned int num_tiles_x = std::ceil(K / static_cast<float>(lhs_info.k0));
+ const unsigned int num_tiles_y = std::ceil(M / static_cast<float>(lhs_info.m0));
+
+ const TensorShape tile_dims(lhs_info.k0, lhs_info.m0);
+ const TensorShape tile_dims_transposed(lhs_info.m0, lhs_info.k0);
+
+ // Simple tensor for the input tile
+ SimpleTensor<T> src_tile{ tile_dims, in.data_type() };
+
+ // Simple tensor for the input tile
+ SimpleTensor<T> src_tile_transposed{ tile_dims_transposed, in.data_type() };
+
+ // Simple tensor to use when storing the values
+ SimpleTensor<T> *tile_to_use = lhs_info.transpose ? &src_tile_transposed : &src_tile;
+
+ const unsigned int offset_output_x = lhs_info.interleave ? tile_to_use->shape()[0] : tile_to_use->shape()[0] * tile_to_use->shape()[1];
+ const unsigned int step_output_x = lhs_info.interleave ? tile_to_use->shape()[0] * lhs_info.v0 : tile_to_use->shape()[0];
+
+ for(unsigned int z = 0; z < B; ++z)
+ {
+ for(unsigned int y = 0; y < num_tiles_y; ++y)
+ {
+ for(unsigned int x = 0; x < num_tiles_x; ++x)
+ {
+ // Get the tile from the input tensor
+ get_tile<T>(in, src_tile, Coordinates(x * lhs_info.k0, y * lhs_info.m0, z, 0));
+
+ if(lhs_info.transpose)
+ {
+ // Transpose matrix
+ transpose_matrix<T>(src_tile, src_tile_transposed);
+ }
+
+ // Store
+ const unsigned int offset_output = (x * lhs_info.k0 * lhs_info.m0 * lhs_info.v0) + ((y % lhs_info.v0) * offset_output_x) + ((y / lhs_info.v0) * out.shape()[0]) + (z * out.shape()[0] * out.shape()[1]);
+
+ for(unsigned int i = 0; i < tile_to_use->shape()[1]; ++i)
+ {
+ const unsigned int offset_tile = i * tile_to_use->shape()[0];
+
+ // Copy per row
+ std::copy(&(*tile_to_use)[offset_tile], &(*tile_to_use)[offset_tile + tile_to_use->shape()[0]], &out[offset_output + i * step_output_x]);
+ }
+ }
+ }
+ }
+
+ return out;
+}
+template SimpleTensor<int> gemm_reshape_lhs_matrix(const SimpleTensor<int> &in, const TensorShape &output_shape, const GEMMLHSMatrixInfo &lhs_info);
+template SimpleTensor<short> gemm_reshape_lhs_matrix(const SimpleTensor<short> &in, const TensorShape &output_shape, const GEMMLHSMatrixInfo &lhs_info);
+template SimpleTensor<char> gemm_reshape_lhs_matrix(const SimpleTensor<char> &in, const TensorShape &output_shape, const GEMMLHSMatrixInfo &lhs_info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute \ No newline at end of file
diff --git a/tests/validation/reference/GEMMReshapeLHSMatrix.h b/tests/validation/reference/GEMMReshapeLHSMatrix.h
new file mode 100644
index 0000000000..c0328dbd51
--- /dev/null
+++ b/tests/validation/reference/GEMMReshapeLHSMatrix.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 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_GEMMRESHAPELHSMATRIX_H__
+#define __ARM_COMPUTE_TEST_GEMMRESHAPELHSMATRIX_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gemm_reshape_lhs_matrix(const SimpleTensor<T> &in, const TensorShape &output_shape, const GEMMLHSMatrixInfo &lhs_info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GEMMRESHAPELHSMATRIX_H__ */ \ No newline at end of file