1 /* 2 * Copyright (c) 2020-2022 Arm Limited. 3 * 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 #ifndef ARM_COMPUTE_CLDEVICE_H 25 #define ARM_COMPUTE_CLDEVICE_H 26 27 #include "arm_compute/core/CL/CLHelpers.h" 28 #include "arm_compute/core/CL/CLTypes.h" 29 #include "arm_compute/core/GPUTarget.h" 30 #include "arm_compute/core/IDevice.h" 31 32 #include <set> 33 #include <sstream> 34 #include <string> 35 36 namespace arm_compute 37 { 38 /** OpenCL device type class 39 * 40 * Initializes and stores all the information about a cl device, 41 * working mainly as a cache mechanism. 42 * */ 43 class CLDevice : public IDevice 44 { 45 public: 46 /** Default Constructor */ CLDevice()47 CLDevice() 48 : _device(cl::Device()), _options() 49 { 50 } 51 52 /** Constructor 53 * 54 * @param[in] cl_device OpenCL device 55 */ CLDevice(const cl::Device & cl_device)56 CLDevice(const cl::Device &cl_device) 57 : _device(), _options() 58 { 59 _device = cl_device; 60 61 // Get device target 62 std::string device_name = _device.getInfo<CL_DEVICE_NAME>(); 63 _options.gpu_target = get_target_from_name(device_name); 64 65 // Fill extensions 66 std::string extensions = _device.getInfo<CL_DEVICE_EXTENSIONS>(); 67 68 std::istringstream iss(extensions); 69 for(std::string s; iss >> s;) 70 { 71 _options.extensions.insert(s); 72 } 73 74 // SW workaround for G76 75 if(_options.gpu_target == GPUTarget::G76) 76 { 77 _options.extensions.insert("cl_arm_integer_dot_product_int8"); 78 } 79 80 // Get device version 81 _options.version = get_cl_version(_device); 82 83 // Get compute units 84 _options.compute_units = _device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>(); 85 86 // Get device version 87 _options.device_version = _device.getInfo<CL_DEVICE_VERSION>(); 88 } 89 90 /** Returns the GPU target of the cl device 91 * 92 * @return The GPU target 93 */ target()94 const GPUTarget &target() const 95 { 96 return _options.gpu_target; 97 } 98 99 /** Returns the number of compute units available 100 * 101 * @return Number of compute units 102 */ compute_units()103 size_t compute_units() const 104 { 105 return _options.compute_units; 106 } 107 108 /** Returns the underlying cl device object 109 * 110 * @return A cl device 111 */ cl_device()112 const cl::Device &cl_device() const 113 { 114 return _device; 115 } 116 117 /** Returns the device's CL version 118 * 119 * @return CLVersion of the device 120 */ version()121 CLVersion version() const 122 { 123 return _options.version; 124 } 125 126 /** Returns the device version as a string 127 * 128 * @return CLVersion of the device 129 */ device_version()130 std::string device_version() const 131 { 132 return _options.device_version; 133 } 134 135 // Inherrited methods type()136 DeviceType type() const override 137 { 138 return DeviceType::CL; 139 } 140 supported(const std::string & extension)141 bool supported(const std::string &extension) const override 142 { 143 return _options.extensions.count(extension) != 0; 144 } 145 146 /** Returns whether non-uniform workgroup is supported and the build options. 147 * 148 * If the feature is supported, the appropriate build options will be 149 * appended to the specified string. 150 * 151 * @return A tuple (supported, build_options) indicating whether the feature 152 * is supported and the corresponding build options to enable it. 153 */ is_non_uniform_workgroup_supported()154 std::tuple<bool, std::string> is_non_uniform_workgroup_supported() const 155 { 156 if(version() == CLVersion::CL30 && get_cl_non_uniform_work_group_supported(_device)) 157 { 158 return {true, " -cl-std=CL3.0 "}; 159 } 160 else if(version() == CLVersion::CL20) 161 { 162 return {true, " -cl-std=CL2.0 "}; 163 } 164 else if(supported("cl_arm_non_uniform_work_group_size")) 165 { 166 return {true, " -cl-arm-non-uniform-work-group-size "}; 167 } 168 169 return {false, ""}; 170 } 171 172 private: 173 cl::Device _device; /**< OpenCL device. */ 174 struct CLDeviceOptions _options; /**< OpenCL device options */ 175 }; 176 177 } // namespace arm_compute 178 179 #endif /* ARM_COMPUTE_CLDEVICE_H */ 180