1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
11 #ifndef BOOST_COMPUTE_SYSTEM_HPP
12 #define BOOST_COMPUTE_SYSTEM_HPP
18 #include <boost/throw_exception.hpp>
20 #include <boost/compute/cl.hpp>
21 #include <boost/compute/device.hpp>
22 #include <boost/compute/context.hpp>
23 #include <boost/compute/platform.hpp>
24 #include <boost/compute/command_queue.hpp>
25 #include <boost/compute/detail/getenv.hpp>
26 #include <boost/compute/exception/no_device_found.hpp>
32 /// \brief Provides access to platforms and devices on the system.
34 /// The system class contains a set of static functions which provide access to
35 /// the OpenCL platforms and compute devices on the host system.
37 /// The default_device() convenience method automatically selects and returns
38 /// the "best" compute device for the system following a set of heuristics and
39 /// environment variables. This simplifies setup of the OpenCL enviornment.
41 /// \see platform, device, context
45 /// Returns the default compute device for the system.
47 /// The default device is selected based on a set of heuristics and can be
48 /// influenced using one of the following environment variables:
50 /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE -
51 /// name of the compute device (e.g. "GTX TITAN")
52 /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE_TYPE
53 /// type of the compute device (e.g. "GPU" or "CPU")
54 /// \li \c BOOST_COMPUTE_DEFAULT_PLATFORM -
55 /// name of the platform (e.g. "NVIDIA CUDA")
56 /// \li \c BOOST_COMPUTE_DEFAULT_VENDOR -
57 /// name of the device vendor (e.g. "NVIDIA")
58 /// \li \c BOOST_COMPUTE_DEFAULT_ENFORCE -
59 /// If this is set to "1", then throw a no_device_found() exception
60 /// if any of the above environment variables is set, but a matching
61 /// device was not found.
63 /// The default device is determined once on the first time this function
64 /// is called. Calling this function multiple times will always result in
65 /// the same device being returned.
67 /// If no OpenCL device is found on the system, a no_device_found exception
70 /// For example, to print the name of the default compute device on the
73 /// // get the default compute device
74 /// boost::compute::device device = boost::compute::system::default_device();
76 /// // print the name of the device
77 /// std::cout << "default device: " << device.name() << std::endl;
79 static device default_device()
81 static device default_device = find_default_device();
83 return default_device;
86 /// Returns the device with \p name.
88 /// \throws no_device_found if no device with \p name is found.
89 static device find_device(const std::string &name)
91 const std::vector<device> devices = system::devices();
92 for(size_t i = 0; i < devices.size(); i++){
93 const device& device = devices[i];
95 if(device.name() == name){
100 BOOST_THROW_EXCEPTION(no_device_found());
103 /// Returns a vector containing all of the compute devices on
106 /// For example, to print out the name of each OpenCL-capable device
107 /// available on the system:
109 /// for(const auto &device : boost::compute::system::devices()){
110 /// std::cout << device.name() << std::endl;
113 static std::vector<device> devices()
115 std::vector<device> devices;
117 const std::vector<platform> platforms = system::platforms();
118 for(size_t i = 0; i < platforms.size(); i++){
119 const std::vector<device> platform_devices = platforms[i].devices();
122 devices.end(), platform_devices.begin(), platform_devices.end()
129 /// Returns the number of compute devices on the system.
130 static size_t device_count()
134 const std::vector<platform> platforms = system::platforms();
135 for(size_t i = 0; i < platforms.size(); i++){
136 count += platforms[i].device_count();
142 /// Returns the default context for the system.
144 /// The default context is created for the default device on the system
145 /// (as returned by default_device()).
147 /// The default context is created once on the first time this function is
148 /// called. Calling this function multiple times will always result in the
149 /// same context object being returned.
150 static context default_context()
152 static context default_context(default_device());
154 return default_context;
157 /// Returns the default command queue for the system.
158 static command_queue& default_queue()
160 static command_queue queue(default_context(), default_device());
165 /// Blocks until all outstanding computations on the default
166 /// command queue are complete.
168 /// This is equivalent to:
170 /// system::default_queue().finish();
174 default_queue().finish();
177 /// Returns a vector containing each of the OpenCL platforms on the system.
179 /// For example, to print out the name of each OpenCL platform present on
182 /// for(const auto &platform : boost::compute::system::platforms()){
183 /// std::cout << platform.name() << std::endl;
186 static std::vector<platform> platforms()
189 clGetPlatformIDs(0, 0, &count);
191 std::vector<platform> platforms;
194 std::vector<cl_platform_id> platform_ids(count);
195 clGetPlatformIDs(count, &platform_ids[0], 0);
197 for(size_t i = 0; i < platform_ids.size(); i++){
198 platforms.push_back(platform(platform_ids[i]));
204 /// Returns the number of compute platforms on the system.
205 static size_t platform_count()
208 clGetPlatformIDs(0, 0, &count);
209 return static_cast<size_t>(count);
214 static device find_default_device()
216 // get a list of all devices on the system
217 const std::vector<device> devices_ = devices();
218 if(devices_.empty()){
219 BOOST_THROW_EXCEPTION(no_device_found());
222 // check for device from environment variable
223 const char *name = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE");
224 const char *type = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
225 const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
226 const char *vendor = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
227 const char *enforce = detail::getenv("BOOST_COMPUTE_DEFAULT_ENFORCE");
229 if(name || type || platform || vendor){
230 for(size_t i = 0; i < devices_.size(); i++){
231 const device& device = devices_[i];
232 if (name && !matches(device.name(), name))
235 if (type && matches(std::string("GPU"), type))
236 if (!(device.type() & device::gpu))
239 if (type && matches(std::string("CPU"), type))
240 if (!(device.type() & device::cpu))
243 if (platform && !matches(device.platform().name(), platform))
246 if (vendor && !matches(device.vendor(), vendor))
252 if(enforce && enforce[0] == '1')
253 BOOST_THROW_EXCEPTION(no_device_found());
256 // find the first gpu device
257 for(size_t i = 0; i < devices_.size(); i++){
258 const device& device = devices_[i];
260 if(device.type() & device::gpu){
265 // find the first cpu device
266 for(size_t i = 0; i < devices_.size(); i++){
267 const device& device = devices_[i];
269 if(device.type() & device::cpu){
274 // return the first device found
279 static bool matches(const std::string &str, const std::string &pattern)
281 return str.find(pattern) != std::string::npos;
285 } // end compute namespace
286 } // end boost namespace
288 #endif // BOOST_COMPUTE_SYSTEM_HPP