blob: b47f8bc9245478ffb0520ffdde08f1f22e59a08c [file] [log] [blame]
Gunes Bayir8918b232023-03-17 13:52:21 +00001/*
2 * Copyright (c) 2023 Arm Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "arm_compute/runtime/CL/CLTensor.h"
Jakub Sujak1ed6a142023-04-13 21:14:42 +010026#include "src/gpu/cl/kernels/ClMatMulNativeKernel.h"
Gunes Bayir8918b232023-03-17 13:52:21 +000027#include "tests/datasets/LargeMatMulDataset.h"
28#include "tests/datasets/SmallMatMulDataset.h"
29#include "tests/framework/Macros.h"
30#include "tests/framework/datasets/Datasets.h"
31#include "tests/validation/Validation.h"
32#include "tests/validation/fixtures/MatMulKernelFixture.h"
33#include "tests/validation/reference/Permute.h"
34
35#include <tuple>
36
37namespace arm_compute
38{
39namespace test
40{
41namespace validation
42{
43namespace
44{
45RelativeTolerance<float> tolerance_f32(0.001f); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */
46constexpr float abs_tolerance_f32(
47 0.0001f); /**< Absolute tolerance value for comparing reference's output against implementation's output for floating point data types in case using relative tolerance fails because of small values */
48constexpr float abs_tolerance_f16(
49 0.001f); /**< Absolute tolerance value for comparing reference's output against implementation's output for fp16 data types in case using relative tolerance fails because of small values */
50RelativeTolerance<half_float::half> tolerance_f16(half(0.01)); /**< Tolerance value for comparing reference's output against implementation's output for floating point data types */
51} // namespace
52
53/** M0 values to test --precommit*/
54const auto m0_values_precommit = framework::dataset::make("M0", { 1, 3 });
55
56/** N0 values to test --precommit*/
57const auto n0_values_precommit = framework::dataset::make("N0", { 2, 4 });
58
59/** K0 values to test --precommit*/
60const auto k0_values_precommit = framework::dataset::make("K0", { 2, 3 });
61
62/** M0 values to test --nightly*/
63const auto m0_values_nightly_lhs_nt = framework::dataset::make("M0", { 1, 2, 3, 4, 5, 6, 7, 8 });
64const auto m0_values_nightly_lhs_t = framework::dataset::make("M0", { 1, 2, 3, 4, 8 });
65
66/** N0 values to test --nightly*/
67const auto n0_values_nightly_rhs_nt = framework::dataset::make("N0", { 1, 2, 3, 4, 8, 16 });
68const auto n0_values_nightly_rhs_t = framework::dataset::make("N0", { 1, 2, 3, 4, 8 });
69
70/** K0 values to test --nightly*/
71const auto k0_values_nightly_lhs_nt_rhs_nt = framework::dataset::make("K0", { 1, 2, 3, 4, 8, 16 });
72const auto k0_values_nightly_rhs_t = framework::dataset::make("K0", { 1, 2, 3, 4, 8 });
73const auto k0_values_nightly_lhs_t_rhs_nt = framework::dataset::make("K0", { 1, 2, 3, 4, 5, 6, 7, 8 });
74
75template <typename T>
Gunes Bayir9d0c4de2023-04-13 18:22:58 +010076using CLMatMulKernelFixture = MatMulKernelValidationFixture<T, ClMatMulNativeKernel>;
Gunes Bayir8918b232023-03-17 13:52:21 +000077
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +010078template <typename T>
79using CLMatMulKernelBiasFixture = MatMulKernelWithBiasValidation<T, ClMatMulNativeKernel>;
80
Gunes Bayir8918b232023-03-17 13:52:21 +000081TEST_SUITE(CL)
82TEST_SUITE(MatMulKernel)
83TEST_SUITE(Validate)
84
85TEST_CASE(SupportedBlockSizes, framework::DatasetMode::ALL)
86{
87 using MatMulConfigurationPair = std::pair<MatMulKernelInfo, bool>;
88
89 const std::vector<MatMulConfigurationPair> supported_block_sizes =
90 {
91 // MatMulKernelInfo(adj_lhs, adj_rhs, M0, N0, K0, export_rhs_to_cl_image = false)
92 // Lhs not-transposed, Rhs-not-transposed
93 { MatMulKernelInfo(false, false, 0, 1, 1), false }, // M0 should be > 0
94 { MatMulKernelInfo(false, false, 3, 5, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
95 { MatMulKernelInfo(false, false, 3, 6, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
96 { MatMulKernelInfo(false, false, 3, 3, 17), false }, // K0 not in {1, 2, 3, 4, 8, 16}
97 { MatMulKernelInfo(false, false, 3, 3, 7), false }, // K0 not in {1, 2, 3, 4, 8, 16}
98 { MatMulKernelInfo(false, false, 9, 1, 2), true },
99 { MatMulKernelInfo(false, false, 3, 16, 3), true },
100 { MatMulKernelInfo(false, false, 7, 3, 4), true },
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100101 { MatMulKernelInfo(false, false, 7, 3, 4, true), false }, // N0 not in {4, 8, 16}
102 { MatMulKernelInfo(false, false, 7, 1, 4, true), false }, // N0 not in {4, 8, 16}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000103 { MatMulKernelInfo(false, false, 7, 12, 4, true), false }, // N0 not in {4, 8, 16}
104 { MatMulKernelInfo(false, false, 7, 4, 4, true), true },
105 { MatMulKernelInfo(false, false, 7, 8, 4, true), true },
106 { MatMulKernelInfo(false, false, 7, 16, 4, true), true },
Gunes Bayir8918b232023-03-17 13:52:21 +0000107
108 // Lhs not-transposed, Rhs transposed
109 { MatMulKernelInfo(false, true, 0, 1, 1), false }, // M0 should be > 0
110 { MatMulKernelInfo(false, true, 3, 11, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
111 { MatMulKernelInfo(false, true, 3, 7, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
112 { MatMulKernelInfo(false, true, 3, 3, 12), false }, // K0 not in {1, 2, 3, 4, 8, 16}
113 { MatMulKernelInfo(false, true, 3, 3, 6), false }, // K0 not in {1, 2, 3, 4, 8, 16}
114 { MatMulKernelInfo(false, true, 5, 1, 2), true },
115 { MatMulKernelInfo(false, true, 3, 3, 3), true },
116 { MatMulKernelInfo(false, true, 2, 4, 8), true },
Ramy Elgammalb531b752023-03-20 10:19:10 +0000117 { MatMulKernelInfo(false, true, 2, 4, 5, true), false }, // K0 not in {4, 8, 16}
118 { MatMulKernelInfo(false, true, 2, 4, 9, true), false }, // K0 not in {4, 8, 16}
119 { MatMulKernelInfo(false, true, 2, 4, 3, true), false }, // K0 not in {4, 8, 16}
120 { MatMulKernelInfo(false, true, 2, 4, 4, true), true },
121 { MatMulKernelInfo(false, true, 2, 4, 8, true), true },
122 { MatMulKernelInfo(false, true, 2, 8, 16, true), true },
Gunes Bayir8918b232023-03-17 13:52:21 +0000123
Ramy Elgammalb531b752023-03-20 10:19:10 +0000124 // Lhs transposed, Rhs-not-transposed
Gunes Bayir8918b232023-03-17 13:52:21 +0000125 { MatMulKernelInfo(true, false, 1, 1, 0), false }, // K0 should be > 0
126 { MatMulKernelInfo(true, false, 3, 11, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
127 { MatMulKernelInfo(true, false, 3, 7, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
128 { MatMulKernelInfo(true, false, 6, 3, 12), false }, // M0 not in {1, 2, 3, 4, 8, 16}
129 { MatMulKernelInfo(true, false, 5, 3, 6), false }, // M0 not in {1, 2, 3, 4, 8, 16}
130 { MatMulKernelInfo(true, false, 4, 1, 22), true },
131 { MatMulKernelInfo(true, false, 3, 3, 3), true },
132 { MatMulKernelInfo(true, false, 2, 4, 8), true },
Gunes Bayirbbeef722023-03-20 10:19:10 +0000133 { MatMulKernelInfo(true, false, 2, 3, 8, true), false }, // N0 not in {4, 8, 16}
134 { MatMulKernelInfo(true, false, 2, 7, 8, true), false }, // N0 not in {4, 8, 16}
135 { MatMulKernelInfo(true, false, 2, 5, 8, true), false }, // N0 not in {4, 8, 16}
136 { MatMulKernelInfo(true, false, 2, 4, 8, true), true },
137 { MatMulKernelInfo(true, false, 2, 8, 8, true), true },
138 { MatMulKernelInfo(true, false, 2, 16, 8, true), true },
Gunes Bayir8918b232023-03-17 13:52:21 +0000139
Ramy Elgammalb531b752023-03-20 10:19:10 +0000140 // Lhs transposed, Rhs-transposed
Gunes Bayir8918b232023-03-17 13:52:21 +0000141 { MatMulKernelInfo(true, true, 2, 1, 5), false }, // K0 should in {1, 2, 3, 4, 8, 16}
142 { MatMulKernelInfo(true, true, 1, 8, 7), false }, // K0 should in {1, 2, 3, 4, 8, 16}
143 { MatMulKernelInfo(true, true, 3, 11, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
144 { MatMulKernelInfo(true, true, 3, 7, 1), false }, // N0 not in {1, 2, 3, 4, 8, 16}
145 { MatMulKernelInfo(true, true, 6, 3, 12), false }, // M0 not in {1, 2, 3, 4, 8, 16}
146 { MatMulKernelInfo(true, true, 5, 3, 6), false }, // M0 not in {1, 2, 3, 4, 8, 16}
147 { MatMulKernelInfo(true, true, 4, 8, 16), true },
148 { MatMulKernelInfo(true, true, 3, 3, 4), true },
149 { MatMulKernelInfo(true, true, 16, 4, 8), true },
Ramy Elgammalb531b752023-03-20 10:19:10 +0000150 { MatMulKernelInfo(true, true, 2, 2, 1, true), false }, // K0 not in {4, 8, 16}
151 { MatMulKernelInfo(true, true, 2, 2, 5, true), false }, // K0 not in {4, 8, 16}
152 { MatMulKernelInfo(true, true, 2, 4, 7, true), false }, // K0 not in {4, 8, 16}
153 { MatMulKernelInfo(true, true, 2, 4, 4, true), true },
154 { MatMulKernelInfo(true, true, 2, 8, 8, true), true },
155 { MatMulKernelInfo(true, true, 2, 8, 16, true), true },
Gunes Bayir8918b232023-03-17 13:52:21 +0000156 };
157
158 // Set big enough shapes so that block sizes are not truncated. Also, set all dimensions equal
159 // so that it doesn't fail for different NT/T configurations. We aim to test the block sizes here,
160 // not the shapes themselves.
161 const TensorInfo lhs_info = TensorInfo(TensorShape(100U, 100U), 1, DataType::F32);
162 const TensorInfo rhs_info = TensorInfo(TensorShape(100U, 100U), 1, DataType::F32);
163
Gunes Bayirbbeef722023-03-20 10:19:10 +0000164 const bool export_to_cl_image_supported = image2d_from_buffer_supported(CLKernelLibrary::get().get_device());
Gunes Bayir8918b232023-03-17 13:52:21 +0000165 for(auto &pair : supported_block_sizes)
166 {
167 TensorInfo output_info;
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100168 Status status = ClMatMulNativeKernel::validate(&lhs_info, &rhs_info, nullptr, &output_info, pair.first);
Gunes Bayir8918b232023-03-17 13:52:21 +0000169
Gunes Bayirbbeef722023-03-20 10:19:10 +0000170 if(!pair.first.export_rhs_to_cl_image || export_to_cl_image_supported)
171 {
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100172 ARM_COMPUTE_EXPECT(bool(status) == pair.second, framework::LogLevel::ERRORS);
Gunes Bayirbbeef722023-03-20 10:19:10 +0000173 }
174 }
175}
176
177TEST_CASE(ExportToCLImage, framework::DatasetMode::ALL)
178{
179 // We skip this test if the hardware does not support exporting to CL Image
180 if(image2d_from_buffer_supported(CLKernelLibrary::get().get_device()))
181 {
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100182 constexpr size_t pixel_size = 4;
183 const size_t max_image_w = pixel_size * CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_IMAGE2D_MAX_WIDTH>();
184 const size_t max_image_h = CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_IMAGE2D_MAX_HEIGHT>();
Gunes Bayirbbeef722023-03-20 10:19:10 +0000185
186 using ShapeConfigurationTuple = std::tuple<TensorShape, TensorShape, bool, bool, bool>;
187 const std::vector<ShapeConfigurationTuple> shape_configurations =
188 {
189 // lhs_shape, rhs_shape, adj_lhs, adj_rhs, expected
190 // Lhs t/Nt, Rhs Nt
191 // Transposition of Lhs doesn't add any value to the tests, therefore always assumed false below
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100192 { TensorShape(5U, 1U), TensorShape(3U, 5U), false, false, false }, // N should be multiple of 4
Gunes Bayirbbeef722023-03-20 10:19:10 +0000193 { TensorShape(5U, 1U), TensorShape(14U, 5U), false, false, false }, // N should be multiple of 4
194 { TensorShape(5U, 1U), TensorShape(12U, 5U), false, false, true },
195 { TensorShape(5U, 1U), TensorShape(8U, 5U), false, false, true },
196 { TensorShape(5U, 1U), TensorShape(4U, 5U), false, false, true },
197 { TensorShape(max_image_h + 1, 1U), TensorShape(4U, max_image_h + 1), false, false, false }, // Cannot fit into CL Image memory's height
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100198 { TensorShape(5U, 1U), TensorShape(max_image_w + 1, 5U), false, false, false }, // Cannot fit into CL Image memory's width
199 { TensorShape(max_image_h, 1U), TensorShape(4U, max_image_h), false, false, true }, // Barely fits into CL Image memory's height
200 { TensorShape(5U, 1U), TensorShape(max_image_w, 5U), false, false, true }, // Barely fits into CL Image memory's width
Ramy Elgammalb531b752023-03-20 10:19:10 +0000201
202 // Lhs Nt/T , Rhs T
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100203 { TensorShape(5U, 1U), TensorShape(5U, 3U), false, true, false }, // K should be multiple of 4
Ramy Elgammalb531b752023-03-20 10:19:10 +0000204 { TensorShape(5U, 1U), TensorShape(5U, 14U), false, true, false }, // K should be multiple of 4
205 { TensorShape(4U, 1U), TensorShape(4U, 10U), false, true, true },
206 { TensorShape(8U, 1U), TensorShape(8U, 9U), false, true, true },
207 { TensorShape(12U, 1U), TensorShape(12U, 6U), false, true, true },
Gunes Bayirbbeef722023-03-20 10:19:10 +0000208 };
209
210 for(auto &tuple : shape_configurations)
211 {
212 TensorShape lhs_shape = std::get<0>(tuple);
213 TensorShape rhs_shape = std::get<1>(tuple);
214
215 const TensorInfo lhs_info = TensorInfo(lhs_shape, 1, DataType::F32);
216 const TensorInfo rhs_info = TensorInfo(rhs_shape, 1, DataType::F32);
217
218 const bool adj_lhs = std::get<2>(tuple);
219 const bool adj_rhs = std::get<3>(tuple);
220
221 // We choose M0, N0, K0 equal to 4 so that they're always valid for CLImage in any combination
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100222 const MatMulKernelInfo matmul_kernel_info
223 {
224 adj_lhs, adj_rhs, 4, 4, 4, true /* export_rhs_to_cl_image */
225 };
Gunes Bayirbbeef722023-03-20 10:19:10 +0000226
227 TensorInfo output_info;
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100228 Status status = ClMatMulNativeKernel::validate(&lhs_info, &rhs_info, nullptr, &output_info, matmul_kernel_info);
Gunes Bayirbbeef722023-03-20 10:19:10 +0000229
230 const bool expected = std::get<4>(tuple);
231 ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
232 }
Gunes Bayir8918b232023-03-17 13:52:21 +0000233 }
234}
235
236TEST_CASE(ValidateInputShapes, framework::DatasetMode::ALL)
237{
238 // Configurations are assumed to be Nt/Nt, but will be transposed inside the test to test other configurations
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100239 using ShapeConfigurationTuple = std::tuple<TensorShape, TensorShape, TensorShape, bool>;
Gunes Bayir8918b232023-03-17 13:52:21 +0000240 const std::vector<ShapeConfigurationTuple> shape_configurations =
241 {
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100242 { TensorShape(5U, 1U), TensorShape(3U, 5U), TensorShape(3U), true },
243 { TensorShape(10U, 12U), TensorShape(3U, 10U), TensorShape(3U), true },
244 { TensorShape(8U, 4U), TensorShape(2U, 8U), TensorShape(2U), true },
245 { TensorShape(8U, 4U), TensorShape(2U, 5U), TensorShape(2U), false }, // Mismatch in the K dimension
246 { TensorShape(5U, 0U), TensorShape(2U, 5U), TensorShape(2U), false }, // Invalid dimension
247 { TensorShape(5U, 4U, 3U, 4U, 5U, 6U), TensorShape(2U, 5U, 3U, 4U, 5U, 6U), TensorShape(2U), true },
248 { TensorShape(5U, 4U, 3U, 4U, 5U, 1U), TensorShape(2U, 5U, 3U, 4U, 5U, 6U), TensorShape(2U), false }, // no batch broadcasting
249 { TensorShape(5U, 4U, 3U, 4U, 9U, 6U), TensorShape(2U, 5U, 3U, 4U, 5U, 6U), TensorShape(2U), false }, // mismatch in batch dimension
250 { TensorShape(5U, 1U), TensorShape(3U, 5U), TensorShape(1U), false }, // Unsupported bias broadcasting.
251 { TensorShape(5U, 1U), TensorShape(3U, 5U), TensorShape(3U, 3U), false }, // 2D bias is unsupported.
252 { TensorShape(5U, 1U), TensorShape(3U, 5U), TensorShape(6U), false }, // bias first dimension != dst first dimension
Gunes Bayir8918b232023-03-17 13:52:21 +0000253 };
254
255 for(auto &tuple : shape_configurations)
256 {
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100257 const bool expected = std::get<3>(tuple);
Gunes Bayir8918b232023-03-17 13:52:21 +0000258
259 for(bool adj_lhs :
260 {
261 false, true
262 })
263 {
264 for(bool adj_rhs :
265 {
266 false, true
267 })
268 {
269 TensorShape lhs_shape = std::get<0>(tuple);
270 TensorShape rhs_shape = std::get<1>(tuple);
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100271 TensorShape bia_shape = std::get<2>(tuple);
Gunes Bayir8918b232023-03-17 13:52:21 +0000272
273 if(adj_lhs)
274 {
275 permute(lhs_shape, PermutationVector(1U, 0U));
276 }
277
278 if(adj_rhs)
279 {
280 permute(rhs_shape, PermutationVector(1U, 0U));
281 }
282
283 const TensorInfo lhs_info = TensorInfo(lhs_shape, 1, DataType::F32);
284 const TensorInfo rhs_info = TensorInfo(rhs_shape, 1, DataType::F32);
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100285 const TensorInfo bia_info = TensorInfo(bia_shape, 1, DataType::F32);
Gunes Bayir8918b232023-03-17 13:52:21 +0000286 TensorInfo output_info;
287
288 MatMulKernelInfo matmul_kernel_info{ adj_lhs, adj_rhs, 1, 1, 1, false /* export_rhs_to_cl_image */ };
289
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100290 Status status = ClMatMulNativeKernel::validate(&lhs_info, &rhs_info, &bia_info, &output_info, matmul_kernel_info);
Gunes Bayir8918b232023-03-17 13:52:21 +0000291 ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
292 }
293 }
294 }
295}
296
297TEST_CASE(ValidateDataTypes, framework::DatasetMode::ALL)
298{
299 // Configurations are assumed to be Nt/Nt, but will be transposed inside the test to test other configurations
300 using DataTypeConfigurationTuple = std::tuple<DataType, DataType, DataType, bool>;
301 const std::vector<DataTypeConfigurationTuple> data_type_configurations =
302 {
303 { DataType::F32, DataType::F32, DataType::F32, true },
304 { DataType::F16, DataType::F16, DataType::F16, true },
305 { DataType::F16, DataType::F32, DataType::F32, false }, // no mixed precision
306 { DataType::F64, DataType::F64, DataType::F64, false }, // no double precision
307 { DataType::QASYMM8, DataType::QASYMM8, DataType::QASYMM8, false }, // no quantized types
308 { DataType::QASYMM8_SIGNED, DataType::QASYMM8_SIGNED, DataType::QASYMM8_SIGNED, false }, // no quantized types
309 { DataType::QSYMM8_PER_CHANNEL, DataType::QSYMM8_PER_CHANNEL, DataType::QSYMM8_PER_CHANNEL, false }, // no quantized types
310 { DataType::QASYMM16, DataType::QASYMM16, DataType::QASYMM16, false }, // no quantized types
311 { DataType::QSYMM16, DataType::QSYMM16, DataType::QSYMM16, false }, // no quantized types
312 { DataType::QSYMM8, DataType::QSYMM8, DataType::QSYMM8, false }, // no quantized types
313 { DataType::S64, DataType::S64, DataType::S64, false }, // no integral types
314 { DataType::S32, DataType::S32, DataType::S32, false }, // no integral types
315 { DataType::S16, DataType::S16, DataType::S16, false }, // no integral types
316 { DataType::S8, DataType::S8, DataType::S8, false }, // no integral types
317 { DataType::U64, DataType::U64, DataType::U64, false }, // no integral types
318 { DataType::U32, DataType::U32, DataType::U32, false }, // no integral types
319 { DataType::U16, DataType::U16, DataType::U16, false }, // no integral types
320 { DataType::U8, DataType::U8, DataType::U8, false }, // no integral types
321 };
322
323 const TensorShape shape = TensorShape(10U, 10U);
324 const MatMulKernelInfo matmul_kernel_info{ false, false, 1, 1, 1, false };
325 for(auto &tuple : data_type_configurations)
326 {
327 const bool expected = std::get<3>(tuple);
328
329 const TensorInfo lhs_info(shape, 1, std::get<0>(tuple));
330 const TensorInfo rhs_info(shape, 1, std::get<1>(tuple));
331 TensorInfo output_info(shape, 1, std::get<2>(tuple));
332
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100333 Status status = ClMatMulNativeKernel::validate(&lhs_info, &rhs_info, nullptr, &output_info, matmul_kernel_info);
Gunes Bayir8918b232023-03-17 13:52:21 +0000334 ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
335 }
336}
337
338TEST_SUITE_END() // Validate
339
340TEST_SUITE(Float)
341TEST_SUITE(FP32)
Gunes Bayirbbeef722023-03-20 10:19:10 +0000342TEST_SUITE(Buffer)
343FIXTURE_DATA_TEST_CASE(RunTiny, CLMatMulKernelFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::TinyMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100344 framework::dataset::make("TransposeA", { false, true })),
345 framework::dataset::make("TransposeB", { false, true })),
346 m0_values_precommit),
347 n0_values_precommit),
348 k0_values_precommit),
349 framework::dataset::make("ExportRhsToCLImage", { false })),
350 framework::dataset::make("DataType", DataType::F32)))
Gunes Bayir8918b232023-03-17 13:52:21 +0000351{
352 // Validate output
353 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
354}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000355FIXTURE_DATA_TEST_CASE(RunSmall, CLMatMulKernelFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100356 framework::dataset::make("TransposeA", { false, true })),
357 framework::dataset::make("TransposeB", { false, true })),
358 m0_values_precommit),
359 n0_values_precommit),
360 k0_values_precommit),
361 framework::dataset::make("ExportRhsToCLImage", { false })),
362 framework::dataset::make("DataType", DataType::F32)))
Gunes Bayir8918b232023-03-17 13:52:21 +0000363{
364 // Validate output
365 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
366}
Mohammed Suhail Munshi8e2dede2023-06-27 14:25:58 +0100367FIXTURE_DATA_TEST_CASE(RunWithBias, CLMatMulKernelBiasFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDataset(),
368 framework::dataset::make("TransposeA", { false, true })),
369 framework::dataset::make("TransposeB", { false, true })),
370 m0_values_precommit),
371 n0_values_precommit),
372 k0_values_precommit),
373 framework::dataset::make("ExportRhsToCLImage", { false })),
374 framework::dataset::make("DataType", DataType::F32)))
375
376{
377 // Validate output
378 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
379}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000380FIXTURE_DATA_TEST_CASE(RunLargeNoTranspose, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100381 framework::dataset::make("TransposeA", { false })),
382 framework::dataset::make("TransposeB", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000383 m0_values_nightly_lhs_nt),
384 n0_values_nightly_rhs_nt),
385 k0_values_nightly_lhs_nt_rhs_nt),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100386 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000387 framework::dataset::make("DataType", DataType::F32)))
388{
389 // Validate output
390 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
391}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000392FIXTURE_DATA_TEST_CASE(RunLargeRhsTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100393 framework::dataset::make("TransposeA", { false })),
394 framework::dataset::make("TransposeB", { true })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000395 m0_values_nightly_lhs_nt),
396 n0_values_nightly_rhs_t),
397 k0_values_nightly_rhs_t),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100398 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000399 framework::dataset::make("DataType", DataType::F32)))
400{
401 // Validate output
402 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
403}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000404FIXTURE_DATA_TEST_CASE(RunLargeLhsTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100405 framework::dataset::make("TransposeA", { true })),
406 framework::dataset::make("TransposeB", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000407 m0_values_nightly_lhs_t),
408 n0_values_nightly_rhs_nt),
409 k0_values_nightly_lhs_t_rhs_nt),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100410 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000411 framework::dataset::make("DataType", DataType::F32)))
412{
413 // Validate output
414 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
415}
416FIXTURE_DATA_TEST_CASE(RunLargeLhsTransposedRhsTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY,
Gunes Bayirbbeef722023-03-20 10:19:10 +0000417 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100418 framework::dataset::make("TransposeA", { true })),
419 framework::dataset::make("TransposeB", { true })),
420 m0_values_nightly_lhs_t),
421 n0_values_nightly_rhs_t),
422 k0_values_nightly_rhs_t),
423 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000424 framework::dataset::make("DataType", DataType::F32)))
425{
426 // Validate output
427 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
428}
429// Running High Dimensional test is enough for FP32, because we're stressing the number of dimensions, not data type or M0/N0/K0
430// It's a good idea to test for each Lhs/Rhs T/NT combinations because they're different CL kernels
Gunes Bayirbbeef722023-03-20 10:19:10 +0000431FIXTURE_DATA_TEST_CASE(RunHighDimensional, CLMatMulKernelFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::HighDimensionalMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100432 framework::dataset::make("TransposeA", { false, true })),
433 framework::dataset::make("TransposeB", { false, true })),
434 framework::dataset::make("M0", { 2 })),
435 framework::dataset::make("N0", { 2 })),
436 framework::dataset::make("K0", { 2 })),
437 framework::dataset::make("ExportRhsToCLImage", { false })),
438 framework::dataset::make("DataType", DataType::F32)))
Gunes Bayir8918b232023-03-17 13:52:21 +0000439{
440 // Validate output
441 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
442}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000443TEST_SUITE_END() // Buffer
444
445TEST_SUITE(ExportRhsToCLImage)
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100446FIXTURE_DATA_TEST_CASE(RunSmallRhsNotTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::ALL,
447 combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDatasetRhsExportToCLImageRhsNT(),
448 framework::dataset::make("TransposeA", { true, false })),
449 framework::dataset::make("TransposeB", { false })),
450 framework::dataset::make("M0", { 2 })),
451 framework::dataset::make("N0", { 4, 8, 16 })),
452 framework::dataset::make("K0", { 2, 4 })),
453 framework::dataset::make("ExportRhsToCLImage", { true })),
454 framework::dataset::make("DataType", DataType::F32)))
Gunes Bayirbbeef722023-03-20 10:19:10 +0000455{
456 // Validate output
457 if(_device_supports_export_to_cl_image)
458 {
459 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
460 }
461}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100462FIXTURE_DATA_TEST_CASE(RunLargeRhsNotTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY,
463 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDatasetRhsExportToCLImageRhsNT(),
464 framework::dataset::make("TransposeA", { true, false })),
465 framework::dataset::make("TransposeB", { false })),
466 framework::dataset::make("M0", { 2 })), // Choices of M0 does not matter much because it's related to Lhs tensor
467 framework::dataset::make("N0", { 4, 8, 16 })),
468 framework::dataset::make("K0", { 1, 2, 3, 4 })),
469 framework::dataset::make("ExportRhsToCLImage", { true })),
470 framework::dataset::make("DataType", DataType::F32)))
Gunes Bayirbbeef722023-03-20 10:19:10 +0000471{
472 // Validate output
473 if(_device_supports_export_to_cl_image)
474 {
475 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
476 }
477}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100478FIXTURE_DATA_TEST_CASE(RunSmallRhsTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::ALL,
479 combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDatasetRhsExportToCLImageRhsT(),
480 framework::dataset::make("TransposeA", { true, false })),
481 framework::dataset::make("TransposeB", { true })),
482 framework::dataset::make("M0", { 2 })),
483 framework::dataset::make("N0", { 2, 4 })),
484 framework::dataset::make("K0", { 4, 8, 16 })),
485 framework::dataset::make("ExportRhsToCLImage", { true })),
486 framework::dataset::make("DataType", DataType::F32)))
Ramy Elgammalb531b752023-03-20 10:19:10 +0000487{
488 // Validate output
489 if(_device_supports_export_to_cl_image)
490 {
491 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
492 }
493}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100494FIXTURE_DATA_TEST_CASE(RunLargeRhsTransposed, CLMatMulKernelFixture<float>, framework::DatasetMode::NIGHTLY,
495 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDatasetRhsExportToCLImageRhsT(),
496 framework::dataset::make("TransposeA", { true, false })),
497 framework::dataset::make("TransposeB", { true })),
498 framework::dataset::make("M0", { 2 })), // Choices of M0 does not matter much because it's related to Lhs tensor
499 framework::dataset::make("N0", { 1, 2, 3, 4 })),
500 framework::dataset::make("K0", { 4, 8, 16 })),
501 framework::dataset::make("ExportRhsToCLImage", { true })),
502 framework::dataset::make("DataType", DataType::F32)))
Ramy Elgammalb531b752023-03-20 10:19:10 +0000503{
504 // Validate output
505 if(_device_supports_export_to_cl_image)
506 {
507 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, abs_tolerance_f32);
508 }
509}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000510TEST_SUITE_END() // ExportRhsToCLImage
Gunes Bayir8918b232023-03-17 13:52:21 +0000511TEST_SUITE_END() // FP32
512
513TEST_SUITE(FP16)
Gunes Bayirbbeef722023-03-20 10:19:10 +0000514TEST_SUITE(Buffer)
515FIXTURE_DATA_TEST_CASE(RunSmall, CLMatMulKernelFixture<half>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100516 framework::dataset::make("TransposeA", { false, true })),
517 framework::dataset::make("TransposeB", { false, true })),
518 m0_values_precommit),
519 n0_values_precommit),
520 k0_values_precommit),
521 framework::dataset::make("ExportRhsToCLImage", { false })),
522 framework::dataset::make("DataType", DataType::F16)))
Gunes Bayir8918b232023-03-17 13:52:21 +0000523{
524 // Validate output
525 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
526}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000527FIXTURE_DATA_TEST_CASE(RunLargeNoTranspose, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100528 framework::dataset::make("TransposeA", { false })),
529 framework::dataset::make("TransposeB", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000530 m0_values_nightly_lhs_nt),
531 n0_values_nightly_rhs_nt),
532 k0_values_nightly_lhs_nt_rhs_nt),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100533 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000534 framework::dataset::make("DataType", DataType::F16)))
535{
536 // Validate output
537 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
538}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000539FIXTURE_DATA_TEST_CASE(RunLargeRhsTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100540 framework::dataset::make("TransposeA", { false })),
541 framework::dataset::make("TransposeB", { true })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000542 m0_values_nightly_lhs_nt),
543 n0_values_nightly_rhs_t),
544 k0_values_nightly_rhs_t),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100545 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000546 framework::dataset::make("DataType", DataType::F16)))
547{
548 // Validate output
549 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
550}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000551FIXTURE_DATA_TEST_CASE(RunLargeLhsTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100552 framework::dataset::make("TransposeA", { true })),
553 framework::dataset::make("TransposeB", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000554 m0_values_nightly_lhs_t),
555 n0_values_nightly_rhs_nt),
556 k0_values_nightly_lhs_t_rhs_nt),
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100557 framework::dataset::make("ExportRhsToCLImage", { false })),
Gunes Bayir8918b232023-03-17 13:52:21 +0000558 framework::dataset::make("DataType", DataType::F16)))
559{
560 // Validate output
561 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
562}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100563FIXTURE_DATA_TEST_CASE(RunLargeLhsTransposedRhsTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY,
564 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDataset(),
565 framework::dataset::make("TransposeA", { true })),
566 framework::dataset::make("TransposeB", { true })),
567 m0_values_nightly_lhs_t),
568 n0_values_nightly_rhs_t),
569 k0_values_nightly_rhs_t),
570 framework::dataset::make("ExportRhsToCLImage", { false })),
571 framework::dataset::make("DataType", DataType::F16)))
Gunes Bayir8918b232023-03-17 13:52:21 +0000572{
573 // Validate output
574 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
575}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000576TEST_SUITE_END() // Buffer
577
578TEST_SUITE(ExportRhsToCLImage)
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100579FIXTURE_DATA_TEST_CASE(RunSmallRhsNotTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::ALL,
580 combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDatasetRhsExportToCLImageRhsNT(),
581 framework::dataset::make("TransposeA", { true, false })),
582 framework::dataset::make("TransposeB", { false })),
583 framework::dataset::make("M0", { 2 })),
584 framework::dataset::make("N0", { 4, 8, 16 })),
585 framework::dataset::make("K0", { 2, 4 })),
586 framework::dataset::make("ExportRhsToCLImage", { true })),
587 framework::dataset::make("DataType", DataType::F16)))
Gunes Bayirbbeef722023-03-20 10:19:10 +0000588{
589 // Validate output
590 if(_device_supports_export_to_cl_image)
591 {
592 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
593 }
594}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100595FIXTURE_DATA_TEST_CASE(RunLargeRhsNotTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY,
596 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDatasetRhsExportToCLImageRhsNT(),
597 framework::dataset::make("TransposeA", { true, false })),
598 framework::dataset::make("TransposeB", { false })),
599 framework::dataset::make("M0", { 2 })), // Choices of M0 does not matter much because it's related to Lhs tensor
600 framework::dataset::make("N0", { 4, 8, 16 })),
601 framework::dataset::make("K0", { 1, 2, 3, 4 })),
602 framework::dataset::make("ExportRhsToCLImage", { true })),
603 framework::dataset::make("DataType", DataType::F16)))
Gunes Bayirbbeef722023-03-20 10:19:10 +0000604{
605 // Validate output
606 if(_device_supports_export_to_cl_image)
607 {
608 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
609 }
610}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100611FIXTURE_DATA_TEST_CASE(RunSmallRhsTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::ALL,
612 combine(combine(combine(combine(combine(combine(combine(datasets::SmallMatMulDatasetRhsExportToCLImageRhsT(),
613 framework::dataset::make("TransposeA", { true, false })),
614 framework::dataset::make("TransposeB", { true })),
615 framework::dataset::make("M0", { 2 })),
616 framework::dataset::make("N0", { 2, 4 })),
617 framework::dataset::make("K0", { 4, 8, 16 })),
618 framework::dataset::make("ExportRhsToCLImage", { true })),
619 framework::dataset::make("DataType", DataType::F16)))
Ramy Elgammalb531b752023-03-20 10:19:10 +0000620{
621 // Validate output
622 if(_device_supports_export_to_cl_image)
623 {
624 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
625 }
626}
Gunes Bayir9d0c4de2023-04-13 18:22:58 +0100627FIXTURE_DATA_TEST_CASE(RunLargeRhsTransposed, CLMatMulKernelFixture<half>, framework::DatasetMode::NIGHTLY,
628 combine(combine(combine(combine(combine(combine(combine(datasets::LargeMatMulDatasetRhsExportToCLImageRhsT(),
629 framework::dataset::make("TransposeA", { true, false })),
630 framework::dataset::make("TransposeB", { true })),
631 framework::dataset::make("M0", { 2 })), // Choices of M0 does not matter much because it's related to Lhs tensor
632 framework::dataset::make("N0", { 1, 2, 3, 4 })),
633 framework::dataset::make("K0", { 4, 8, 16 })),
634 framework::dataset::make("ExportRhsToCLImage", { true })),
635 framework::dataset::make("DataType", DataType::F16)))
Ramy Elgammalb531b752023-03-20 10:19:10 +0000636{
637 // Validate output
638 if(_device_supports_export_to_cl_image)
639 {
640 validate(CLAccessor(_target), _reference, tolerance_f16, 0.f, abs_tolerance_f16);
641 }
642}
Gunes Bayirbbeef722023-03-20 10:19:10 +0000643TEST_SUITE_END() // ExportRhsToCLImage
Gunes Bayir8918b232023-03-17 13:52:21 +0000644TEST_SUITE_END() // FP16
645TEST_SUITE_END() // Float
646TEST_SUITE_END() // MatMulKernel
647TEST_SUITE_END() // CL
648} // namespace validation
649} // namespace test
650} // namespace arm_compute