File indexing completed on 2025-09-17 08:24:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_SYSTEM_HPP
0012 #define BOOST_COMPUTE_SYSTEM_HPP
0013
0014 #include <string>
0015 #include <vector>
0016 #include <cstdlib>
0017
0018 #include <boost/throw_exception.hpp>
0019
0020 #if defined(BOOST_COMPUTE_THREAD_SAFE)
0021 # if defined(BOOST_COMPUTE_USE_CPP11)
0022 # include <mutex>
0023 # include <thread>
0024 # include <atomic>
0025 # else
0026 # include <boost/thread/mutex.hpp>
0027 # include <boost/thread/lock_guard.hpp>
0028 # include <boost/atomic.hpp>
0029 # endif
0030 #endif
0031
0032 #include <boost/compute/cl.hpp>
0033 #include <boost/compute/device.hpp>
0034 #include <boost/compute/context.hpp>
0035 #include <boost/compute/platform.hpp>
0036 #include <boost/compute/command_queue.hpp>
0037 #include <boost/compute/detail/getenv.hpp>
0038 #include <boost/compute/exception/no_device_found.hpp>
0039 #include <boost/compute/exception/context_error.hpp>
0040
0041 namespace boost {
0042 namespace compute {
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 class system
0056 {
0057 public:
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 static device default_device()
0093 {
0094 return init_default_device();
0095 }
0096
0097
0098
0099
0100 static device find_device(const std::string &name)
0101 {
0102 const std::vector<device> devices = system::devices();
0103 for(size_t i = 0; i < devices.size(); i++){
0104 const device& device = devices[i];
0105
0106 if(device.name() == name){
0107 return device;
0108 }
0109 }
0110
0111 BOOST_THROW_EXCEPTION(no_device_found());
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 static std::vector<device> devices()
0125 {
0126 std::vector<device> devices;
0127
0128 const std::vector<platform> platforms = system::platforms();
0129 for(size_t i = 0; i < platforms.size(); i++){
0130 const std::vector<device> platform_devices = platforms[i].devices();
0131
0132 devices.insert(
0133 devices.end(), platform_devices.begin(), platform_devices.end()
0134 );
0135 }
0136
0137 return devices;
0138 }
0139
0140
0141 static size_t device_count()
0142 {
0143 size_t count = 0;
0144
0145 const std::vector<platform> platforms = system::platforms();
0146 for(size_t i = 0; i < platforms.size(); i++){
0147 count += platforms[i].device_count();
0148 }
0149
0150 return count;
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 static context default_context()
0162 {
0163 return init_default_context();
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 static command_queue& default_queue(const command_queue &user_queue = command_queue())
0182 {
0183 return init_default_queue(user_queue);
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193 static void finish()
0194 {
0195 default_queue().finish();
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 static std::vector<platform> platforms()
0208 {
0209 cl_uint count = 0;
0210 clGetPlatformIDs(0, 0, &count);
0211
0212 std::vector<platform> platforms;
0213 if(count > 0)
0214 {
0215 std::vector<cl_platform_id> platform_ids(count);
0216 clGetPlatformIDs(count, &platform_ids[0], 0);
0217
0218 for(size_t i = 0; i < platform_ids.size(); i++){
0219 platforms.push_back(platform(platform_ids[i]));
0220 }
0221 }
0222 return platforms;
0223 }
0224
0225
0226 static size_t platform_count()
0227 {
0228 cl_uint count = 0;
0229 clGetPlatformIDs(0, 0, &count);
0230 return static_cast<size_t>(count);
0231 }
0232
0233 private:
0234
0235 static device find_default_device()
0236 {
0237
0238 const std::vector<device> devices_ = devices();
0239 if(devices_.empty()){
0240 BOOST_THROW_EXCEPTION(no_device_found());
0241 }
0242
0243
0244 const char *name = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE");
0245 const char *type = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
0246 const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
0247 const char *vendor = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
0248 const char *enforce = detail::getenv("BOOST_COMPUTE_DEFAULT_ENFORCE");
0249
0250 if(name || type || platform || vendor){
0251 for(size_t i = 0; i < devices_.size(); i++){
0252 const device& device = devices_[i];
0253 if (name && !matches(device.name(), name))
0254 continue;
0255
0256 if (type && matches(std::string("GPU"), type))
0257 if (!(device.type() & device::gpu))
0258 continue;
0259
0260 if (type && matches(std::string("CPU"), type))
0261 if (!(device.type() & device::cpu))
0262 continue;
0263
0264 if (platform && !matches(device.platform().name(), platform))
0265 continue;
0266
0267 if (vendor && !matches(device.vendor(), vendor))
0268 continue;
0269
0270 return device;
0271 }
0272
0273 if(enforce && enforce[0] == '1')
0274 BOOST_THROW_EXCEPTION(no_device_found());
0275 }
0276
0277
0278 for(size_t i = 0; i < devices_.size(); i++){
0279 const device& device = devices_[i];
0280
0281 if(device.type() & device::gpu){
0282 return device;
0283 }
0284 }
0285
0286
0287 for(size_t i = 0; i < devices_.size(); i++){
0288 const device& device = devices_[i];
0289
0290 if(device.type() & device::cpu){
0291 return device;
0292 }
0293 }
0294
0295
0296 return devices_[0];
0297 }
0298
0299
0300 static bool matches(const std::string &str, const std::string &pattern)
0301 {
0302 return str.find(pattern) != std::string::npos;
0303 }
0304
0305
0306 static device init_default_device(const device &user_device = device())
0307 {
0308 static device default_device;
0309
0310 #ifdef BOOST_COMPUTE_THREAD_SAFE
0311 #ifdef BOOST_COMPUTE_USE_CPP11
0312 using namespace std;
0313 #else
0314 using namespace boost;
0315 #endif
0316 static atomic<bool> is_init;
0317 static mutex init_mutex;
0318
0319 bool is_init_value = is_init.load(memory_order_consume);
0320 if (!is_init_value)
0321 {
0322 lock_guard<mutex> lock(init_mutex);
0323 is_init_value = is_init.load(memory_order_consume);
0324 if (!is_init_value)
0325 {
0326 default_device = user_device.get() ?
0327 user_device : find_default_device();
0328
0329 is_init.store(true, memory_order_release);
0330 }
0331 }
0332 #else
0333 if (!default_device.get())
0334 {
0335 default_device = user_device.get() ?
0336 user_device : find_default_device();
0337 }
0338 #endif
0339 return default_device;
0340 }
0341
0342
0343 static context init_default_context(const context &user_context = context())
0344 {
0345 static context default_context;
0346
0347 #ifdef BOOST_COMPUTE_THREAD_SAFE
0348 #ifdef BOOST_COMPUTE_USE_CPP11
0349 using namespace std;
0350 #else
0351 using namespace boost;
0352 #endif
0353 static atomic<bool> is_init;
0354 static mutex init_mutex;
0355
0356 bool is_init_value = is_init.load(memory_order_consume);
0357 if (!is_init_value)
0358 {
0359 lock_guard<mutex> lock(init_mutex);
0360 is_init_value = is_init.load(memory_order_consume);
0361 if (!is_init_value)
0362 {
0363 default_context = user_context.get() ?
0364 user_context : context(default_device());
0365
0366 is_init.store(true, memory_order_release);
0367 }
0368 }
0369 #else
0370 if (!default_context.get())
0371 {
0372 default_context = user_context.get() ?
0373 user_context : context(default_device());
0374 }
0375 #endif
0376 return default_context;
0377 }
0378
0379
0380 static void init_default_device_and_context(const command_queue &user_queue)
0381 {
0382 device user_device = user_queue.get_device();
0383 context user_context = user_queue.get_context();
0384
0385 if ( (user_device != init_default_device(user_device)) ||
0386 (user_context != init_default_context(user_context)) )
0387 {
0388
0389 BOOST_THROW_EXCEPTION(set_default_queue_error());
0390 }
0391 }
0392
0393
0394 static command_queue& init_default_queue(const command_queue &user_queue = command_queue())
0395 {
0396 static command_queue default_queue;
0397
0398 #ifdef BOOST_COMPUTE_THREAD_SAFE
0399 #ifdef BOOST_COMPUTE_USE_CPP11
0400 using namespace std;
0401 #else
0402 using namespace boost;
0403 #endif
0404 static atomic<bool> is_init;
0405 static mutex init_mutex;
0406
0407 bool is_init_value = is_init.load(memory_order_consume);
0408 if (!is_init_value)
0409 {
0410 lock_guard<mutex> lock(init_mutex);
0411 is_init_value = is_init.load(memory_order_consume);
0412 if (!is_init_value)
0413 {
0414 if (user_queue.get())
0415 init_default_device_and_context(user_queue);
0416
0417 default_queue = user_queue.get() ?
0418 user_queue :
0419 command_queue(default_context(), default_device());
0420
0421 is_init.store(true, memory_order_release);
0422 }
0423 }
0424 #else
0425 if (!default_queue.get())
0426 {
0427 if (user_queue.get())
0428 init_default_device_and_context(user_queue);
0429
0430 default_queue = user_queue.get() ?
0431 user_queue :
0432 command_queue(default_context(), default_device());
0433 }
0434 #endif
0435 else
0436 {
0437 BOOST_ASSERT_MSG(user_queue.get() == 0,
0438 "Default command queue has already been set.");
0439 }
0440 return default_queue;
0441 }
0442 };
0443
0444 }
0445 }
0446
0447 #endif