blob: d56b341abfc336a89af95161b6e296e031ec508b [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
Gian Marco Iodice926afe12019-03-19 11:44:13 +000026#include "arm_compute/core/CL/ICLGEMMKernelConfiguration.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010027#include "arm_compute/core/CL/ICLTensor.h"
Gian Marco Iodice926afe12019-03-19 11:44:13 +000028#include "arm_compute/core/CL/gemm/reshaped/CLGEMMReshapedKernelConfiguration.h"
29#include "arm_compute/core/CL/gemm/reshaped_only_rhs/CLGEMMReshapedOnlyRHSKernelConfiguration.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/Error.h"
Gian Marco Iodice750641d2018-05-08 12:01:57 +010031#include "arm_compute/core/GPUTarget.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032#include "arm_compute/core/Helpers.h"
Gian Marco Iodice7026b302019-06-26 17:18:11 +010033#include "arm_compute/core/KernelDescriptors.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010034#include "arm_compute/core/TensorInfo.h"
35#include "arm_compute/core/Types.h"
Gian Marco Iodicebb36a8e2018-04-19 12:05:08 +010036#include "arm_compute/core/Utils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010037#include "arm_compute/core/Validate.h"
Gian Marco Iodicee16c8902019-06-14 16:11:10 +010038#include "arm_compute/core/utils/helpers/float_ops.h"
Michalis Spyroub27e13a2019-09-27 11:04:27 +010039#include "arm_compute/core/utils/misc/Cast.h"
Gian Marco Iodice750641d2018-05-08 12:01:57 +010040#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010041#include "arm_compute/runtime/CL/CLScheduler.h"
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000042#include "arm_compute/runtime/CL/gemm/CLGEMMKernelSelection.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010043#include "arm_compute/runtime/ITensorAllocator.h"
44
giuros011c9efeb2019-01-11 14:04:43 +000045namespace arm_compute
46{
Gian Marco Iodice750641d2018-05-08 12:01:57 +010047using namespace arm_compute::misc::shape_calculator;
Gian Marco Iodice90313eb2019-01-16 15:40:25 +000048using namespace arm_compute::cl_gemm;
Michalis Spyroub27e13a2019-09-27 11:04:27 +010049using namespace arm_compute::utils::cast;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010050
Michalis Spyroub27e13a2019-09-27 11:04:27 +010051CLGEMM::CLGEMM(std::shared_ptr<IMemoryManager> memory_manager, IWeightsManager *weights_manager)
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010052 : _memory_group(std::move(memory_manager)),
Michalis Spyroub27e13a2019-09-27 11:04:27 +010053 _weights_manager(weights_manager),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010054 _mm_kernel(),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000055 _reshape_lhs_kernel(),
56 _reshape_rhs_kernel(),
Michalis Spyroub27e13a2019-09-27 11:04:27 +010057 _reshape_rhs_kernel_managed(),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000058 _mm_reshaped_kernel(),
Gian Marco Iodice926afe12019-03-19 11:44:13 +000059 _mm_reshaped_only_rhs_kernel(),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010060 _tmp_a(),
61 _tmp_b(),
62 _original_b(nullptr),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010063 _reshape_b_only_on_first_run(false),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000064 _is_prepared(false),
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000065 _gemm_kernel_type(CLGEMMKernelType::NATIVE_V1)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010066{
67}
68
Gian Marco Iodice026d0452020-08-28 13:52:12 +010069CLGEMMKernelType 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 +010070{
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000071 std::unique_ptr<ICLGEMMKernelSelection> gemm_kernel = CLGEMMKernelSelectionFactory::create(CLScheduler::get().target());
72 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_kernel.get());
Anthony Barbier6ff3b192017-09-04 18:44:23 +010073
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000074 CLGEMMKernelSelectionParams params;
75 params.m = m;
76 params.n = n;
77 params.k = k;
Gian Marco Iodice026d0452020-08-28 13:52:12 +010078 params.b = b;
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000079 params.is_rhs_constant = reshape_b_only_on_first_run;
80 params.data_type = data_type;
Gian Marco Iodice05639f62019-09-24 12:05:06 +010081
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000082 return gemm_kernel->select_kernel(params);
Gian Marco Iodice926afe12019-03-19 11:44:13 +000083}
84
Manuel Bottini2b84be52020-04-08 10:15:51 +010085void CLGEMM::configure_native_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
86 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +000087{
88 const unsigned int m = gemm_info.reinterpret_input_as_3d() ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
89 const unsigned int n = b->info()->dimension(0);
90 const unsigned int k = a->info()->dimension(0);
91 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco36a0a462018-01-12 10:21:40 +000092
93 // Set the target for the kernels
Gian Marco36a0a462018-01-12 10:21:40 +000094 _mm_kernel.set_target(gpu_target);
95
Gian Marco Iodicef3622be2019-07-29 14:27:16 +010096 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 +000097
98 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +010099 _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 +0000100
101 // Tune kernel statically
102 CLScheduler::get().tune_kernel_static(_mm_kernel);
103}
104
Manuel Bottini2b84be52020-04-08 10:15:51 +0100105void CLGEMM::configure_reshaped_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
106 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000107{
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000108 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
109 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
110 const unsigned int n = b->info()->dimension(0);
111 const unsigned int k = a->info()->dimension(0);
112 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000113 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000114 int mult_transpose1xW_width = 1;
115 int mult_interleave4x4_height = 1;
Gian Marco36a0a462018-01-12 10:21:40 +0000116
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000117 // Set the target for the kernels
118 _reshape_lhs_kernel.set_target(gpu_target);
119 _mm_kernel.set_target(gpu_target);
120
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100121 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
Gian Marco36a0a462018-01-12 10:21:40 +0000122 {
123 mult_transpose1xW_width = 4;
124 mult_interleave4x4_height = 2;
125 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000126
giuros018b6b4a92018-12-18 19:01:33 +0000127 GEMMRHSMatrixInfo rhs_info;
128 rhs_info.n0 = 16 / b->info()->element_size();
129 rhs_info.k0 = 1;
130 rhs_info.h0 = mult_transpose1xW_width;
131 rhs_info.interleave = false;
132 rhs_info.transpose = false;
Gian Marco36a0a462018-01-12 10:21:40 +0000133
giuros011c9efeb2019-01-11 14:04:43 +0000134 GEMMLHSMatrixInfo lhs_info;
135 lhs_info.m0 = 4;
136 lhs_info.k0 = 4;
137 lhs_info.v0 = mult_interleave4x4_height;
138 lhs_info.interleave = true;
139 lhs_info.transpose = true;
140
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100141 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 +0000142
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100143 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
144
145 // Manage intermediate buffers
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000146 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100147
148 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice68a3f562018-07-26 11:44:03 +0100149 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000150 _memory_group.manage(&_tmp_b);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100151 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100152
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000153 // Configure interleave kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100154 _reshape_lhs_kernel.configure(compile_context, a, &_tmp_a, lhs_info, reinterpret_input_as_3d);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100155
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000156 // Configure transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100157 ICLTensor *reshaped_rhs = &_tmp_b;
158 if(_weights_manager && _weights_manager->are_weights_managed(b))
159 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100160 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100161 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
162 }
163 else
164 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100165 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100166 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100167
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000168 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100169 _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 +0000170
171 CLScheduler::get().tune_kernel_static(_mm_kernel);
172
173 // Allocate intermediate tensors
174 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100175
176 if(!_reshape_b_only_on_first_run && use_mm_b)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100177 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000178 _tmp_b.allocator()->allocate();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100179 }
180}
181
Manuel Bottini2b84be52020-04-08 10:15:51 +0100182void CLGEMM::configure_reshaped_v2(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
183 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000184{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000185 DataType data_type = a->info()->data_type();
186 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
187 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
188 const unsigned int n = b->info()->dimension(0);
189 const unsigned int k = a->info()->dimension(0);
190 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
191 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
192 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100193 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100194
195 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100196 kernel_info.m = m;
197 kernel_info.n = n;
198 kernel_info.k = k;
199 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
200 kernel_info.reinterpret_input_as_3d = false;
201 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100202 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000203
204 // Set the target for the kernels
205 _reshape_lhs_kernel.set_target(gpu_target);
206 _mm_kernel.set_target(gpu_target);
207
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100208 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
209
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000210 // Manage intermediate buffers
211 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100212
213 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000214 {
215 _memory_group.manage(&_tmp_b);
216 }
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100217
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000218 // _tmp_a and _tmp_b will be auto configured in _interleave_kernel and in _transpose_kernel
219
220 GEMMLHSMatrixInfo lhs_info{};
221 GEMMRHSMatrixInfo rhs_info{};
222
223 // Pick up the GEMM configuration
224 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
225 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
226
227 // Configure lhs_info and rhs_info
228 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
229
Manuel Bottini2b84be52020-04-08 10:15:51 +0100230 _reshape_lhs_kernel.configure(compile_context, a, &_tmp_a, lhs_info, gemm_info.reinterpret_input_as_3d());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100231
232 ICLTensor *reshaped_rhs = &_tmp_b;
233 if(_weights_manager && _weights_manager->are_weights_managed(b))
234 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100235 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100236 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
237 }
238 else
239 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100240 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100241 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000242
243 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100244 _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 +0000245
246 // Allocate intermediate tensors
247 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100248
249 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000250 {
251 _tmp_b.allocator()->allocate();
252 }
253}
254
Manuel Bottini2b84be52020-04-08 10:15:51 +0100255void CLGEMM::configure_reshaped_only_rhs(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
256 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000257{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000258 DataType data_type = a->info()->data_type();
259 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
260 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
261 const unsigned int n = b->info()->dimension(0);
262 const unsigned int k = a->info()->dimension(0);
263 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
264 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
265 const GPUTarget gpu_target = CLScheduler::get().target();
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100266 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100267
268 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100269 kernel_info.m = m;
270 kernel_info.n = n;
271 kernel_info.k = k;
272 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
273 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
274 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100275 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000276
277 // Set the target for the kernels
278 _mm_kernel.set_target(gpu_target);
279
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100280 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
281
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000282 // Manage intermediate buffers
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100283 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000284 {
285 _memory_group.manage(&_tmp_b);
286 }
287
288 GEMMLHSMatrixInfo lhs_info{};
289 GEMMRHSMatrixInfo rhs_info{};
290
291 // Pick up the GEMM configuration
292 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
293 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
294
Gian Marco Iodicec6eaec32020-07-20 13:31:05 +0100295 unsigned int m_internal = m;
296 unsigned int b_internal = batch_size;
297 if(reinterpret_input_as_3d)
298 {
299 m_internal = a->info()->dimension(1);
300 b_internal = a->info()->dimension(2);
301 }
302
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000303 // Configure lhs_info and rhs_info
Gian Marco Iodicec6eaec32020-07-20 13:31:05 +0100304 std::tie(lhs_info, rhs_info) = gemm_config->configure(m_internal, n, k, b_internal, data_type);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000305
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100306 ICLTensor *reshaped_rhs = &_tmp_b;
307 if(_weights_manager && _weights_manager->are_weights_managed(b))
308 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100309 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100310 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
311 }
312 else
313 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100314 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100315 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000316
317 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100318 _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 +0000319
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100320 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000321 {
322 _tmp_b.allocator()->allocate();
323 }
324}
325
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000326Status 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 +0000327{
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100328 ARM_COMPUTE_UNUSED(alpha);
Gian Marco Iodice215b4ea2018-06-28 16:29:29 +0100329 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100330
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000331 // Get the GPU target
332 const GPUTarget gpu_target = CLScheduler::get().target();
333 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
334 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
335 const unsigned int n = b->dimension(0);
336 const unsigned int k = a->dimension(0);
337 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100338
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100339 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 +0000340
341 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100342 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(a, b, c, output, alpha, beta,
343 false, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000344
345 return Status{};
346}
347
348Status CLGEMM::validate_reshaped_v1(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
349{
350 ARM_COMPUTE_UNUSED(alpha);
351 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100352
353 TensorInfo tmp_a_info{};
354 TensorInfo tmp_b_info{};
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100355
356 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000357 const GPUTarget gpu_target = CLScheduler::get().target();
358 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 +0000359 const unsigned int n = b->dimension(0);
360 const unsigned int k = a->dimension(0);
361 int mult_transpose1xW_width = 1;
362 int mult_interleave4x4_height = 1;
363 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100364
365 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
366 {
367 mult_transpose1xW_width = 4;
368 mult_interleave4x4_height = 2;
369 }
370
giuros018b6b4a92018-12-18 19:01:33 +0000371 GEMMRHSMatrixInfo rhs_info;
372 rhs_info.n0 = 16 / b->element_size();
373 rhs_info.k0 = 1;
374 rhs_info.h0 = mult_transpose1xW_width;
375 rhs_info.interleave = false;
376 rhs_info.transpose = false;
377
giuros011c9efeb2019-01-11 14:04:43 +0000378 GEMMLHSMatrixInfo lhs_info;
379 lhs_info.m0 = 4;
380 lhs_info.k0 = 4;
381 lhs_info.v0 = mult_interleave4x4_height;
382 lhs_info.interleave = true;
383 lhs_info.transpose = true;
384
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100385 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 +0100386
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000387 // Validate interleave kernel
388 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())));
389 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 +0000390
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000391 // Validate transpose kernel
392 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
393 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
Michele Di Giorgioebc3a902018-11-16 16:04:25 +0000394
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000395 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100396 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(&tmp_a_info, &tmp_b_info, c, output, alpha, beta,
397 true, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100398
Georgios Pinitas78c00902018-01-09 17:33:11 +0000399 return Status{};
400}
401
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000402Status 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 +0000403{
404 ARM_COMPUTE_UNUSED(alpha);
405 ARM_COMPUTE_UNUSED(output);
406
407 TensorInfo tmp_a_info{};
408 TensorInfo tmp_b_info{};
409
410 // Get the GPU target
411 const GPUTarget gpu_target = CLScheduler::get().target();
412 DataType data_type = a->data_type();
413 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
414 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
415 const unsigned int n = b->dimension(0);
416 const unsigned int k = a->dimension(0);
417 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
418 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100419 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100420
421 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100422 kernel_info.m = m;
423 kernel_info.n = n;
424 kernel_info.k = k;
425 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
426 kernel_info.reinterpret_input_as_3d = false;
427 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100428 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000429
430 GEMMLHSMatrixInfo lhs_info;
431 GEMMRHSMatrixInfo rhs_info;
432
433 // Pick up the GEMM configuration
434 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
435 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
436
437 // Configure lhs_info and rhs_info
438 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
439
440 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())));
441 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeLHSMatrixKernel::validate(a, &tmp_a_info, lhs_info, gemm_info.reinterpret_input_as_3d()));
442
443 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
444 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
445
446 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100447 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 +0000448
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000449 return Status{};
450}
451
452Status 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)
453{
454 ARM_COMPUTE_UNUSED(alpha);
455 ARM_COMPUTE_UNUSED(output);
456
457 TensorInfo tmp_b_info{};
458
459 // Get the GPU target
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100460 const GPUTarget gpu_target = CLScheduler::get().target();
461 const DataType data_type = a->data_type();
462 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
463 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
464 const unsigned int n = b->dimension(0);
465 const unsigned int k = a->dimension(0);
466 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
467 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
468 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100469
470 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100471 kernel_info.m = m;
472 kernel_info.n = n;
473 kernel_info.k = k;
474 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
475 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
476 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100477 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000478
479 GEMMLHSMatrixInfo lhs_info;
480 GEMMRHSMatrixInfo rhs_info;
481
482 // Pick up the GEMM configuration
483 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
484 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
485
486 // Configure lhs_info and rhs_info
487 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
488
489 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
490 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
491
492 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100493 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 +0000494
495 return Status{};
496}
497
498void CLGEMM::configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
499{
Manuel Bottini2b84be52020-04-08 10:15:51 +0100500 configure(CLKernelLibrary::get().get_compile_context(), a, b, c, output, alpha, beta, gemm_info);
501}
502
503void 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)
504{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000505 ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, output);
506
507 // Perform validation step
508 ARM_COMPUTE_ERROR_THROW_ON(validate(a->info(), b->info(), c != nullptr ? c->info() : nullptr, output->info(), alpha, beta, gemm_info));
509
510 // Check if we need to reshape the matrix B only on the first run
511 _reshape_b_only_on_first_run = gemm_info.reshape_b_only_on_first_run();
512 _is_prepared = gemm_info.retain_internal_weights();
513 _original_b = b;
514
515 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000516 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
517 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
518 const unsigned int n = b->info()->dimension(0);
519 const unsigned int k = a->info()->dimension(0);
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100520 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 +0000521
522 // Select GEMMType
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100523 _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 +0000524
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100525 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100526
527 const ICLTensor *c_to_use = fuse_add_c ? c : nullptr;
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000528
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000529 switch(_gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000530 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000531 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000532 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100533 configure_native_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000534 break;
535 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000536 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000537 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100538 configure_reshaped_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000539 break;
540 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000541 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000542 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100543 configure_reshaped_v2(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000544 break;
545 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000546 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000547 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100548 configure_reshaped_only_rhs(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000549 break;
550 }
551 default:
552 {
553 ARM_COMPUTE_ERROR("GEMMType not supported");
554 }
555 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000556}
557
558Status CLGEMM::validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
559{
560 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000561 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
562 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
563 const unsigned int n = b->dimension(0);
564 const unsigned int k = a->dimension(0);
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100565 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000566
567 // Select GEMMType
Gian Marco Iodice026d0452020-08-28 13:52:12 +0100568 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 +0000569
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100570 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100571
572 const ITensorInfo *c_to_use = fuse_add_c ? c : nullptr;
573
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000574 switch(gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000575 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000576 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000577 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000578 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 +0000579 break;
580 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000581 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000582 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100583 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 +0000584 break;
585 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000586 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000587 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000588 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 +0000589 break;
590 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000591 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000592 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100593 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 +0000594 break;
595 }
596 default:
597 {
598 ARM_COMPUTE_RETURN_ERROR_MSG("GEMMType not supported");
599 }
600 }
601
602 return Status{};
603}
604
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100605void CLGEMM::run()
606{
Georgios Pinitase0437672018-05-02 14:07:55 +0100607 prepare();
608
Georgios Pinitasda953f22019-04-02 17:27:03 +0100609 MemoryGroupResourceScope scope_mg(_memory_group);
Georgios Pinitas8a94e7c2017-09-15 19:06:47 +0100610
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100611 // Run matrix multiply kernel
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000612 switch(_gemm_kernel_type)
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000613 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000614 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000615 {
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100616 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000617 break;
618 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000619 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000620 {
621 // Run interleave kernel
622 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
623
624 if(!_reshape_b_only_on_first_run)
625 {
626 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100627 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
628 {
629 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
630 }
631 else
632 {
633 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
634 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000635 }
636
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100637 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000638 break;
639 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000640 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000641 {
642 // Run interleave kernel
643 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
644
645 if(!_reshape_b_only_on_first_run)
646 {
647 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100648 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
649 {
650 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
651 }
652 else
653 {
654 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
655 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000656 }
657
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100658 CLScheduler::get().enqueue(_mm_reshaped_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000659 break;
660 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000661 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000662 {
663 if(!_reshape_b_only_on_first_run)
664 {
665 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100666 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
667 {
668 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
669 }
670 else
671 {
672 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
673 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000674 }
675
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100676 CLScheduler::get().enqueue(_mm_reshaped_only_rhs_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000677 break;
678 }
679 default:
680 {
681 ARM_COMPUTE_ERROR("GEMMType not supported");
682 }
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000683 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100684}
Georgios Pinitas82b51482018-04-24 15:14:12 +0100685
Georgios Pinitase0437672018-05-02 14:07:55 +0100686void CLGEMM::prepare()
687{
688 if(!_is_prepared)
689 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000690 if(_gemm_kernel_type != CLGEMMKernelType::NATIVE_V1 && _reshape_b_only_on_first_run)
Georgios Pinitase0437672018-05-02 14:07:55 +0100691 {
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100692 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
693 {
694 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
695 }
696 else
697 {
698 // Run transpose kernel and mark original weights tensor as unused
699 _tmp_b.allocator()->allocate();
700 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
701 _original_b->mark_as_unused();
702 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100703 }
704 CLScheduler::get().queue().finish();
705 _is_prepared = true;
706 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100707}
giuros011c9efeb2019-01-11 14:04:43 +0000708} // namespace arm_compute