blob: 9bbc32657ec859154f22996c896469e3a4985c26 [file] [log] [blame]
Michalis Spyrou11d49182020-03-26 10:31:32 +00001/*
Viet-Hoa Do246fe082023-08-16 10:29:00 +01002 * Copyright (c) 2020-2023 Arm Limited.
Michalis Spyrou11d49182020-03-26 10:31:32 +00003 *
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/core/CL/CLCompileContext.h"
Michalis Spyrou11d49182020-03-26 10:31:32 +000025
26#include "arm_compute/core/CL/CLHelpers.h"
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010027#include "arm_compute/core/CL/OpenCL.h"
Michalis Spyrou11d49182020-03-26 10:31:32 +000028#include "arm_compute/core/Error.h"
29#include "arm_compute/core/Utils.h"
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010030
Michalis Spyrou11d49182020-03-26 10:31:32 +000031#include "support/StringSupport.h"
32
Giorgio Arenaea8d2662021-05-20 11:36:56 +010033#include <regex>
34
Michalis Spyrou11d49182020-03-26 10:31:32 +000035namespace arm_compute
36{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010037CLBuildOptions::CLBuildOptions() : _build_opts()
Michalis Spyrou11d49182020-03-26 10:31:32 +000038{
39}
40
41void CLBuildOptions::add_option(std::string option)
42{
43 _build_opts.emplace(std::move(option));
44}
45
46void CLBuildOptions::add_option_if(bool cond, std::string option)
47{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010048 if (cond)
Michalis Spyrou11d49182020-03-26 10:31:32 +000049 {
50 add_option(std::move(option));
51 }
52}
53
54void CLBuildOptions::add_option_if_else(bool cond, std::string option_true, std::string option_false)
55{
56 (cond) ? add_option(std::move(option_true)) : add_option(std::move(option_false));
57}
58
59void CLBuildOptions::add_options(const StringSet &options)
60{
61 _build_opts.insert(options.begin(), options.end());
62}
63
64void CLBuildOptions::add_options_if(bool cond, const StringSet &options)
65{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010066 if (cond)
Michalis Spyrou11d49182020-03-26 10:31:32 +000067 {
68 add_options(options);
69 }
70}
71
72const CLBuildOptions::StringSet &CLBuildOptions::options() const
73{
74 return _build_opts;
75}
76
Giorgio Arena232c4522022-03-03 10:09:01 +000077bool CLBuildOptions::operator==(const CLBuildOptions &other) const
78{
79 return _build_opts == other._build_opts;
80}
81
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010082Program::Program() : _context(), _device(), _is_binary(false), _name(), _source(), _binary()
Michalis Spyrou11d49182020-03-26 10:31:32 +000083{
84}
85
86Program::Program(cl::Context context, std::string name, std::string source)
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010087 : _context(std::move(context)),
88 _device(),
89 _is_binary(false),
90 _name(std::move(name)),
91 _source(std::move(source)),
92 _binary()
Michalis Spyrou11d49182020-03-26 10:31:32 +000093{
94}
95
96Program::Program(cl::Context context, cl::Device device, std::string name, std::vector<unsigned char> binary)
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010097 : _context(std::move(context)),
98 _device(std::move(device)),
99 _is_binary(true),
100 _name(std::move(name)),
101 _source(),
102 _binary(std::move(binary))
Michalis Spyrou11d49182020-03-26 10:31:32 +0000103{
104}
105
106Program::operator cl::Program() const
107{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100108 if (_is_binary)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000109 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100110 return cl::Program(_context, {_device}, {_binary});
Michalis Spyrou11d49182020-03-26 10:31:32 +0000111 }
112 else
113 {
114 return cl::Program(_context, _source, false);
115 }
116}
117
118bool Program::build(const cl::Program &program, const std::string &build_options)
119{
120 try
121 {
122 return program.build(build_options.c_str()) == CL_SUCCESS;
123 }
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100124 catch (const cl::Error &e)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000125 {
126 cl_int err = CL_SUCCESS;
127 const auto build_info = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(&err);
128
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100129 for (auto &pair : build_info)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000130 {
131 std::cerr << pair.second << std::endl;
132 }
133
134 return false;
135 }
136}
137
138cl::Program Program::build(const std::string &build_options) const
139{
140 cl::Program cl_program = static_cast<cl::Program>(*this);
141 build(cl_program, build_options);
142 return cl_program;
143}
144
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100145Kernel::Kernel() : _name(), _kernel()
Michalis Spyrou11d49182020-03-26 10:31:32 +0000146{
147}
148
149Kernel::Kernel(std::string name, const cl::Program &program)
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100150 : _name(std::move(name)), _kernel(cl::Kernel(program, _name.c_str()))
Michalis Spyrou11d49182020-03-26 10:31:32 +0000151{
152}
153CLCompileContext::CLCompileContext()
Manuel Bottinibe9f9f92021-01-25 15:07:17 +0000154 : _context(), _device(), _programs_map(), _built_programs_map(), _is_wbsm_supported()
Michalis Spyrou11d49182020-03-26 10:31:32 +0000155{
156}
157
158CLCompileContext::CLCompileContext(cl::Context context, const cl::Device &device)
Manuel Bottinibe9f9f92021-01-25 15:07:17 +0000159 : _context(), _device(), _programs_map(), _built_programs_map(), _is_wbsm_supported()
Michalis Spyrou11d49182020-03-26 10:31:32 +0000160{
Manuel Bottinibe9f9f92021-01-25 15:07:17 +0000161 _context = std::move(context);
162 _device = CLDevice(device);
163 _is_wbsm_supported = get_wbsm_support_info(device);
Michalis Spyrou11d49182020-03-26 10:31:32 +0000164}
165
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100166Kernel CLCompileContext::create_kernel(const std::string &kernel_name,
167 const std::string &program_name,
168 const std::string &program_source,
169 const std::string &kernel_path,
170 const StringSet &build_options_set,
171 bool is_binary) const
Michalis Spyrou11d49182020-03-26 10:31:32 +0000172{
173 const std::string build_options = generate_build_options(build_options_set, kernel_path);
174 const std::string built_program_name = program_name + "_" + build_options;
175 auto built_program_it = _built_programs_map.find(built_program_name);
176 cl::Program cl_program;
177
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100178 if (_built_programs_map.end() != built_program_it)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000179 {
180 // If program has been built, retrieve to create kernel from it
181 cl_program = built_program_it->second;
182 }
183 else
184 {
185 Program program = load_program(program_name, program_source, is_binary);
186
187 // Build program
188 cl_program = program.build(build_options);
189
190 // Add built program to internal map
Michalis Spyrou12910f22020-04-14 13:54:45 +0100191 _built_programs_map.emplace(built_program_name, cl_program);
Michalis Spyrou11d49182020-03-26 10:31:32 +0000192 }
193
194 // Create and return kernel
195 return Kernel(kernel_name, cl_program);
196}
197
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100198const Program &
199CLCompileContext::load_program(const std::string &program_name, const std::string &program_source, bool is_binary) const
Michalis Spyrou11d49182020-03-26 10:31:32 +0000200{
201 const auto program_it = _programs_map.find(program_name);
202
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100203 if (program_it != _programs_map.end())
Michalis Spyrou11d49182020-03-26 10:31:32 +0000204 {
205 return program_it->second;
206 }
207
208 Program program;
209
210#ifdef EMBEDDED_KERNELS
211 ARM_COMPUTE_UNUSED(is_binary);
212 program = Program(_context, program_name, program_source);
213#else /* EMBEDDED_KERNELS */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100214 if (is_binary)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000215 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100216 program = Program(_context, _device.cl_device(), program_name,
217 std::vector<unsigned char>(program_source.begin(), program_source.end()));
Michalis Spyrou11d49182020-03-26 10:31:32 +0000218 }
219 else
220 {
221 program = Program(_context, program_name, program_source);
222 }
223#endif /* EMBEDDED_KERNELS */
224
225 // Insert program to program map
226 const auto new_program = _programs_map.emplace(program_name, std::move(program));
227
228 return new_program.first->second;
229}
230
231void CLCompileContext::set_context(cl::Context context)
232{
233 _context = std::move(context);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100234 if (_context.get() != nullptr)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000235 {
236 const auto cl_devices = _context.getInfo<CL_CONTEXT_DEVICES>();
237
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100238 if (!cl_devices.empty())
Michalis Spyrou11d49182020-03-26 10:31:32 +0000239 {
240 _device = CLDevice(cl_devices[0]);
241 }
242 }
243}
244
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100245std::string CLCompileContext::generate_build_options(const StringSet &build_options_set,
246 const std::string &kernel_path) const
Michalis Spyrou11d49182020-03-26 10:31:32 +0000247{
248 std::string concat_str;
SiCong Lif44bbc52022-08-29 18:25:51 +0100249 bool ext_supported = false;
Viet-Hoa Dof8bb0922022-05-30 15:15:15 +0100250 std::string ext_buildopts;
Michalis Spyrou11d49182020-03-26 10:31:32 +0000251
252#if defined(ARM_COMPUTE_DEBUG_ENABLED)
253 // Enable debug properties in CL kernels
254 concat_str += " -DARM_COMPUTE_DEBUG_ENABLED";
255#endif // defined(ARM_COMPUTE_DEBUG_ENABLED)
256
257 GPUTarget gpu_arch = get_arch_from_target(_device.target());
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100258 concat_str +=
259 " -DGPU_ARCH=" + support::cpp11::to_string(static_cast<std::underlying_type<GPUTarget>::type>(gpu_arch));
Michalis Spyrou11d49182020-03-26 10:31:32 +0000260
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100261 if (_device.supported("cl_khr_fp16"))
Michalis Spyrou11d49182020-03-26 10:31:32 +0000262 {
263 concat_str += " -DARM_COMPUTE_OPENCL_FP16_ENABLED=1 ";
264 }
265
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100266 if (_device.supported("cl_arm_integer_dot_product_int8") || _device.supported("cl_khr_integer_dot_product"))
Michalis Spyrou11d49182020-03-26 10:31:32 +0000267 {
268 concat_str += " -DARM_COMPUTE_OPENCL_DOT8_ENABLED=1 ";
269 }
270
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100271 if (_device.supported("cl_arm_integer_dot_product_accumulate_int8"))
Michalis Spyrou11d49182020-03-26 10:31:32 +0000272 {
273 concat_str += " -DARM_COMPUTE_OPENCL_DOT8_ACC_ENABLED=1 ";
274 }
275
Viet-Hoa Dof8bb0922022-05-30 15:15:15 +0100276 std::tie(ext_supported, ext_buildopts) = _device.is_non_uniform_workgroup_supported();
277
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100278 if (ext_supported)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000279 {
Viet-Hoa Dof8bb0922022-05-30 15:15:15 +0100280 concat_str += ext_buildopts;
Michalis Spyrou11d49182020-03-26 10:31:32 +0000281 }
282 else
283 {
284 ARM_COMPUTE_ERROR("Non uniform workgroup size is not supported!!");
285 }
286
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100287 if (gpu_arch != GPUTarget::UNKNOWN && gpu_arch != GPUTarget::MIDGARD && get_ddk_version() >= 11)
Giorgio Arenaea8d2662021-05-20 11:36:56 +0100288 {
Viet-Hoa Dob5368fb2022-09-21 11:31:46 +0100289 concat_str += " -DUNROLL_WITH_PRAGMA ";
Giorgio Arenaea8d2662021-05-20 11:36:56 +0100290 }
291
Michalis Spyrou11d49182020-03-26 10:31:32 +0000292 std::string build_options = stringify_set(build_options_set, kernel_path) + concat_str;
293
294 return build_options;
295}
296
297bool CLCompileContext::fp16_supported() const
298{
299 return _device.supported("cl_khr_fp16");
300}
301
302std::string CLCompileContext::stringify_set(const StringSet &s, const std::string &kernel_path) const
303{
304 std::string concat_set;
305#ifndef EMBEDDED_KERNELS
306 concat_set += "-I" + kernel_path + " ";
307#else /* EMBEDDED_KERNELS */
308 ARM_COMPUTE_UNUSED(kernel_path);
309#endif /* EMBEDDED_KERNELS */
310
311 // Concatenate set
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100312 for (const auto &el : s)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000313 {
314 concat_set += " " + el;
315 }
316
317 return concat_set;
318}
319
320void CLCompileContext::add_built_program(const std::string &built_program_name, const cl::Program &program) const
321{
322 _built_programs_map.emplace(built_program_name, program);
323}
324
325void CLCompileContext::clear_programs_cache()
326{
327 _programs_map.clear();
328 _built_programs_map.clear();
329}
330
331const std::map<std::string, cl::Program> &CLCompileContext::get_built_programs() const
332{
333 return _built_programs_map;
334}
335
336cl::Context &CLCompileContext::context()
337{
338 return _context;
339}
340
341const cl::Device &CLCompileContext::get_device() const
342{
343 return _device.cl_device();
344}
345
346void CLCompileContext::set_device(cl::Device device)
347{
Manuel Bottinibe9f9f92021-01-25 15:07:17 +0000348 _is_wbsm_supported = get_wbsm_support_info(device);
Viet-Hoa Do246fe082023-08-16 10:29:00 +0100349 _device = std::move(device);
Michalis Spyrou11d49182020-03-26 10:31:32 +0000350}
351
352cl::NDRange CLCompileContext::default_ndrange() const
353{
354 GPUTarget _target = get_target_from_device(_device.cl_device());
355 cl::NDRange default_range;
356
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100357 switch (_target)
Michalis Spyrou11d49182020-03-26 10:31:32 +0000358 {
359 case GPUTarget::MIDGARD:
360 case GPUTarget::T600:
361 case GPUTarget::T700:
362 case GPUTarget::T800:
363 default_range = cl::NDRange(128u, 1);
364 break;
365 default:
366 default_range = cl::NullRange;
367 }
368
369 return default_range;
370}
371
372bool CLCompileContext::int64_base_atomics_supported() const
373{
374 return _device.supported("cl_khr_int64_base_atomics");
375}
376
Manuel Bottinibe9f9f92021-01-25 15:07:17 +0000377bool CLCompileContext::is_wbsm_supported() const
378{
379 return _is_wbsm_supported;
380}
381
Michalis Spyrou11d49182020-03-26 10:31:32 +0000382size_t CLCompileContext::max_local_workgroup_size(const cl::Kernel &kernel) const
383{
384 size_t result;
385
386 size_t err = kernel.getWorkGroupInfo(_device.cl_device(), CL_KERNEL_WORK_GROUP_SIZE, &result);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100387 ARM_COMPUTE_ERROR_ON_MSG(err != 0,
388 "clGetKernelWorkGroupInfo failed to return the maximum workgroup size for the kernel");
Michalis Spyrou11d49182020-03-26 10:31:32 +0000389 ARM_COMPUTE_UNUSED(err);
390
391 return result;
392}
393
394std::string CLCompileContext::get_device_version() const
395{
396 return _device.device_version();
397}
398
399cl_uint CLCompileContext::get_num_compute_units() const
400{
401 return _device.compute_units();
402}
Viet-Hoa Dob5368fb2022-09-21 11:31:46 +0100403
404int32_t CLCompileContext::get_ddk_version() const
405{
406 const std::string device_version = _device.device_version();
407 const std::regex ddk_regex("r([0-9]*)p[0-9]");
408 std::smatch ddk_match;
409
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100410 if (std::regex_search(device_version, ddk_match, ddk_regex))
Viet-Hoa Dob5368fb2022-09-21 11:31:46 +0100411 {
412 return std::stoi(ddk_match[1]);
413 }
414
415 return -1;
416}
SiCong Lif44bbc52022-08-29 18:25:51 +0100417GPUTarget CLCompileContext::get_gpu_target() const
418{
419 return _device.target();
420}
Michalis Spyrou11d49182020-03-26 10:31:32 +0000421} // namespace arm_compute