blob: 09b63970564b26fa4049f7f0d6b1e28695d6e67b [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Giorgio Arena695ad692020-02-07 10:28:45 +00002 * 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"
42#include "arm_compute/runtime/ITensorAllocator.h"
43
giuros011c9efeb2019-01-11 14:04:43 +000044namespace arm_compute
45{
Gian Marco Iodice750641d2018-05-08 12:01:57 +010046using namespace arm_compute::misc::shape_calculator;
Gian Marco Iodice90313eb2019-01-16 15:40:25 +000047using namespace arm_compute::cl_gemm;
Michalis Spyroub27e13a2019-09-27 11:04:27 +010048using namespace arm_compute::utils::cast;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010049
Michalis Spyroub27e13a2019-09-27 11:04:27 +010050CLGEMM::CLGEMM(std::shared_ptr<IMemoryManager> memory_manager, IWeightsManager *weights_manager)
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010051 : _memory_group(std::move(memory_manager)),
Michalis Spyroub27e13a2019-09-27 11:04:27 +010052 _weights_manager(weights_manager),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010053 _mm_kernel(),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000054 _reshape_lhs_kernel(),
55 _reshape_rhs_kernel(),
Michalis Spyroub27e13a2019-09-27 11:04:27 +010056 _reshape_rhs_kernel_managed(),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000057 _mm_reshaped_kernel(),
Gian Marco Iodice926afe12019-03-19 11:44:13 +000058 _mm_reshaped_only_rhs_kernel(),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010059 _tmp_a(),
60 _tmp_b(),
61 _original_b(nullptr),
Georgios Pinitasebf6b8a2018-09-24 16:31:08 +010062 _reshape_b_only_on_first_run(false),
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +000063 _is_prepared(false),
Gian Marco Iodice926afe12019-03-19 11:44:13 +000064 _gemm_type(GEMMType::NATIVE)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065{
66}
67
Gian Marco Iodice926afe12019-03-19 11:44:13 +000068CLGEMM::GEMMType CLGEMM::select_gemm_type(unsigned int m, unsigned int n, unsigned int k, DataType data_type, bool reshape_b_only_on_first_run, GPUTarget gpu_target)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010069{
Gian Marco Iodice926afe12019-03-19 11:44:13 +000070 GEMMType gemm_type = GEMMType::RESHAPED_V1;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010071
Gian Marco Iodice05639f62019-09-24 12:05:06 +010072 if(gpu_target_is_in(gpu_target, GPUTarget::G51, GPUTarget::G51BIG, GPUTarget::G51LIT,
73 GPUTarget::G52, GPUTarget::G52LIT, GPUTarget::G71, GPUTarget::G72,
74 GPUTarget::G76, GPUTarget::G77))
Gian Marco Iodice926afe12019-03-19 11:44:13 +000075 {
Gian Marco Iodice05639f62019-09-24 12:05:06 +010076 if(data_type == DataType::F32)
Gian Marco Iodice926afe12019-03-19 11:44:13 +000077 {
Gian Marco Iodice05639f62019-09-24 12:05:06 +010078 if((m > 1) && (n < 16))
Gian Marco Iodice926afe12019-03-19 11:44:13 +000079 {
Gian Marco Iodice12f2b8c2020-02-13 12:27:37 +000080 gemm_type = GEMMType::RESHAPED_V2;
Gian Marco Iodice05639f62019-09-24 12:05:06 +010081 }
82 else if(m == 1)
83 {
84 gemm_type = GEMMType::RESHAPED_ONLY_RHS;
Gian Marco Iodice926afe12019-03-19 11:44:13 +000085 }
86 else
87 {
Gian Marco Iodice05639f62019-09-24 12:05:06 +010088 // COMPMID-852
89 if((k > 256) && (m > 4) && reshape_b_only_on_first_run)
90 {
91 constexpr float alpha = 3.2f;
92 constexpr float fact0 = 1.51f;
93 constexpr float fact1 = 1.66f;
94 constexpr float ops = 12.0f;
95 const float scale = k > 1024 ? 1.07f : 1.0f;
Gian Marco Iodice12f2b8c2020-02-13 12:27:37 +000096 gemm_type = (alpha + ((n * fact0) / ops) < ((fact1 * n * scale) / ops)) ? GEMMType::RESHAPED_V2 : GEMMType::RESHAPED_V2;
Gian Marco Iodice05639f62019-09-24 12:05:06 +010097 }
98 else
99 {
Gian Marco Iodice12f2b8c2020-02-13 12:27:37 +0000100 gemm_type = GEMMType::RESHAPED_ONLY_RHS;
Gian Marco Iodice05639f62019-09-24 12:05:06 +0100101 }
102 }
103
104 const auto workload = static_cast<float>((m * n) / 20.0f);
105
106 gemm_type = ((workload > 1600.0f) && (gemm_type == GEMMType::RESHAPED_V1) && (data_type == DataType::F32)) ? GEMMType::RESHAPED_V2 : gemm_type;
107 }
108 else
109 {
110 if((m == 1) || (!reshape_b_only_on_first_run))
111 {
Giorgio Arena695ad692020-02-07 10:28:45 +0000112 if((n > k) && gpu_target_is_in(gpu_target, GPUTarget::G71))
113 {
114 gemm_type = GEMMType::NATIVE;
115 }
116 else
117 {
118 gemm_type = GEMMType::RESHAPED_ONLY_RHS;
119 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000120 }
Gian Marco Iodice05639f62019-09-24 12:05:06 +0100121 else
122 {
123 gemm_type = GEMMType::RESHAPED_V2;
124 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000125 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000126 }
127 else
128 {
129 // We reshape the matrices only if we do not have the vector-by-matrix case and we reshape the matrix B only once
130 gemm_type = ((m != 1) && reshape_b_only_on_first_run) ? GEMMType::RESHAPED_V1 : GEMMType::NATIVE;
131 }
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100132
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000133 return gemm_type;
134}
135
136void CLGEMM::configure_native(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
137{
138 const unsigned int m = gemm_info.reinterpret_input_as_3d() ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
139 const unsigned int n = b->info()->dimension(0);
140 const unsigned int k = a->info()->dimension(0);
141 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco36a0a462018-01-12 10:21:40 +0000142
143 // Set the target for the kernels
Gian Marco36a0a462018-01-12 10:21:40 +0000144 _mm_kernel.set_target(gpu_target);
145
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100146 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 +0000147
148 // Configure and tune matrix multiply kernel
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100149 _mm_kernel.configure(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 +0000150
151 // Tune kernel statically
152 CLScheduler::get().tune_kernel_static(_mm_kernel);
153}
154
155void CLGEMM::configure_reshaped_v1(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
156{
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000157 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
158 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
159 const unsigned int n = b->info()->dimension(0);
160 const unsigned int k = a->info()->dimension(0);
161 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000162 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000163 int mult_transpose1xW_width = 1;
164 int mult_interleave4x4_height = 1;
Gian Marco36a0a462018-01-12 10:21:40 +0000165
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000166 // Set the target for the kernels
167 _reshape_lhs_kernel.set_target(gpu_target);
168 _mm_kernel.set_target(gpu_target);
169
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100170 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
Gian Marco36a0a462018-01-12 10:21:40 +0000171 {
172 mult_transpose1xW_width = 4;
173 mult_interleave4x4_height = 2;
174 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000175
giuros018b6b4a92018-12-18 19:01:33 +0000176 GEMMRHSMatrixInfo rhs_info;
177 rhs_info.n0 = 16 / b->info()->element_size();
178 rhs_info.k0 = 1;
179 rhs_info.h0 = mult_transpose1xW_width;
180 rhs_info.interleave = false;
181 rhs_info.transpose = false;
Gian Marco36a0a462018-01-12 10:21:40 +0000182
giuros011c9efeb2019-01-11 14:04:43 +0000183 GEMMLHSMatrixInfo lhs_info;
184 lhs_info.m0 = 4;
185 lhs_info.k0 = 4;
186 lhs_info.v0 = mult_interleave4x4_height;
187 lhs_info.interleave = true;
188 lhs_info.transpose = true;
189
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100190 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 +0000191
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100192 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
193
194 // Manage intermediate buffers
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000195 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100196
197 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice68a3f562018-07-26 11:44:03 +0100198 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000199 _memory_group.manage(&_tmp_b);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100200 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100201
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000202 // Configure interleave kernel
203 _reshape_lhs_kernel.configure(a, &_tmp_a, lhs_info, reinterpret_input_as_3d);
Gian Marco Iodiceedfa9f42017-08-15 11:45:22 +0100204
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000205 // Configure transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100206 ICLTensor *reshaped_rhs = &_tmp_b;
207 if(_weights_manager && _weights_manager->are_weights_managed(b))
208 {
209 _reshape_rhs_kernel_managed.configure(b, rhs_info);
210 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
211 }
212 else
213 {
214 _reshape_rhs_kernel.configure(b, &_tmp_b, rhs_info);
215 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100216
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000217 // Configure and tune matrix multiply kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100218 _mm_kernel.configure(&_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 +0000219
220 CLScheduler::get().tune_kernel_static(_mm_kernel);
221
222 // Allocate intermediate tensors
223 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100224
225 if(!_reshape_b_only_on_first_run && use_mm_b)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100226 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000227 _tmp_b.allocator()->allocate();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100228 }
229}
230
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000231void CLGEMM::configure_reshaped_v2(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
232{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000233 DataType data_type = a->info()->data_type();
234 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
235 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
236 const unsigned int n = b->info()->dimension(0);
237 const unsigned int k = a->info()->dimension(0);
238 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
239 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
240 const GPUTarget gpu_target = CLScheduler::get().target();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100241 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100242
243 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100244 kernel_info.m = m;
245 kernel_info.n = n;
246 kernel_info.k = k;
247 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
248 kernel_info.reinterpret_input_as_3d = false;
249 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100250 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000251
252 // Set the target for the kernels
253 _reshape_lhs_kernel.set_target(gpu_target);
254 _mm_kernel.set_target(gpu_target);
255
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100256 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
257
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000258 // Manage intermediate buffers
259 _memory_group.manage(&_tmp_a);
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100260
261 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000262 {
263 _memory_group.manage(&_tmp_b);
264 }
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100265
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000266 // _tmp_a and _tmp_b will be auto configured in _interleave_kernel and in _transpose_kernel
267
268 GEMMLHSMatrixInfo lhs_info{};
269 GEMMRHSMatrixInfo rhs_info{};
270
271 // Pick up the GEMM configuration
272 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
273 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
274
275 // Configure lhs_info and rhs_info
276 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
277
278 _reshape_lhs_kernel.configure(a, &_tmp_a, lhs_info, gemm_info.reinterpret_input_as_3d());
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100279
280 ICLTensor *reshaped_rhs = &_tmp_b;
281 if(_weights_manager && _weights_manager->are_weights_managed(b))
282 {
283 _reshape_rhs_kernel_managed.configure(b, rhs_info);
284 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
285 }
286 else
287 {
288 _reshape_rhs_kernel.configure(b, &_tmp_b, rhs_info);
289 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000290
291 // Configure and tune matrix multiply kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100292 _mm_reshaped_kernel.configure(&_tmp_a, reshaped_rhs, c, output, alpha, beta, lhs_info, rhs_info, kernel_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000293
294 // Allocate intermediate tensors
295 _tmp_a.allocator()->allocate();
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100296
297 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000298 {
299 _tmp_b.allocator()->allocate();
300 }
301}
302
303void CLGEMM::configure_reshaped_only_rhs(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
304{
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000305 DataType data_type = a->info()->data_type();
306 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
307 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
308 const unsigned int n = b->info()->dimension(0);
309 const unsigned int k = a->info()->dimension(0);
310 const unsigned int batch_size = reinterpret_input_as_3d ? a->info()->dimension(3) : a->info()->dimension(2);
311 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
312 const GPUTarget gpu_target = CLScheduler::get().target();
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100313 bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100314
315 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100316 kernel_info.m = m;
317 kernel_info.n = n;
318 kernel_info.k = k;
319 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
320 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
321 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100322 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000323
324 // Set the target for the kernels
325 _mm_kernel.set_target(gpu_target);
326
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100327 const bool use_mm_b = (!_weights_manager || !_weights_manager->are_weights_managed(b));
328
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000329 // Manage intermediate buffers
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100330 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000331 {
332 _memory_group.manage(&_tmp_b);
333 }
334
335 GEMMLHSMatrixInfo lhs_info{};
336 GEMMRHSMatrixInfo rhs_info{};
337
338 // Pick up the GEMM configuration
339 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
340 ARM_COMPUTE_ERROR_ON_NULLPTR(gemm_config.get());
341
342 // Configure lhs_info and rhs_info
343 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
344
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100345 ICLTensor *reshaped_rhs = &_tmp_b;
346 if(_weights_manager && _weights_manager->are_weights_managed(b))
347 {
348 _reshape_rhs_kernel_managed.configure(b, rhs_info);
349 reshaped_rhs = utils::cast::polymorphic_downcast<ICLTensor *>(_weights_manager->acquire(b, &_reshape_rhs_kernel_managed));
350 }
351 else
352 {
353 _reshape_rhs_kernel.configure(b, &_tmp_b, rhs_info);
354 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000355
356 // Configure and tune matrix multiply kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100357 _mm_reshaped_only_rhs_kernel.configure(a, reshaped_rhs, c, output, alpha, beta, lhs_info, rhs_info, kernel_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000358
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100359 if(!_reshape_b_only_on_first_run && use_mm_b)
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000360 {
361 _tmp_b.allocator()->allocate();
362 }
363}
364
365Status CLGEMM::validate_native(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 +0000366{
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100367 ARM_COMPUTE_UNUSED(alpha);
Gian Marco Iodice215b4ea2018-06-28 16:29:29 +0100368 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100369
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000370 // Get the GPU target
371 const GPUTarget gpu_target = CLScheduler::get().target();
372 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
373 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
374 const unsigned int n = b->dimension(0);
375 const unsigned int k = a->dimension(0);
376 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100377
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100378 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 +0000379
380 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100381 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(a, b, c, output, alpha, beta,
382 false, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000383
384 return Status{};
385}
386
387Status CLGEMM::validate_reshaped_v1(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
388{
389 ARM_COMPUTE_UNUSED(alpha);
390 ARM_COMPUTE_UNUSED(output);
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100391
392 TensorInfo tmp_a_info{};
393 TensorInfo tmp_b_info{};
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100394
395 // Get the GPU target
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000396 const GPUTarget gpu_target = CLScheduler::get().target();
397 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 +0000398 const unsigned int n = b->dimension(0);
399 const unsigned int k = a->dimension(0);
400 int mult_transpose1xW_width = 1;
401 int mult_interleave4x4_height = 1;
402 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100403
404 if(get_arch_from_target(gpu_target) == GPUTarget::BIFROST)
405 {
406 mult_transpose1xW_width = 4;
407 mult_interleave4x4_height = 2;
408 }
409
giuros018b6b4a92018-12-18 19:01:33 +0000410 GEMMRHSMatrixInfo rhs_info;
411 rhs_info.n0 = 16 / b->element_size();
412 rhs_info.k0 = 1;
413 rhs_info.h0 = mult_transpose1xW_width;
414 rhs_info.interleave = false;
415 rhs_info.transpose = false;
416
giuros011c9efeb2019-01-11 14:04:43 +0000417 GEMMLHSMatrixInfo lhs_info;
418 lhs_info.m0 = 4;
419 lhs_info.k0 = 4;
420 lhs_info.v0 = mult_interleave4x4_height;
421 lhs_info.interleave = true;
422 lhs_info.transpose = true;
423
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100424 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 +0100425
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000426 // Validate interleave kernel
427 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())));
428 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 +0000429
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000430 // Validate transpose kernel
431 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
432 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
Michele Di Giorgioebc3a902018-11-16 16:04:25 +0000433
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000434 // Validate matrix multiply
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100435 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMMatrixMultiplyKernel::validate(&tmp_a_info, &tmp_b_info, c, output, alpha, beta,
436 true, reshape_info, gpu_target, gemm_info.fp_mixed_precision(), gemm_info.activation_info()));
Gian Marco Iodice750641d2018-05-08 12:01:57 +0100437
Georgios Pinitas78c00902018-01-09 17:33:11 +0000438 return Status{};
439}
440
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000441Status CLGEMM::validate_reshaped_v2(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
442{
443 ARM_COMPUTE_UNUSED(alpha);
444 ARM_COMPUTE_UNUSED(output);
445
446 TensorInfo tmp_a_info{};
447 TensorInfo tmp_b_info{};
448
449 // Get the GPU target
450 const GPUTarget gpu_target = CLScheduler::get().target();
451 DataType data_type = a->data_type();
452 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
453 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
454 const unsigned int n = b->dimension(0);
455 const unsigned int k = a->dimension(0);
456 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
457 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100458 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100459
460 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100461 kernel_info.m = m;
462 kernel_info.n = n;
463 kernel_info.k = k;
464 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
465 kernel_info.reinterpret_input_as_3d = false;
466 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100467 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000468
469 GEMMLHSMatrixInfo lhs_info;
470 GEMMRHSMatrixInfo rhs_info;
471
472 // Pick up the GEMM configuration
473 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedKernelConfigurationFactory::create(gpu_target);
474 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
475
476 // Configure lhs_info and rhs_info
477 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
478
479 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())));
480 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeLHSMatrixKernel::validate(a, &tmp_a_info, lhs_info, gemm_info.reinterpret_input_as_3d()));
481
482 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
483 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
484
485 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100486 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 +0000487
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000488 return Status{};
489}
490
491Status 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)
492{
493 ARM_COMPUTE_UNUSED(alpha);
494 ARM_COMPUTE_UNUSED(output);
495
496 TensorInfo tmp_b_info{};
497
498 // Get the GPU target
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100499 const GPUTarget gpu_target = CLScheduler::get().target();
500 const DataType data_type = a->data_type();
501 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
502 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
503 const unsigned int n = b->dimension(0);
504 const unsigned int k = a->dimension(0);
505 const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2);
506 const int depth_output_gemm3d = gemm_info.depth_output_gemm3d();
507 const bool broadcast_bias = gemm_info.broadcast_bias();
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100508
509 GEMMKernelInfo kernel_info;
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100510 kernel_info.m = m;
511 kernel_info.n = n;
512 kernel_info.k = k;
513 kernel_info.depth_output_gemm3d = depth_output_gemm3d;
514 kernel_info.reinterpret_input_as_3d = reinterpret_input_as_3d;
515 kernel_info.broadcast_bias = broadcast_bias;
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100516 kernel_info.activation_info = gemm_info.activation_info();
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000517
518 GEMMLHSMatrixInfo lhs_info;
519 GEMMRHSMatrixInfo rhs_info;
520
521 // Pick up the GEMM configuration
522 std::unique_ptr<ICLGEMMKernelConfiguration> gemm_config = CLGEMMReshapedOnlyRHSKernelConfigurationFactory::create(gpu_target);
523 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(gemm_config.get());
524
525 // Configure lhs_info and rhs_info
526 std::tie(lhs_info, rhs_info) = gemm_config->configure(m, n, k, batch_size, data_type);
527
528 auto_init_if_empty(tmp_b_info, b->clone()->set_tensor_shape(compute_rhs_reshaped_shape(*b, rhs_info)));
529 ARM_COMPUTE_RETURN_ON_ERROR(CLGEMMReshapeRHSMatrixKernel::validate(b, &tmp_b_info, rhs_info));
530
531 // Validate matrix multiply
Gian Marco Iodice7026b302019-06-26 17:18:11 +0100532 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 +0000533
534 return Status{};
535}
536
537void CLGEMM::configure(const ICLTensor *a, const ICLTensor *b, const ICLTensor *c, ICLTensor *output, float alpha, float beta, const GEMMInfo &gemm_info)
538{
539 ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, output);
540
541 // Perform validation step
542 ARM_COMPUTE_ERROR_THROW_ON(validate(a->info(), b->info(), c != nullptr ? c->info() : nullptr, output->info(), alpha, beta, gemm_info));
543
544 // Check if we need to reshape the matrix B only on the first run
545 _reshape_b_only_on_first_run = gemm_info.reshape_b_only_on_first_run();
546 _is_prepared = gemm_info.retain_internal_weights();
547 _original_b = b;
548
549 // Get the GPU target
550 const GPUTarget gpu_target = CLScheduler::get().target();
551 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
552 const unsigned int m = reinterpret_input_as_3d ? (a->info()->dimension(1) * a->info()->dimension(2)) : a->info()->dimension(1);
553 const unsigned int n = b->info()->dimension(0);
554 const unsigned int k = a->info()->dimension(0);
555
556 // Select GEMMType
557 _gemm_type = select_gemm_type(m, n, k, a->info()->data_type(), _reshape_b_only_on_first_run, gpu_target);
558
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100559 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100560
561 const ICLTensor *c_to_use = fuse_add_c ? c : nullptr;
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000562
563 switch(_gemm_type)
564 {
565 case GEMMType::NATIVE:
566 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100567 configure_native(a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000568 break;
569 }
570 case GEMMType::RESHAPED_V1:
571 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100572 configure_reshaped_v1(a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000573 break;
574 }
575 case GEMMType::RESHAPED_V2:
576 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100577 configure_reshaped_v2(a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000578 break;
579 }
580 case GEMMType::RESHAPED_ONLY_RHS:
581 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100582 configure_reshaped_only_rhs(a, b, c_to_use, output, alpha, beta, gemm_info);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000583 break;
584 }
585 default:
586 {
587 ARM_COMPUTE_ERROR("GEMMType not supported");
588 }
589 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000590}
591
592Status CLGEMM::validate(const ITensorInfo *a, const ITensorInfo *b, const ITensorInfo *c, const ITensorInfo *output, float alpha, float beta, const GEMMInfo &gemm_info)
593{
594 // Get the GPU target
595 const GPUTarget gpu_target = CLScheduler::get().target();
596 bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d();
597 const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1);
598 const unsigned int n = b->dimension(0);
599 const unsigned int k = a->dimension(0);
600
601 // Select GEMMType
602 GEMMType gemm_type = select_gemm_type(m, n, k, a->data_type(), gemm_info.reshape_b_only_on_first_run(), gpu_target);
603
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100604 const bool fuse_add_c = (!(helpers::float_ops::is_zero(beta)) && c != nullptr);
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100605
606 const ITensorInfo *c_to_use = fuse_add_c ? c : nullptr;
607
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000608 switch(gemm_type)
609 {
610 case GEMMType::NATIVE:
611 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100612 ARM_COMPUTE_RETURN_ON_ERROR(validate_native(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000613 break;
614 }
615 case GEMMType::RESHAPED_V1:
616 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100617 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 +0000618 break;
619 }
620 case GEMMType::RESHAPED_V2:
621 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100622 ARM_COMPUTE_RETURN_ON_ERROR(validate_reshaped_v2(a, b, c_to_use, output, alpha, beta, gemm_info));
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000623 break;
624 }
625 case GEMMType::RESHAPED_ONLY_RHS:
626 {
Gian Marco Iodicee16c8902019-06-14 16:11:10 +0100627 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 +0000628 break;
629 }
630 default:
631 {
632 ARM_COMPUTE_RETURN_ERROR_MSG("GEMMType not supported");
633 }
634 }
635
636 return Status{};
637}
638
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100639void CLGEMM::run()
640{
Georgios Pinitase0437672018-05-02 14:07:55 +0100641 prepare();
642
Georgios Pinitasda953f22019-04-02 17:27:03 +0100643 MemoryGroupResourceScope scope_mg(_memory_group);
Georgios Pinitas8a94e7c2017-09-15 19:06:47 +0100644
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100645 // Run matrix multiply kernel
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000646 switch(_gemm_type)
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000647 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000648 case GEMMType::NATIVE:
649 {
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100650 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000651 break;
652 }
653 case GEMMType::RESHAPED_V1:
654 {
655 // Run interleave kernel
656 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
657
658 if(!_reshape_b_only_on_first_run)
659 {
660 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100661 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
662 {
663 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
664 }
665 else
666 {
667 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
668 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000669 }
670
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100671 CLScheduler::get().enqueue(_mm_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000672 break;
673 }
674 case GEMMType::RESHAPED_V2:
675 {
676 // Run interleave kernel
677 CLScheduler::get().enqueue(_reshape_lhs_kernel, false);
678
679 if(!_reshape_b_only_on_first_run)
680 {
681 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100682 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
683 {
684 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
685 }
686 else
687 {
688 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
689 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000690 }
691
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100692 CLScheduler::get().enqueue(_mm_reshaped_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000693 break;
694 }
695 case GEMMType::RESHAPED_ONLY_RHS:
696 {
697 if(!_reshape_b_only_on_first_run)
698 {
699 // Run transpose kernel
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100700 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
701 {
702 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
703 }
704 else
705 {
706 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
707 }
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000708 }
709
Gian Marco Iodicef3622be2019-07-29 14:27:16 +0100710 CLScheduler::get().enqueue(_mm_reshaped_only_rhs_kernel, true);
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000711 break;
712 }
713 default:
714 {
715 ARM_COMPUTE_ERROR("GEMMType not supported");
716 }
Gian Marco Iodicebf9731e2018-12-12 10:18:04 +0000717 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100718}
Georgios Pinitas82b51482018-04-24 15:14:12 +0100719
Georgios Pinitase0437672018-05-02 14:07:55 +0100720void CLGEMM::prepare()
721{
722 if(!_is_prepared)
723 {
Gian Marco Iodice926afe12019-03-19 11:44:13 +0000724 if(_gemm_type != GEMMType::NATIVE && _reshape_b_only_on_first_run)
Georgios Pinitase0437672018-05-02 14:07:55 +0100725 {
Michalis Spyroub27e13a2019-09-27 11:04:27 +0100726 if(_weights_manager && _weights_manager->are_weights_managed(_original_b))
727 {
728 _weights_manager->run(_original_b, &_reshape_rhs_kernel_managed);
729 }
730 else
731 {
732 // Run transpose kernel and mark original weights tensor as unused
733 _tmp_b.allocator()->allocate();
734 CLScheduler::get().enqueue(_reshape_rhs_kernel, false);
735 _original_b->mark_as_unused();
736 }
Georgios Pinitase0437672018-05-02 14:07:55 +0100737 }
738 CLScheduler::get().queue().finish();
739 _is_prepared = true;
740 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100741}
giuros011c9efeb2019-01-11 14:04:43 +0000742} // namespace arm_compute