blob: 4a74630036be36fd0dbf9dd714e9acdbf4e4326d [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 Iodice5a4fe192020-03-16 12:22:37 +000069CLGEMMKernelType CLGEMM::select_gemm_kernel(unsigned int m, unsigned int n, unsigned int k, 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;
78 params.is_rhs_constant = reshape_b_only_on_first_run;
79 params.data_type = data_type;
Gian Marco Iodice05639f62019-09-24 12:05:06 +010080
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +000081 return gemm_kernel->select_kernel(params);
Gian Marco Iodice926afe12019-03-19 11:44:13 +000082}
83
Manuel Bottini2b84be52020-04-08 10:15:51 +010084void CLGEMM::configure_native_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
85 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +000086{
87 const unsigned int m = gemm_info.reinterpret_input_as_3d() ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
88 const unsigned int n = b->info()->dimension(0);
89 const unsigned int k = a->info()->dimension(0);
90 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco36a0a462018-01-12 10:21:40 +000091
92 // Set the target for the kernels
Gian Marco36a0a462018-01-12 10:21:40 +000093 _mm_kernel.set_target(gpu_target);
94
Gian Marco Iodicef3622be2019-07-29 14:27:16 +010095 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 +000096
97 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +010098 _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 +000099
100 // Tune kernel statically
101 CLScheduler::get().tune_kernel_static(_mm_kernel);
102}
103
Manuel Bottini2b84be52020-04-08 10:15:51 +0100104void CLGEMM::configure_reshaped_v1(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
105 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000106{
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000107 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
108 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
109 const unsigned int n = b->info()->dimension(0);
110 const unsigned int k = a->info()->dimension(0);
111 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000112 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000113 int mult_transpose1xW_width = 1;
114 int mult_interleave4x4_height = 1;
Gian Marco36a0a462018-01-12 10:21:40 +0000115
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000116 // Set the target for the kernels
117 _reshape_lhs_kernel.set_target(gpu_target);
118 _mm_kernel.set_target(gpu_target);
119
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100120 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
Gian Marco36a0a462018-01-12 10:21:40 +0000121 {
122 mult_transpose1xW_width = 4;
123 mult_interleave4x4_height = 2;
124 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000125
giuros018b6b4a92018-12-18 19:01:33 +0000126 GEMMRHSMatrixInfo rhs_info;
127 rhs_info.n0 = 16 / b->info()->element_size();
128 rhs_info.k0 = 1;
129 rhs_info.h0 = mult_transpose1xW_width;
130 rhs_info.interleave = false;
131 rhs_info.transpose = false;
Gian Marco36a0a462018-01-12 10:21:40 +0000132
giuros011c9efeb2019-01-11 14:04:43 +0000133 GEMMLHSMatrixInfo lhs_info;
134 lhs_info.m0 = 4;
135 lhs_info.k0 = 4;
136 lhs_info.v0 = mult_interleave4x4_height;
137 lhs_info.interleave = true;
138 lhs_info.transpose = true;
139
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100140 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 +0000141
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100142 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
143
144 // Manage intermediate buffers
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000145 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100146
147 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice68a3f562018-07-26 11:44:03 +0100148 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000149 _memory_group.manage(&_tmp_b);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100150 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100151
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000152 // Configure interleave kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100153 _reshape_lhs_kernel.configure(compile_context, a, &_tmp_a, lhs_info, reinterpret_input_as_3d);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100154
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000155 // Configure transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100156 ICLTensor *reshaped_rhs = &_tmp_b;
157 if(_weights_manager && _weights_manager->are_weights_managed(b))
158 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100159 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100160 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
161 }
162 else
163 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100164 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100165 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100166
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000167 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100168 _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 +0000169
170 CLScheduler::get().tune_kernel_static(_mm_kernel);
171
172 // Allocate intermediate tensors
173 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100174
175 if(!_reshape_b_only_on_first_run && use_mm_b)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100176 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000177 _tmp_b.allocator()->allocate();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100178 }
179}
180
Manuel Bottini2b84be52020-04-08 10:15:51 +0100181void CLGEMM::configure_reshaped_v2(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
182 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000183{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000184 DataType data_type = a->info()->data_type();
185 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
186 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
187 const unsigned int n = b->info()->dimension(0);
188 const unsigned int k = a->info()->dimension(0);
189 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
190 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
191 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100192 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100193
194 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100195 kernel_info.m = m;
196 kernel_info.n = n;
197 kernel_info.k = k;
198 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
199 kernel_info.reinterpret_input_as_3d = false;
200 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100201 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000202
203 // Set the target for the kernels
204 _reshape_lhs_kernel.set_target(gpu_target);
205 _mm_kernel.set_target(gpu_target);
206
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100207 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
208
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000209 // Manage intermediate buffers
210 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100211
212 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000213 {
214 _memory_group.manage(&_tmp_b);
215 }
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100216
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000217 // _tmp_a and _tmp_b will be auto configured in _interleave_kernel and in _transpose_kernel
218
219 GEMMLHSMatrixInfo lhs_info{};
220 GEMMRHSMatrixInfo rhs_info{};
221
222 // Pick up the GEMM configuration
223 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
224 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
225
226 // Configure lhs_info and rhs_info
227 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
228
Manuel Bottini2b84be52020-04-08 10:15:51 +0100229 _reshape_lhs_kernel.configure(compile_context, a, &_tmp_a, lhs_info, gemm_info.reinterpret_input_as_3d());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100230
231 ICLTensor *reshaped_rhs = &_tmp_b;
232 if(_weights_manager && _weights_manager->are_weights_managed(b))
233 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100234 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100235 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
236 }
237 else
238 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100239 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100240 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000241
242 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100243 _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 +0000244
245 // Allocate intermediate tensors
246 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100247
248 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000249 {
250 _tmp_b.allocator()->allocate();
251 }
252}
253
Manuel Bottini2b84be52020-04-08 10:15:51 +0100254void CLGEMM::configure_reshaped_only_rhs(const CLCompileContext &compile_context, const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta,
255 const GEMMInfo &gemm_info)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000256{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000257 DataType data_type = a->info()->data_type();
258 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
259 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
260 const unsigned int n = b->info()->dimension(0);
261 const unsigned int k = a->info()->dimension(0);
262 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
263 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
264 const GPUTarget gpu_target = CLScheduler::get().target();
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100265 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100266
267 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100268 kernel_info.m = m;
269 kernel_info.n = n;
270 kernel_info.k = k;
271 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
272 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
273 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100274 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000275
276 // Set the target for the kernels
277 _mm_kernel.set_target(gpu_target);
278
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100279 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
280
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000281 // Manage intermediate buffers
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100282 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000283 {
284 _memory_group.manage(&_tmp_b);
285 }
286
287 GEMMLHSMatrixInfo lhs_info{};
288 GEMMRHSMatrixInfo rhs_info{};
289
290 // Pick up the GEMM configuration
291 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
292 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
293
Gian Marco Iodicec6eaec32020-07-20 13:31:05 +0100294 unsigned int m_internal = m;
295 unsigned int b_internal = batch_size;
296 if(reinterpret_input_as_3d)
297 {
298 m_internal = a->info()->dimension(1);
299 b_internal = a->info()->dimension(2);
300 }
301
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000302 // Configure lhs_info and rhs_info
Gian Marco Iodicec6eaec32020-07-20 13:31:05 +0100303 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 +0000304
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100305 ICLTensor *reshaped_rhs = &_tmp_b;
306 if(_weights_manager && _weights_manager->are_weights_managed(b))
307 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100308 _reshape_rhs_kernel_managed.configure(compile_context, b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100309 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
310 }
311 else
312 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100313 _reshape_rhs_kernel.configure(compile_context, b, &_tmp_b, rhs_info);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100314 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000315
316 // Configure and tune matrix multiply kernel
Manuel Bottini2b84be52020-04-08 10:15:51 +0100317 _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 +0000318
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100319 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000320 {
321 _tmp_b.allocator()->allocate();
322 }
323}
324
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000325Status 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 +0000326{
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100327 ARM_COMPUTE_UNUSED(alpha);
Gian Marco Iodice215b4ea2018-06-28 16:29:29 +0100328 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100329
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000330 // Get the GPU target
331 const GPUTarget gpu_target = CLScheduler::get().target();
332 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
333 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
334 const unsigned int n = b->dimension(0);
335 const unsigned int k = a->dimension(0);
336 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100337
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100338 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 +0000339
340 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100341 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(a, b, c, output, alpha, beta,
342 false, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000343
344 return Status{};
345}
346
347Status CLGEMM::validate_reshaped_v1(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
348{
349 ARM_COMPUTE_UNUSED(alpha);
350 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100351
352 TensorInfo tmp_a_info{};
353 TensorInfo tmp_b_info{};
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100354
355 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000356 const GPUTarget gpu_target = CLScheduler::get().target();
357 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 +0000358 const unsigned int n = b->dimension(0);
359 const unsigned int k = a->dimension(0);
360 int mult_transpose1xW_width = 1;
361 int mult_interleave4x4_height = 1;
362 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100363
364 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
365 {
366 mult_transpose1xW_width = 4;
367 mult_interleave4x4_height = 2;
368 }
369
giuros018b6b4a92018-12-18 19:01:33 +0000370 GEMMRHSMatrixInfo rhs_info;
371 rhs_info.n0 = 16 / b->element_size();
372 rhs_info.k0 = 1;
373 rhs_info.h0 = mult_transpose1xW_width;
374 rhs_info.interleave = false;
375 rhs_info.transpose = false;
376
giuros011c9efeb2019-01-11 14:04:43 +0000377 GEMMLHSMatrixInfo lhs_info;
378 lhs_info.m0 = 4;
379 lhs_info.k0 = 4;
380 lhs_info.v0 = mult_interleave4x4_height;
381 lhs_info.interleave = true;
382 lhs_info.transpose = true;
383
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100384 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 +0100385
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000386 // Validate interleave kernel
387 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())));
388 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 +0000389
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000390 // Validate transpose kernel
391 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
392 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
Michele Di Giorgioebc3a902018-11-16 16:04:25 +0000393
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000394 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100395 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(&tmp_a_info, &tmp_b_info, c, output, alpha, beta,
396 true, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100397
Georgios Pinitas78c00902018-01-09 17:33:11 +0000398 return Status{};
399}
400
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000401Status 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 +0000402{
403 ARM_COMPUTE_UNUSED(alpha);
404 ARM_COMPUTE_UNUSED(output);
405
406 TensorInfo tmp_a_info{};
407 TensorInfo tmp_b_info{};
408
409 // Get the GPU target
410 const GPUTarget gpu_target = CLScheduler::get().target();
411 DataType data_type = a->data_type();
412 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
413 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
414 const unsigned int n = b->dimension(0);
415 const unsigned int k = a->dimension(0);
416 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
417 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100418 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100419
420 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100421 kernel_info.m = m;
422 kernel_info.n = n;
423 kernel_info.k = k;
424 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
425 kernel_info.reinterpret_input_as_3d = false;
426 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100427 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000428
429 GEMMLHSMatrixInfo lhs_info;
430 GEMMRHSMatrixInfo rhs_info;
431
432 // Pick up the GEMM configuration
433 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
434 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
435
436 // Configure lhs_info and rhs_info
437 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
438
439 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())));
440 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeLHSMatrixKernel::validate(a, &tmp_a_info, lhs_info, gemm_info.reinterpret_input_as_3d()));
441
442 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
443 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
444
445 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100446 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 +0000447
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000448 return Status{};
449}
450
451Status 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)
452{
453 ARM_COMPUTE_UNUSED(alpha);
454 ARM_COMPUTE_UNUSED(output);
455
456 TensorInfo tmp_b_info{};
457
458 // Get the GPU target
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100459 const GPUTarget gpu_target = CLScheduler::get().target();
460 const DataType data_type = a->data_type();
461 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
462 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
463 const unsigned int n = b->dimension(0);
464 const unsigned int k = a->dimension(0);
465 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
466 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
467 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100468
469 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100470 kernel_info.m = m;
471 kernel_info.n = n;
472 kernel_info.k = k;
473 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
474 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
475 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100476 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000477
478 GEMMLHSMatrixInfo lhs_info;
479 GEMMRHSMatrixInfo rhs_info;
480
481 // Pick up the GEMM configuration
482 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
483 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
484
485 // Configure lhs_info and rhs_info
486 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
487
488 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
489 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
490
491 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100492 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 +0000493
494 return Status{};
495}
496
497void CLGEMM::configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
498{
Manuel Bottini2b84be52020-04-08 10:15:51 +0100499 configure(CLKernelLibrary::get().get_compile_context(), a, b, c, output, alpha, beta, gemm_info);
500}
501
502void 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)
503{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000504 ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, output);
505
506 // Perform validation step
507 ARM_COMPUTE_ERROR_THROW_ON(validate(a->info(), b->info(), c != nullptr ? c->info() : nullptr, output->info(), alpha, beta, gemm_info));
508
509 // Check if we need to reshape the matrix B only on the first run
510 _reshape_b_only_on_first_run = gemm_info.reshape_b_only_on_first_run();
511 _is_prepared = gemm_info.retain_internal_weights();
512 _original_b = b;
513
514 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000515 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
516 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
517 const unsigned int n = b->info()->dimension(0);
518 const unsigned int k = a->info()->dimension(0);
519
520 // Select GEMMType
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000521 _gemm_kernel_type = select_gemm_kernel(m, n, k, a->info()->data_type(), _reshape_b_only_on_first_run);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000522
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100523 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100524
525 const ICLTensor *c_to_use = fuse_add_c ? c : nullptr;
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000526
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000527 switch(_gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000528 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000529 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000530 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100531 configure_native_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000532 break;
533 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000534 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000535 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100536 configure_reshaped_v1(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000537 break;
538 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000539 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000540 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100541 configure_reshaped_v2(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000542 break;
543 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000544 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000545 {
Manuel Bottini2b84be52020-04-08 10:15:51 +0100546 configure_reshaped_only_rhs(compile_context, a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000547 break;
548 }
549 default:
550 {
551 ARM_COMPUTE_ERROR("GEMMType not supported");
552 }
553 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000554}
555
556Status CLGEMM::validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
557{
558 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000559 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
560 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
561 const unsigned int n = b->dimension(0);
562 const unsigned int k = a->dimension(0);
563
564 // Select GEMMType
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000565 CLGEMMKernelType gemm_kernel_type = select_gemm_kernel(m, n, k, a->data_type(), gemm_info.reshape_b_only_on_first_run());
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000566
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100567 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100568
569 const ITensorInfo *c_to_use = fuse_add_c ? c : nullptr;
570
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000571 switch(gemm_kernel_type)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000572 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000573 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000574 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000575 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 +0000576 break;
577 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000578 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000579 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100580 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 +0000581 break;
582 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000583 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000584 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000585 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 +0000586 break;
587 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000588 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000589 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100590 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 +0000591 break;
592 }
593 default:
594 {
595 ARM_COMPUTE_RETURN_ERROR_MSG("GEMMType not supported");
596 }
597 }
598
599 return Status{};
600}
601
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100602void CLGEMM::run()
603{
Georgios Pinitase0437672018-05-02 14:07:55 +0100604 prepare();
605
Georgios Pinitasda953f22019-04-02 17:27:03 +0100606 MemoryGroupResourceScope scope_mg(_memory_group);
Georgios Pinitas8a94e7c2017-09-15 19:06:47 +0100607
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100608 // Run matrix multiply kernel
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000609 switch(_gemm_kernel_type)
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000610 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000611 case CLGEMMKernelType::NATIVE_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000612 {
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100613 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000614 break;
615 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000616 case CLGEMMKernelType::RESHAPED_V1:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000617 {
618 // Run interleave kernel
619 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
620
621 if(!_reshape_b_only_on_first_run)
622 {
623 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100624 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
625 {
626 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
627 }
628 else
629 {
630 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
631 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000632 }
633
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100634 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000635 break;
636 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000637 case CLGEMMKernelType::RESHAPED:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000638 {
639 // Run interleave kernel
640 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
641
642 if(!_reshape_b_only_on_first_run)
643 {
644 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100645 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
646 {
647 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
648 }
649 else
650 {
651 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
652 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000653 }
654
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100655 CLScheduler::get().enqueue(_mm_reshaped_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000656 break;
657 }
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000658 case CLGEMMKernelType::RESHAPED_ONLY_RHS:
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000659 {
660 if(!_reshape_b_only_on_first_run)
661 {
662 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100663 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
664 {
665 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
666 }
667 else
668 {
669 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
670 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000671 }
672
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100673 CLScheduler::get().enqueue(_mm_reshaped_only_rhs_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000674 break;
675 }
676 default:
677 {
678 ARM_COMPUTE_ERROR("GEMMType not supported");
679 }
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000680 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100681}
Georgios Pinitas82b51482018-04-24 15:14:12 +0100682
Georgios Pinitase0437672018-05-02 14:07:55 +0100683void CLGEMM::prepare()
684{
685 if(!_is_prepared)
686 {
Gian Marco Iodice5a4fe192020-03-16 12:22:37 +0000687 if(_gemm_kernel_type != CLGEMMKernelType::NATIVE_V1 && _reshape_b_only_on_first_run)
Georgios Pinitase0437672018-05-02 14:07:55 +0100688 {
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100689 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
690 {
691 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
692 }
693 else
694 {
695 // Run transpose kernel and mark original weights tensor as unused
696 _tmp_b.allocator()->allocate();
697 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
698 _original_b->mark_as_unused();
699 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100700 }
701 CLScheduler::get().queue().finish();
702 _is_prepared = true;
703 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100704}
giuros011c9efeb2019-01-11 14:04:43 +0000705} // namespace arm_compute