File indexing completed on 2024-11-15 09:04:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_DEVICE_HPP
0012 #define BOOST_COMPUTE_DEVICE_HPP
0013
0014 #include <algorithm>
0015 #include <string>
0016 #include <vector>
0017
0018 #include <boost/algorithm/string/split.hpp>
0019 #include <boost/algorithm/string/classification.hpp>
0020
0021 #include <boost/compute/config.hpp>
0022 #include <boost/compute/exception.hpp>
0023 #include <boost/compute/types/fundamental.hpp>
0024 #include <boost/compute/detail/duration.hpp>
0025 #include <boost/compute/detail/get_object_info.hpp>
0026 #include <boost/compute/detail/assert_cl_success.hpp>
0027
0028 namespace boost {
0029 namespace compute {
0030
0031 class platform;
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 class device
0047 {
0048 public:
0049 enum type {
0050 cpu = CL_DEVICE_TYPE_CPU,
0051 gpu = CL_DEVICE_TYPE_GPU,
0052 accelerator = CL_DEVICE_TYPE_ACCELERATOR
0053 };
0054
0055
0056 device()
0057 : m_id(0)
0058 {
0059 }
0060
0061
0062
0063 explicit device(cl_device_id id, bool retain = true)
0064 : m_id(id)
0065 {
0066 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0067 if(m_id && retain && is_subdevice()){
0068 clRetainDevice(m_id);
0069 }
0070 #else
0071 (void) retain;
0072 #endif
0073 }
0074
0075
0076 device(const device &other)
0077 : m_id(other.m_id)
0078 {
0079 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0080 if(m_id && is_subdevice()){
0081 clRetainDevice(m_id);
0082 }
0083 #endif
0084 }
0085
0086
0087 device& operator=(const device &other)
0088 {
0089 if(this != &other){
0090 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0091 if(m_id && is_subdevice()){
0092 clReleaseDevice(m_id);
0093 }
0094 #endif
0095
0096 m_id = other.m_id;
0097
0098 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0099 if(m_id && is_subdevice()){
0100 clRetainDevice(m_id);
0101 }
0102 #endif
0103 }
0104
0105 return *this;
0106 }
0107
0108 #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
0109
0110 device(device&& other) BOOST_NOEXCEPT
0111 : m_id(other.m_id)
0112 {
0113 other.m_id = 0;
0114 }
0115
0116
0117 device& operator=(device&& other) BOOST_NOEXCEPT
0118 {
0119 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0120 if(m_id && is_subdevice()){
0121 clReleaseDevice(m_id);
0122 }
0123 #endif
0124
0125 m_id = other.m_id;
0126 other.m_id = 0;
0127
0128 return *this;
0129 }
0130 #endif
0131
0132
0133 ~device()
0134 {
0135 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0136 if(m_id && is_subdevice()){
0137 BOOST_COMPUTE_ASSERT_CL_SUCCESS(
0138 clReleaseDevice(m_id)
0139 );
0140 }
0141 #endif
0142 }
0143
0144
0145 cl_device_id id() const
0146 {
0147 return m_id;
0148 }
0149
0150
0151 cl_device_id& get() const
0152 {
0153 return const_cast<cl_device_id&>(m_id);
0154 }
0155
0156
0157 cl_device_type type() const
0158 {
0159 return get_info<cl_device_type>(CL_DEVICE_TYPE);
0160 }
0161
0162 #ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
0163
0164 platform platform() const;
0165 #else
0166 boost::compute::platform platform() const;
0167 #endif
0168
0169
0170 std::string name() const
0171 {
0172 return get_info<std::string>(CL_DEVICE_NAME);
0173 }
0174
0175
0176 std::string vendor() const
0177 {
0178 return get_info<std::string>(CL_DEVICE_VENDOR);
0179 }
0180
0181
0182 std::string profile() const
0183 {
0184 return get_info<std::string>(CL_DEVICE_PROFILE);
0185 }
0186
0187
0188 std::string version() const
0189 {
0190 return get_info<std::string>(CL_DEVICE_VERSION);
0191 }
0192
0193
0194 std::string driver_version() const
0195 {
0196 return get_info<std::string>(CL_DRIVER_VERSION);
0197 }
0198
0199
0200 std::vector<std::string> extensions() const
0201 {
0202 std::string extensions_string =
0203 get_info<std::string>(CL_DEVICE_EXTENSIONS);
0204 std::vector<std::string> extensions_vector;
0205 boost::split(extensions_vector,
0206 extensions_string,
0207 boost::is_any_of("\t "),
0208 boost::token_compress_on);
0209 return extensions_vector;
0210 }
0211
0212
0213
0214 bool supports_extension(const std::string &name) const
0215 {
0216 const std::vector<std::string> extensions = this->extensions();
0217
0218 return std::find(
0219 extensions.begin(), extensions.end(), name) != extensions.end();
0220 }
0221
0222
0223 uint_ address_bits() const
0224 {
0225 return get_info<uint_>(CL_DEVICE_ADDRESS_BITS);
0226 }
0227
0228
0229 ulong_ global_memory_size() const
0230 {
0231 return get_info<ulong_>(CL_DEVICE_GLOBAL_MEM_SIZE);
0232 }
0233
0234
0235 ulong_ local_memory_size() const
0236 {
0237 return get_info<ulong_>(CL_DEVICE_LOCAL_MEM_SIZE);
0238 }
0239
0240
0241 uint_ clock_frequency() const
0242 {
0243 return get_info<uint_>(CL_DEVICE_MAX_CLOCK_FREQUENCY);
0244 }
0245
0246
0247 uint_ compute_units() const
0248 {
0249 return get_info<uint_>(CL_DEVICE_MAX_COMPUTE_UNITS);
0250 }
0251
0252
0253 ulong_ max_memory_alloc_size() const
0254 {
0255 return get_info<ulong_>(CL_DEVICE_MAX_MEM_ALLOC_SIZE);
0256 }
0257
0258
0259 size_t max_work_group_size() const
0260 {
0261 return get_info<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE);
0262 }
0263
0264
0265 uint_ max_work_item_dimensions() const
0266 {
0267 return get_info<uint_>(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
0268 }
0269
0270
0271 template<class T>
0272 uint_ preferred_vector_width() const
0273 {
0274 return 0;
0275 }
0276
0277
0278 size_t profiling_timer_resolution() const
0279 {
0280 return get_info<size_t>(CL_DEVICE_PROFILING_TIMER_RESOLUTION);
0281 }
0282
0283
0284 bool is_subdevice() const
0285 {
0286 #if defined(BOOST_COMPUTE_CL_VERSION_1_2)
0287 try {
0288 return get_info<cl_device_id>(CL_DEVICE_PARENT_DEVICE) != 0;
0289 }
0290 catch(opencl_error&){
0291
0292
0293 return false;
0294 }
0295 #else
0296 return false;
0297 #endif
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 template<class T>
0315 T get_info(cl_device_info info) const
0316 {
0317 return detail::get_object_info<T>(clGetDeviceInfo, m_id, info);
0318 }
0319
0320
0321 template<int Enum>
0322 typename detail::get_object_info_type<device, Enum>::type
0323 get_info() const;
0324
0325 #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
0326
0327
0328
0329
0330 std::vector<device>
0331 partition(const cl_device_partition_property *properties) const
0332 {
0333
0334 uint_ count = 0;
0335 int_ ret = clCreateSubDevices(m_id, properties, 0, 0, &count);
0336 if(ret != CL_SUCCESS){
0337 BOOST_THROW_EXCEPTION(opencl_error(ret));
0338 }
0339
0340
0341 std::vector<cl_device_id> ids(count);
0342 ret = clCreateSubDevices(m_id, properties, count, &ids[0], 0);
0343 if(ret != CL_SUCCESS){
0344 BOOST_THROW_EXCEPTION(opencl_error(ret));
0345 }
0346
0347
0348 std::vector<device> devices(count);
0349 for(size_t i = 0; i < count; i++){
0350 devices[i] = device(ids[i], false);
0351 }
0352
0353 return devices;
0354 }
0355
0356
0357 std::vector<device> partition_equally(size_t count) const
0358 {
0359 cl_device_partition_property properties[] = {
0360 CL_DEVICE_PARTITION_EQUALLY,
0361 static_cast<cl_device_partition_property>(count),
0362 0
0363 };
0364
0365 return partition(properties);
0366 }
0367
0368
0369 std::vector<device>
0370 partition_by_counts(const std::vector<size_t> &counts) const
0371 {
0372 std::vector<cl_device_partition_property> properties;
0373
0374 properties.push_back(CL_DEVICE_PARTITION_BY_COUNTS);
0375 for(size_t i = 0; i < counts.size(); i++){
0376 properties.push_back(
0377 static_cast<cl_device_partition_property>(counts[i]));
0378 }
0379 properties.push_back(CL_DEVICE_PARTITION_BY_COUNTS_LIST_END);
0380 properties.push_back(0);
0381
0382 return partition(&properties[0]);
0383 }
0384
0385
0386 std::vector<device>
0387 partition_by_affinity_domain(cl_device_affinity_domain domain) const
0388 {
0389 cl_device_partition_property properties[] = {
0390 CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN,
0391 static_cast<cl_device_partition_property>(domain),
0392 0
0393 };
0394
0395 return partition(properties);
0396 }
0397 #endif
0398
0399 #if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
0400
0401
0402
0403
0404
0405
0406 ulong_ get_host_timer() const
0407 {
0408 ulong_ host_timestamp = 0;
0409 cl_int ret = clGetHostTimer(m_id, &host_timestamp);
0410 if(ret != CL_SUCCESS){
0411 BOOST_THROW_EXCEPTION(opencl_error(ret));
0412 }
0413 return host_timestamp;
0414 }
0415
0416
0417
0418
0419
0420
0421
0422
0423 std::pair<ulong_, ulong_> get_device_and_host_timer() const
0424 {
0425 ulong_ host_timestamp;
0426 ulong_ device_timestamp;
0427 cl_int ret = clGetDeviceAndHostTimer(
0428 m_id, &device_timestamp, &host_timestamp
0429 );
0430 if(ret != CL_SUCCESS){
0431 BOOST_THROW_EXCEPTION(opencl_error(ret));
0432 }
0433 return std::make_pair(
0434 device_timestamp, host_timestamp
0435 );
0436 }
0437
0438 #if !defined(BOOST_COMPUTE_NO_HDR_CHRONO) || !defined(BOOST_COMPUTE_NO_BOOST_CHRONO)
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451 template<class Duration>
0452 Duration get_host_timer() const
0453 {
0454 const ulong_ nanoseconds = this->get_host_timer();
0455 return detail::make_duration_from_nanoseconds(Duration(), nanoseconds);
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 template<class Duration>
0467 std::pair<Duration, Duration> get_device_and_host_timer() const
0468 {
0469 const std::pair<ulong_, ulong_> timestamps = this->get_device_and_host_timer();
0470 return std::make_pair(
0471 detail::make_duration_from_nanoseconds(Duration(), timestamps.first),
0472 detail::make_duration_from_nanoseconds(Duration(), timestamps.second)
0473 );
0474 }
0475 #endif
0476 #endif
0477
0478
0479 bool operator==(const device &other) const
0480 {
0481 return m_id == other.m_id;
0482 }
0483
0484
0485 bool operator!=(const device &other) const
0486 {
0487 return m_id != other.m_id;
0488 }
0489
0490
0491
0492 bool check_version(int major, int minor) const
0493 {
0494 std::stringstream stream;
0495 stream << version();
0496
0497 int actual_major, actual_minor;
0498 stream.ignore(7);
0499 stream >> actual_major;
0500 stream.ignore(1);
0501 stream >> actual_minor;
0502
0503 return actual_major > major ||
0504 (actual_major == major && actual_minor >= minor);
0505 }
0506
0507 private:
0508 cl_device_id m_id;
0509 };
0510
0511
0512 template<>
0513 inline uint_ device::preferred_vector_width<short_>() const
0514 {
0515 return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT);
0516 }
0517
0518
0519 template<>
0520 inline uint_ device::preferred_vector_width<int_>() const
0521 {
0522 return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT);
0523 }
0524
0525
0526 template<>
0527 inline uint_ device::preferred_vector_width<long_>() const
0528 {
0529 return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG);
0530 }
0531
0532
0533 template<>
0534 inline uint_ device::preferred_vector_width<float_>() const
0535 {
0536 return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT);
0537 }
0538
0539
0540 template<>
0541 inline uint_ device::preferred_vector_width<double_>() const
0542 {
0543 return get_info<uint_>(CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE);
0544 }
0545
0546
0547 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0548 ((cl_uint, CL_DEVICE_ADDRESS_BITS))
0549 ((bool, CL_DEVICE_AVAILABLE))
0550 ((bool, CL_DEVICE_COMPILER_AVAILABLE))
0551 ((bool, CL_DEVICE_ENDIAN_LITTLE))
0552 ((bool, CL_DEVICE_ERROR_CORRECTION_SUPPORT))
0553 ((cl_device_exec_capabilities, CL_DEVICE_EXECUTION_CAPABILITIES))
0554 ((std::string, CL_DEVICE_EXTENSIONS))
0555 ((cl_ulong, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE))
0556 ((cl_device_mem_cache_type, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE))
0557 ((cl_uint, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE))
0558 ((cl_ulong, CL_DEVICE_GLOBAL_MEM_SIZE))
0559 ((bool, CL_DEVICE_IMAGE_SUPPORT))
0560 ((size_t, CL_DEVICE_IMAGE2D_MAX_HEIGHT))
0561 ((size_t, CL_DEVICE_IMAGE2D_MAX_WIDTH))
0562 ((size_t, CL_DEVICE_IMAGE3D_MAX_DEPTH))
0563 ((size_t, CL_DEVICE_IMAGE3D_MAX_HEIGHT))
0564 ((size_t, CL_DEVICE_IMAGE3D_MAX_WIDTH))
0565 ((cl_ulong, CL_DEVICE_LOCAL_MEM_SIZE))
0566 ((cl_device_local_mem_type, CL_DEVICE_LOCAL_MEM_TYPE))
0567 ((cl_uint, CL_DEVICE_MAX_CLOCK_FREQUENCY))
0568 ((cl_uint, CL_DEVICE_MAX_COMPUTE_UNITS))
0569 ((cl_uint, CL_DEVICE_MAX_CONSTANT_ARGS))
0570 ((cl_ulong, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE))
0571 ((cl_ulong, CL_DEVICE_MAX_MEM_ALLOC_SIZE))
0572 ((size_t, CL_DEVICE_MAX_PARAMETER_SIZE))
0573 ((cl_uint, CL_DEVICE_MAX_READ_IMAGE_ARGS))
0574 ((cl_uint, CL_DEVICE_MAX_SAMPLERS))
0575 ((size_t, CL_DEVICE_MAX_WORK_GROUP_SIZE))
0576 ((cl_uint, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS))
0577 ((std::vector<size_t>, CL_DEVICE_MAX_WORK_ITEM_SIZES))
0578 ((cl_uint, CL_DEVICE_MAX_WRITE_IMAGE_ARGS))
0579 ((cl_uint, CL_DEVICE_MEM_BASE_ADDR_ALIGN))
0580 ((cl_uint, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE))
0581 ((std::string, CL_DEVICE_NAME))
0582 ((cl_platform_id, CL_DEVICE_PLATFORM))
0583 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR))
0584 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT))
0585 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT))
0586 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG))
0587 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT))
0588 ((cl_uint, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE))
0589 ((std::string, CL_DEVICE_PROFILE))
0590 ((size_t, CL_DEVICE_PROFILING_TIMER_RESOLUTION))
0591 ((cl_command_queue_properties, CL_DEVICE_QUEUE_PROPERTIES))
0592 ((cl_device_fp_config, CL_DEVICE_SINGLE_FP_CONFIG))
0593 ((cl_device_type, CL_DEVICE_TYPE))
0594 ((std::string, CL_DEVICE_VENDOR))
0595 ((cl_uint, CL_DEVICE_VENDOR_ID))
0596 ((std::string, CL_DEVICE_VERSION))
0597 ((std::string, CL_DRIVER_VERSION))
0598 )
0599
0600 #ifdef CL_DEVICE_DOUBLE_FP_CONFIG
0601 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0602 ((cl_device_fp_config, CL_DEVICE_DOUBLE_FP_CONFIG))
0603 )
0604 #endif
0605
0606 #ifdef CL_DEVICE_HALF_FP_CONFIG
0607 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0608 ((cl_device_fp_config, CL_DEVICE_HALF_FP_CONFIG))
0609 )
0610 #endif
0611
0612 #ifdef BOOST_COMPUTE_CL_VERSION_1_1
0613 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0614 ((bool, CL_DEVICE_HOST_UNIFIED_MEMORY))
0615 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR))
0616 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT))
0617 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT))
0618 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG))
0619 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT))
0620 ((cl_uint, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE))
0621 ((std::string, CL_DEVICE_OPENCL_C_VERSION))
0622 )
0623 #endif
0624
0625 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
0626 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0627 ((std::string, CL_DEVICE_BUILT_IN_KERNELS))
0628 ((bool, CL_DEVICE_LINKER_AVAILABLE))
0629 ((cl_device_id, CL_DEVICE_PARENT_DEVICE))
0630 ((cl_uint, CL_DEVICE_PARTITION_MAX_SUB_DEVICES))
0631 ((cl_device_partition_property, CL_DEVICE_PARTITION_PROPERTIES))
0632 ((cl_device_affinity_domain, CL_DEVICE_PARTITION_AFFINITY_DOMAIN))
0633 ((cl_device_partition_property, CL_DEVICE_PARTITION_TYPE))
0634 ((size_t, CL_DEVICE_PRINTF_BUFFER_SIZE))
0635 ((bool, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC))
0636 ((cl_uint, CL_DEVICE_REFERENCE_COUNT))
0637 )
0638 #endif
0639
0640 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
0641 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0642 ((size_t, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE))
0643 ((size_t, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE))
0644 ((cl_uint, CL_DEVICE_MAX_ON_DEVICE_EVENTS))
0645 ((cl_uint, CL_DEVICE_MAX_ON_DEVICE_QUEUES))
0646 ((cl_uint, CL_DEVICE_MAX_PIPE_ARGS))
0647 ((cl_uint, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS))
0648 ((cl_uint, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS))
0649 ((cl_uint, CL_DEVICE_PIPE_MAX_PACKET_SIZE))
0650 ((cl_uint, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT))
0651 ((cl_uint, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT))
0652 ((cl_uint, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT))
0653 ((cl_uint, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE))
0654 ((cl_uint, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE))
0655 ((cl_command_queue_properties, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES))
0656 ((cl_device_svm_capabilities, CL_DEVICE_SVM_CAPABILITIES))
0657 ((cl_uint, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT))
0658 ((cl_uint, CL_DEVICE_IMAGE_PITCH_ALIGNMENT))
0659 )
0660 #endif
0661
0662 #ifdef BOOST_COMPUTE_CL_VERSION_2_1
0663 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(device,
0664 ((std::string, CL_DEVICE_IL_VERSION))
0665 ((cl_uint, CL_DEVICE_MAX_NUM_SUB_GROUPS))
0666 ((bool, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS))
0667 )
0668 #endif
0669
0670 }
0671 }
0672
0673 #endif