blob: 57a5f9739e6c41b0b3cc2185ec9134bc6fd54e4e [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 Arm Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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#include "arm_compute/runtime/CL/functions/CLGEMM.h"
25
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010026#include "arm_compute/core/CL/CLKernelLibrary.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010027#include "arm_compute/core/CL/ICLTensor.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010028#include "arm_compute/core/Error.h"
Gian Marco Iodice750641d2018-05-08 12:01:57 +010029#include "arm_compute/core/GPUTarget.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/Helpers.h"
Gian Marco Iodice7026b302019-06-26 17:18:11 +010031#include "arm_compute/core/KernelDescriptors.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032#include "arm_compute/core/TensorInfo.h"
33#include "arm_compute/core/Types.h"
Gian Marco Iodicebb36a8e2018-04-19 12:05:08 +010034#include "arm_compute/core/Utils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010035#include "arm_compute/core/Validate.h"
Gian Marco Iodice750641d2018-05-08 12:01:57 +010036#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010037#include "arm_compute/runtime/CL/CLScheduler.h"
38#include "arm_compute/runtime/ITensorAllocator.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010039#include "src/core/CL/ICLGEMMKernelConfiguration.h"
40#include "src/core/CL/gemm/reshaped/CLGEMMReshapedKernelConfiguration.h"
41#include "src/core/CL/gemm/reshaped_only_rhs/CLGEMMReshapedOnlyRHSKernelConfiguration.h"
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010042#include "src/core/CL/kernels/CLGEMMMatrixMultiplyKernel.h"
43#include "src/core/CL/kernels/CLGEMMMatrixMultiplyReshapedKernel.h"
44#include "src/core/CL/kernels/CLGEMMMatrixMultiplyReshapedOnlyRHSKernel.h"
45#include "src/core/CL/kernels/CLGEMMReshapeLHSMatrixKernel.h"
46#include "src/core/CL/kernels/CLGEMMReshapeRHSMatrixKernel.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010047#include "src/core/helpers/AutoConfiguration.h"
48#include "src/core/utils/helpers/float_ops.h"
49#include "src/runtime/CL/gemm/CLGEMMKernelSelection.h"
50#include "support/Cast.h"
51
52#include "support/MemorySupport.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010053
giuros011c9efeb2019-01-11 14:04:43 +000054namespace arm_compute
55{
Gian Marco Iodice750641d2018-05-08 12:01:57 +010056using namespace arm_compute::misc::shape_calculator;
Gian Marco Iodice90313eb2019-01-16 15:40:25 +000057using namespace arm_compute::cl_gemm;
Michalis Spyroub27e13a2019-09-27 11:04:27 +010058using namespace arm_compute::utils::cast;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010059
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010060namespace weights_transformations
61{
62CLGEMMReshapeRHSMatrixKernelManaged::CLGEMMReshapeRHSMatrixKernelManaged()
63 : _kernel(support::cpp14::make_unique<CLGEMMReshapeRHSMatrixKernel>())
64{
65}
66
67CLGEMMReshapeRHSMatrixKernelManaged::~CLGEMMReshapeRHSMatrixKernelManaged() = default;
68
69void CLGEMMReshapeRHSMatrixKernelManaged::run()
70{
71 _output.allocator()->allocate();
72 CLScheduler::get().enqueue(*_kernel, false);
73 _reshape_run = true;
74}
75
76void CLGEMMReshapeRHSMatrixKernelManaged::release()
77{
78 _output.allocator()->free();
79}
80
81ICLTensor *CLGEMMReshapeRHSMatrixKernelManaged::get_weights()
82{
83 return &_output;
84}
85
86uint32_t CLGEMMReshapeRHSMatrixKernelManaged::uid()
87{
88 return _uid;
89}
90
91void CLGEMMReshapeRHSMatrixKernelManaged::configure(const ICLTensor *input, GEMMRHSMatrixInfo info)
92{
93 configure(CLKernelLibrary::get().get_compile_context(), input, info);
94}
95
96void CLGEMMReshapeRHSMatrixKernelManaged::configure(const CLCompileContext &compile_context, const ICLTensor *input, GEMMRHSMatrixInfo info)
97{
98 _kernel->configure(compile_context, input, &_output, info);
99}
100} // namespace weights_transformations
101
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100102CLGEMM::CLGEMM(std::shared_ptr<IMemoryManager> memory_manager, IWeightsManager *weights_manager)
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +0100103 : _memory_group(std::move(memory_manager)),
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100104 _weights_manager(weights_manager),
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100105 _mm_kernel(support::cpp14::make_unique<CLGEMMMatrixMultiplyKernel>()),
106 _reshape_lhs_kernel(support::cpp14::make_unique<CLGEMMReshapeLHSMatrixKernel>()),
107 _reshape_rhs_kernel(support::cpp14::make_unique<CLGEMMReshapeRHSMatrixKernel>()),
108 _reshape_rhs_kernel_managed(support::cpp14::make_unique<weights_transformations::CLGEMMReshapeRHSMatrixKernelManaged>()),
109 _mm_reshaped_kernel(support::cpp14::make_unique<CLGEMMMatrixMultiplyReshapedKernel>()),
110 _mm_reshaped_only_rhs_kernel(support::cpp14::make_unique<CLGEMMMatrixMultiplyReshapedOnlyRHSKernel>()),
111 _mm_reshaped_only_rhs_fallback_kernel(support::cpp14::make_unique<CLGEMMMatrixMultiplyReshapedOnlyRHSKernel>()),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +0100112 _tmp_a(),
113 _tmp_b(),
114 _original_b(nullptr),
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100115 _lhs(nullptr),
116 _dst(nullptr),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +0100117 _reshape_b_only_on_first_run(false),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000118 _is_prepared(false),
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000119 _gemm_kernel_type(CLGEMMKernelType::NATIVE_V1)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100120{
121}
122
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100123CLGEMM::~CLGEMM() = default;
124
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100125CLGEMMKernelType CLGEMM::select_gemm_kernel(unsigned int m, unsigned int n, unsigned int k, unsigned int b, DataType data_type, bool reshape_b_only_on_first_run)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100126{
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000127 std::unique_ptr<ICLGEMMKernelSelection> gemm_kernel = CLGEMMKernelSelectionFactory::create(CLScheduler::get().target());
128 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_kernel.get());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100129
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000130 CLGEMMKernelSelectionParams params;
131 params.m = m;
132 params.n = n;
133 params.k = k;
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100134 params.b = b;
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000135 params.is_rhs_constant = reshape_b_only_on_first_run;
136 params.data_type = data_type;
Gian Marco Iodice05639f62019-09-24 12:05:06 +0100137
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000138 return gemm_kernel->select_kernel(params);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000139}
140
Manuel Bottini2b84be52020-04-08 10:15:51 +0100141void CLGEMM::configure_native_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
142 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000143{
144 const unsigned int m = gemm_info.reinterpret_input_as_3d() ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
145 const unsigned int n = b->info()->dimension(0);
146 const unsigned int k = a->info()->dimension(0);
147 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco36a0a462018-01-12 10:21:40 +0000148
149 // Set the target for the kernels
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100150 _mm_kernel->set_target(gpu_target);
Gian Marco36a0a462018-01-12 10:21:40 +0000151
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100152 GEMMReshapeInfo reshape_info(m, n, k, 1, 1, gemm_info.depth_output_gemm3d(), gemm_info.reinterpret_input_as_3d(), gemm_info.broadcast_bias());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000153
154 // Configure and tune matrix multiply kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100155 _mm_kernel->configure(compile_context, a, b, c, output, alpha, beta, false, reshape_info, gemm_info.fp_mixed_precision(), gemm_info.activation_info());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000156
157 // Tune kernel statically
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100158 CLScheduler::get().tune_kernel_static(*_mm_kernel);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000159}
160
Manuel Bottini2b84be52020-04-08 10:15:51 +0100161void CLGEMM::configure_reshaped_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
162 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000163{
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000164 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
165 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
166 const unsigned int n = b->info()->dimension(0);
167 const unsigned int k = a->info()->dimension(0);
168 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000169 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000170 int mult_transpose1xW_width = 1;
171 int mult_interleave4x4_height = 1;
Gian Marco36a0a462018-01-12 10:21:40 +0000172
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000173 // Set the target for the kernels
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100174 _reshape_lhs_kernel->set_target(gpu_target);
175 _mm_kernel->set_target(gpu_target);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000176
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100177 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
Gian Marco36a0a462018-01-12 10:21:40 +0000178 {
179 mult_transpose1xW_width = 4;
180 mult_interleave4x4_height = 2;
181 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000182
giuros018b6b4a92018-12-18 19:01:33 +0000183 GEMMRHSMatrixInfo rhs_info;
184 rhs_info.n0 = 16 / b->info()->element_size();
185 rhs_info.k0 = 1;
186 rhs_info.h0 = mult_transpose1xW_width;
187 rhs_info.interleave = false;
188 rhs_info.transpose = false;
Gian Marco36a0a462018-01-12 10:21:40 +0000189
giuros011c9efeb2019-01-11 14:04:43 +0000190 GEMMLHSMatrixInfo lhs_info;
191 lhs_info.m0 = 4;
192 lhs_info.k0 = 4;
193 lhs_info.v0 = mult_interleave4x4_height;
194 lhs_info.interleave = true;
195 lhs_info.transpose = true;
196
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100197 GEMMReshapeInfo reshape_info(m, n, k, mult_transpose1xW_width, mult_interleave4x4_height, depth_output_gemm3d, false, gemm_info.broadcast_bias());
Gian Marcob5311a62017-12-13 12:48:03 +0000198
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100199 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
200
201 // Manage intermediate buffers
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000202 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100203
204 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice68a3f562018-07-26 11:44:03 +0100205 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000206 _memory_group.manage(&_tmp_b);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100207 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100208
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000209 // Configure interleave kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100210 _reshape_lhs_kernel->configure(compile_context, a, &_tmp_a, lhs_info, reinterpret_input_as_3d);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100211
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000212 // Configure transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100213 ICLTensor *reshaped_rhs = &_tmp_b;
214 if(_weights_manager && _weights_manager->are_weights_managed(b))
215 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100216 _reshape_rhs_kernel_managed->configure(compile_context, b, rhs_info);
217 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, _reshape_rhs_kernel_managed.get()));
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100218 }
219 else
220 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100221 _reshape_rhs_kernel->configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100222 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100223
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000224 // Configure and tune matrix multiply kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100225 _mm_kernel->configure(compile_context, &_tmp_a, reshaped_rhs, c, output, alpha, beta, true, reshape_info, gemm_info.fp_mixed_precision(), gemm_info.activation_info());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000226
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100227 CLScheduler::get().tune_kernel_static(*_mm_kernel);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000228
229 // Allocate intermediate tensors
230 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100231
232 if(!_reshape_b_only_on_first_run && use_mm_b)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100233 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000234 _tmp_b.allocator()->allocate();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100235 }
236}
237
Manuel Bottini2b84be52020-04-08 10:15:51 +0100238void CLGEMM::configure_reshaped_v2(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
239 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000240{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000241 DataType data_type = a->info()->data_type();
242 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
243 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
244 const unsigned int n = b->info()->dimension(0);
245 const unsigned int k = a->info()->dimension(0);
246 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
247 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
248 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100249 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100250
251 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100252 kernel_info.m = m;
253 kernel_info.n = n;
254 kernel_info.k = k;
255 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
256 kernel_info.reinterpret_input_as_3d = false;
257 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100258 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000259
260 // Set the target for the kernels
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100261 _reshape_lhs_kernel->set_target(gpu_target);
262 _mm_kernel->set_target(gpu_target);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000263
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100264 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
265
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000266 // Manage intermediate buffers
267 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100268
269 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000270 {
271 _memory_group.manage(&_tmp_b);
272 }
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100273
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000274 // _tmp_a and _tmp_b will be auto configured in _interleave_kernel and in _transpose_kernel
275
276 GEMMLHSMatrixInfo lhs_info{};
277 GEMMRHSMatrixInfo rhs_info{};
278
279 // Pick up the GEMM configuration
280 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
281 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
282
283 // Configure lhs_info and rhs_info
284 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
285
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100286 _reshape_lhs_kernel->configure(compile_context, a, &_tmp_a, lhs_info, gemm_info.reinterpret_input_as_3d());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100287
288 ICLTensor *reshaped_rhs = &_tmp_b;
289 if(_weights_manager && _weights_manager->are_weights_managed(b))
290 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100291 _reshape_rhs_kernel_managed->configure(compile_context, b, rhs_info);
292 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, _reshape_rhs_kernel_managed.get()));
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100293 }
294 else
295 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100296 _reshape_rhs_kernel->configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100297 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000298
299 // Configure and tune matrix multiply kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100300 _mm_reshaped_kernel->configure(compile_context, &_tmp_a, reshaped_rhs, c, output, alpha, beta, lhs_info, rhs_info, kernel_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000301
302 // Allocate intermediate tensors
303 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100304
305 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000306 {
307 _tmp_b.allocator()->allocate();
308 }
309}
310
Manuel Bottini2b84be52020-04-08 10:15:51 +0100311void CLGEMM::configure_reshaped_only_rhs(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
312 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000313{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000314 DataType data_type = a->info()->data_type();
315 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
316 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
317 const unsigned int n = b->info()->dimension(0);
318 const unsigned int k = a->info()->dimension(0);
319 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
320 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
321 const GPUTarget gpu_target = CLScheduler::get().target();
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100322 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100323
324 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100325 kernel_info.m = m;
326 kernel_info.n = n;
327 kernel_info.k = k;
328 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
329 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
330 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100331 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000332
333 // Set the target for the kernels
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100334 _mm_kernel->set_target(gpu_target);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000335
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100336 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
337
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000338 // Manage intermediate buffers
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100339 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000340 {
341 _memory_group.manage(&_tmp_b);
342 }
343
344 GEMMLHSMatrixInfo lhs_info{};
345 GEMMRHSMatrixInfo rhs_info{};
346
347 // Pick up the GEMM configuration
348 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
349 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
350
351 // Configure lhs_info and rhs_info
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100352 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000353
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100354 ICLTensor *reshaped_rhs = &_tmp_b;
355 if(_weights_manager && _weights_manager->are_weights_managed(b))
356 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100357 _reshape_rhs_kernel_managed->configure(compile_context, b, rhs_info);
358 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, _reshape_rhs_kernel_managed.get()));
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100359 }
360 else
361 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100362 _reshape_rhs_kernel->configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100363 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000364
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100365 // Configure two variants of CLGEMMMatrixMultiplyReshapedOnlyRHSKernel (has_pad_y = false/true)
366 // During the prepare stage we check the padding requirement for the lhs and dst tensors. If they do not have
367 // pad y, we dispatch CLGEMMMatrixMultiplyReshapedOnlyRHSKernel with has_pad_y = false
368
369 // Configure matrix multiply kernel with no y padding support
370 kernel_info.has_pad_y = false;
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100371 _mm_reshaped_only_rhs_kernel->configure(compile_context, a, reshaped_rhs, c, output, alpha, beta, lhs_info, rhs_info, kernel_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000372
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100373 // Configure matrix multiply kernel with y padding support
374 kernel_info.has_pad_y = true;
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100375 _mm_reshaped_only_rhs_fallback_kernel->configure(compile_context, a, reshaped_rhs, c, output, alpha, beta, lhs_info, rhs_info, kernel_info);
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100376
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100377 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000378 {
379 _tmp_b.allocator()->allocate();
380 }
381}
382
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000383Status CLGEMM::validate_native_v1(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
Georgios Pinitas78c00902018-01-09 17:33:11 +0000384{
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100385 ARM_COMPUTE_UNUSED(alpha);
Gian Marco Iodice215b4ea2018-06-28 16:29:29 +0100386 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100387
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000388 // Get the GPU target
389 const GPUTarget gpu_target = CLScheduler::get().target();
390 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
391 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
392 const unsigned int n = b->dimension(0);
393 const unsigned int k = a->dimension(0);
394 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100395
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100396 const GEMMReshapeInfo reshape_info = GEMMReshapeInfo(m, n, k, 1, 1, depth_output_gemm3d, reinterpret_input_as_3d, gemm_info.broadcast_bias());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000397
398 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100399 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(a, b, c, output, alpha, beta,
400 false, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000401
402 return Status{};
403}
404
405Status CLGEMM::validate_reshaped_v1(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
406{
407 ARM_COMPUTE_UNUSED(alpha);
408 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100409
410 TensorInfo tmp_a_info{};
411 TensorInfo tmp_b_info{};
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100412
413 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000414 const GPUTarget gpu_target = CLScheduler::get().target();
415 const unsigned int m = gemm_info.reinterpret_input_as_3d() ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000416 const unsigned int n = b->dimension(0);
417 const unsigned int k = a->dimension(0);
418 int mult_transpose1xW_width = 1;
419 int mult_interleave4x4_height = 1;
420 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100421
422 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
423 {
424 mult_transpose1xW_width = 4;
425 mult_interleave4x4_height = 2;
426 }
427
giuros018b6b4a92018-12-18 19:01:33 +0000428 GEMMRHSMatrixInfo rhs_info;
429 rhs_info.n0 = 16 / b->element_size();
430 rhs_info.k0 = 1;
431 rhs_info.h0 = mult_transpose1xW_width;
432 rhs_info.interleave = false;
433 rhs_info.transpose = false;
434
giuros011c9efeb2019-01-11 14:04:43 +0000435 GEMMLHSMatrixInfo lhs_info;
436 lhs_info.m0 = 4;
437 lhs_info.k0 = 4;
438 lhs_info.v0 = mult_interleave4x4_height;
439 lhs_info.interleave = true;
440 lhs_info.transpose = true;
441
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100442 const GEMMReshapeInfo reshape_info = GEMMReshapeInfo(m, n, k, mult_transpose1xW_width, mult_interleave4x4_height, depth_output_gemm3d, false, gemm_info.broadcast_bias());
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100443
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000444 // Validate interleave kernel
445 auto_init_if_empty(tmp_a_info, a->clone()->set_tensor_shape(compute_lhs_reshaped_shape(*a, lhs_info, gemm_info.reinterpret_input_as_3d())));
446 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeLHSMatrixKernel::validate(a, &tmp_a_info, lhs_info, gemm_info.reinterpret_input_as_3d()));
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000447
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000448 // Validate transpose kernel
449 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
450 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
Michele Di Giorgioebc3a902018-11-16 16:04:25 +0000451
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000452 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100453 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(&tmp_a_info, &tmp_b_info, c, output, alpha, beta,
454 true, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100455
Georgios Pinitas78c00902018-01-09 17:33:11 +0000456 return Status{};
457}
458
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000459Status CLGEMM::validate_reshaped(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000460{
461 ARM_COMPUTE_UNUSED(alpha);
462 ARM_COMPUTE_UNUSED(output);
463
464 TensorInfo tmp_a_info{};
465 TensorInfo tmp_b_info{};
466
467 // Get the GPU target
468 const GPUTarget gpu_target = CLScheduler::get().target();
469 DataType data_type = a->data_type();
470 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
471 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
472 const unsigned int n = b->dimension(0);
473 const unsigned int k = a->dimension(0);
474 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
475 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100476 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100477
478 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100479 kernel_info.m = m;
480 kernel_info.n = n;
481 kernel_info.k = k;
482 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
483 kernel_info.reinterpret_input_as_3d = false;
484 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100485 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000486
487 GEMMLHSMatrixInfo lhs_info;
488 GEMMRHSMatrixInfo rhs_info;
489
490 // Pick up the GEMM configuration
491 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
492 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
493
494 // Configure lhs_info and rhs_info
495 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
496
497 auto_init_if_empty(tmp_a_info, a->clone()->set_tensor_shape(compute_lhs_reshaped_shape(*a, lhs_info, gemm_info.reinterpret_input_as_3d())));
498 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeLHSMatrixKernel::validate(a, &tmp_a_info, lhs_info, gemm_info.reinterpret_input_as_3d()));
499
500 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
501 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
502
503 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100504 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyReshapedKernel::validate(&tmp_a_info, &tmp_b_info, c, output, alpha, beta, lhs_info, rhs_info, kernel_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000505
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000506 return Status{};
507}
508
509Status CLGEMM::validate_reshaped_only_rhs(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
510{
511 ARM_COMPUTE_UNUSED(alpha);
512 ARM_COMPUTE_UNUSED(output);
513
514 TensorInfo tmp_b_info{};
515
516 // Get the GPU target
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100517 const GPUTarget gpu_target = CLScheduler::get().target();
518 const DataType data_type = a->data_type();
519 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
520 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
521 const unsigned int n = b->dimension(0);
522 const unsigned int k = a->dimension(0);
523 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
524 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
525 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100526
527 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100528 kernel_info.m = m;
529 kernel_info.n = n;
530 kernel_info.k = k;
531 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
532 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
533 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100534 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000535
536 GEMMLHSMatrixInfo lhs_info;
537 GEMMRHSMatrixInfo rhs_info;
538
539 // Pick up the GEMM configuration
540 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
541 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
542
543 // Configure lhs_info and rhs_info
544 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
545
546 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
547 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
548
549 // Validate matrix multiply
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100550 kernel_info.has_pad_y = false;
551 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyReshapedOnlyRHSKernel::validate(a, &tmp_b_info, c, output, alpha, beta, lhs_info, rhs_info, kernel_info));
552
553 kernel_info.has_pad_y = true;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100554 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyReshapedOnlyRHSKernel::validate(a, &tmp_b_info, c, output, alpha, beta, lhs_info, rhs_info, kernel_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000555
556 return Status{};
557}
558
559void CLGEMM::configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
560{
Manuel Bottini2b84be52020-04-08 10:15:51 +0100561 configure(CLKernelLibrary::get().get_compile_context(), a, b, c, output, alpha, beta, gemm_info);
562}
563
564void CLGEMM::configure(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
565{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000566 ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, output);
567
568 // Perform validation step
569 ARM_COMPUTE_ERROR_THROW_ON(validate(a->info(), b->info(), c != nullptr ? c->info() : nullptr, output->info(), alpha, beta, gemm_info));
570
571 // Check if we need to reshape the matrix B only on the first run
572 _reshape_b_only_on_first_run = gemm_info.reshape_b_only_on_first_run();
573 _is_prepared = gemm_info.retain_internal_weights();
574 _original_b = b;
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100575 _lhs = a;
576 _dst = output;
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000577
578 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000579 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
580 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
581 const unsigned int n = b->info()->dimension(0);
582 const unsigned int k = a->info()->dimension(0);
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100583 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000584
585 // Select GEMMType
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100586 _gemm_kernel_type = select_gemm_kernel(m, n, k, batch_size, a->info()->data_type(), _reshape_b_only_on_first_run);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000587
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100588 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100589
590 const ICLTensor *c_to_use = fuse_add_c ? c : nullptr;
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000591
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000592 switch(_gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000593 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000594 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000595 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100596 configure_native_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000597 break;
598 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000599 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000600 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100601 configure_reshaped_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000602 break;
603 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000604 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000605 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100606 configure_reshaped_v2(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000607 break;
608 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000609 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000610 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100611 configure_reshaped_only_rhs(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000612 break;
613 }
614 default:
615 {
616 ARM_COMPUTE_ERROR("GEMMType not supported");
617 }
618 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000619}
620
621Status CLGEMM::validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
622{
623 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000624 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
625 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
626 const unsigned int n = b->dimension(0);
627 const unsigned int k = a->dimension(0);
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100628 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000629
630 // Select GEMMType
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100631 CLGEMMKernelType gemm_kernel_type = select_gemm_kernel(m, n, k, batch_size, a->data_type(), gemm_info.reshape_b_only_on_first_run());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000632
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100633 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100634
635 const ITensorInfo *c_to_use = fuse_add_c ? c : nullptr;
636
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000637 switch(gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000638 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000639 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000640 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000641 ARM_COMPUTE_RETURN_ON_ERROR(validate_native_v1(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000642 break;
643 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000644 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000645 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100646 ARM_COMPUTE_RETURN_ON_ERROR(validate_reshaped_v1(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000647 break;
648 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000649 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000650 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000651 ARM_COMPUTE_RETURN_ON_ERROR(validate_reshaped(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000652 break;
653 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000654 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000655 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100656 ARM_COMPUTE_RETURN_ON_ERROR(validate_reshaped_only_rhs(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000657 break;
658 }
659 default:
660 {
661 ARM_COMPUTE_RETURN_ERROR_MSG("GEMMType not supported");
662 }
663 }
664
665 return Status{};
666}
667
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100668void CLGEMM::run()
669{
Georgios Pinitase0437672018-05-02 14:07:55 +0100670 prepare();
Georgios Pinitasda953f22019-04-02 17:27:03 +0100671 MemoryGroupResourceScope scope_mg(_memory_group);
Georgios Pinitas8a94e7c2017-09-15 19:06:47 +0100672
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100673 // Run matrix multiply kernel
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000674 switch(_gemm_kernel_type)
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000675 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000676 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000677 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100678 CLScheduler::get().enqueue(*_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000679 break;
680 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000681 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000682 {
683 // Run interleave kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100684 CLScheduler::get().enqueue(*_reshape_lhs_kernel, false);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000685
686 if(!_reshape_b_only_on_first_run)
687 {
688 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100689 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
690 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100691 _weights_manager->run(_original_b, _reshape_rhs_kernel_managed.get());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100692 }
693 else
694 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100695 CLScheduler::get().enqueue(*_reshape_rhs_kernel, false);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100696 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000697 }
698
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100699 CLScheduler::get().enqueue(*_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000700 break;
701 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000702 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000703 {
704 // Run interleave kernel
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100705 CLScheduler::get().enqueue(*_reshape_lhs_kernel, false);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000706
707 if(!_reshape_b_only_on_first_run)
708 {
709 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100710 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
711 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100712 _weights_manager->run(_original_b, _reshape_rhs_kernel_managed.get());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100713 }
714 else
715 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100716 CLScheduler::get().enqueue(*_reshape_rhs_kernel, false);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100717 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000718 }
719
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100720 CLScheduler::get().enqueue(*_mm_reshaped_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000721 break;
722 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000723 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000724 {
725 if(!_reshape_b_only_on_first_run)
726 {
727 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100728 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
729 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100730 _weights_manager->run(_original_b, _reshape_rhs_kernel_managed.get());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100731 }
732 else
733 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100734 CLScheduler::get().enqueue(*_reshape_rhs_kernel, false);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100735 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000736 }
SiCong Li4d2365d2020-11-08 22:11:01 +0000737 // In case of RESHAPED_ONLY_RHS, we need to check the padding requirement
738 // Check if the lhs or dst tensors have padding
739 const unsigned int cross_plane_pad_lhs = _lhs->info()->padding().top + _lhs->info()->padding().bottom;
740 const unsigned int cross_plane_pad_dst = _dst->info()->padding().top + _dst->info()->padding().bottom;
741
742 bool has_pad_y = (cross_plane_pad_lhs != 0) || (cross_plane_pad_dst != 0);
743 if(has_pad_y)
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100744 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100745 CLScheduler::get().enqueue(*_mm_reshaped_only_rhs_fallback_kernel, true);
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100746 }
747 else
748 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100749 CLScheduler::get().enqueue(*_mm_reshaped_only_rhs_kernel, true);
Gian Marco Iodice9ae06d42020-10-22 16:37:12 +0100750 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000751 break;
752 }
753 default:
754 {
755 ARM_COMPUTE_ERROR("GEMMType not supported");
756 }
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000757 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100758}
Georgios Pinitas82b51482018-04-24 15:14:12 +0100759
Georgios Pinitase0437672018-05-02 14:07:55 +0100760void CLGEMM::prepare()
761{
762 if(!_is_prepared)
763 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000764 if(_gemm_kernel_type != CLGEMMKernelType::NATIVE_V1 && _reshape_b_only_on_first_run)
Georgios Pinitase0437672018-05-02 14:07:55 +0100765 {
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100766 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
767 {
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100768 _weights_manager->run(_original_b, _reshape_rhs_kernel_managed.get());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100769 }
770 else
771 {
772 // Run transpose kernel and mark original weights tensor as unused
773 _tmp_b.allocator()->allocate();
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100774 CLScheduler::get().enqueue(*_reshape_rhs_kernel, false);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100775 _original_b->mark_as_unused();
776 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100777 }
778 CLScheduler::get().queue().finish();
779 _is_prepared = true;
780 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100781}
giuros011c9efeb2019-01-11 14:04:43 +0000782} // namespace arm_compute