]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/compute/system.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / compute / system.hpp
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
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
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10
11 #ifndef BOOST_COMPUTE_SYSTEM_HPP
12 #define BOOST_COMPUTE_SYSTEM_HPP
13
14 #include <string>
15 #include <vector>
16 #include <cstdlib>
17
18 #include <boost/throw_exception.hpp>
19
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>
27
28 namespace boost {
29 namespace compute {
30
31 /// \class system
32 /// \brief Provides access to platforms and devices on the system.
33 ///
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.
36 ///
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.
40 ///
41 /// \see platform, device, context
42 class system
43 {
44 public:
45 /// Returns the default compute device for the system.
46 ///
47 /// The default device is selected based on a set of heuristics and can be
48 /// influenced using one of the following environment variables:
49 ///
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.
62 ///
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.
66 ///
67 /// If no OpenCL device is found on the system, a no_device_found exception
68 /// is thrown.
69 ///
70 /// For example, to print the name of the default compute device on the
71 /// system:
72 /// \code
73 /// // get the default compute device
74 /// boost::compute::device device = boost::compute::system::default_device();
75 ///
76 /// // print the name of the device
77 /// std::cout << "default device: " << device.name() << std::endl;
78 /// \endcode
79 static device default_device()
80 {
81 static device default_device = find_default_device();
82
83 return default_device;
84 }
85
86 /// Returns the device with \p name.
87 ///
88 /// \throws no_device_found if no device with \p name is found.
89 static device find_device(const std::string &name)
90 {
91 const std::vector<device> devices = system::devices();
92 for(size_t i = 0; i < devices.size(); i++){
93 const device& device = devices[i];
94
95 if(device.name() == name){
96 return device;
97 }
98 }
99
100 BOOST_THROW_EXCEPTION(no_device_found());
101 }
102
103 /// Returns a vector containing all of the compute devices on
104 /// the system.
105 ///
106 /// For example, to print out the name of each OpenCL-capable device
107 /// available on the system:
108 /// \code
109 /// for(const auto &device : boost::compute::system::devices()){
110 /// std::cout << device.name() << std::endl;
111 /// }
112 /// \endcode
113 static std::vector<device> devices()
114 {
115 std::vector<device> devices;
116
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();
120
121 devices.insert(
122 devices.end(), platform_devices.begin(), platform_devices.end()
123 );
124 }
125
126 return devices;
127 }
128
129 /// Returns the number of compute devices on the system.
130 static size_t device_count()
131 {
132 size_t count = 0;
133
134 const std::vector<platform> platforms = system::platforms();
135 for(size_t i = 0; i < platforms.size(); i++){
136 count += platforms[i].device_count();
137 }
138
139 return count;
140 }
141
142 /// Returns the default context for the system.
143 ///
144 /// The default context is created for the default device on the system
145 /// (as returned by default_device()).
146 ///
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()
151 {
152 static context default_context(default_device());
153
154 return default_context;
155 }
156
157 /// Returns the default command queue for the system.
158 static command_queue& default_queue()
159 {
160 static command_queue queue(default_context(), default_device());
161
162 return queue;
163 }
164
165 /// Blocks until all outstanding computations on the default
166 /// command queue are complete.
167 ///
168 /// This is equivalent to:
169 /// \code
170 /// system::default_queue().finish();
171 /// \endcode
172 static void finish()
173 {
174 default_queue().finish();
175 }
176
177 /// Returns a vector containing each of the OpenCL platforms on the system.
178 ///
179 /// For example, to print out the name of each OpenCL platform present on
180 /// the system:
181 /// \code
182 /// for(const auto &platform : boost::compute::system::platforms()){
183 /// std::cout << platform.name() << std::endl;
184 /// }
185 /// \endcode
186 static std::vector<platform> platforms()
187 {
188 cl_uint count = 0;
189 clGetPlatformIDs(0, 0, &count);
190
191 std::vector<platform> platforms;
192 if(count > 0)
193 {
194 std::vector<cl_platform_id> platform_ids(count);
195 clGetPlatformIDs(count, &platform_ids[0], 0);
196
197 for(size_t i = 0; i < platform_ids.size(); i++){
198 platforms.push_back(platform(platform_ids[i]));
199 }
200 }
201 return platforms;
202 }
203
204 /// Returns the number of compute platforms on the system.
205 static size_t platform_count()
206 {
207 cl_uint count = 0;
208 clGetPlatformIDs(0, 0, &count);
209 return static_cast<size_t>(count);
210 }
211
212 private:
213 /// \internal_
214 static device find_default_device()
215 {
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());
220 }
221
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");
228
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))
233 continue;
234
235 if (type && matches(std::string("GPU"), type))
236 if (!(device.type() & device::gpu))
237 continue;
238
239 if (type && matches(std::string("CPU"), type))
240 if (!(device.type() & device::cpu))
241 continue;
242
243 if (platform && !matches(device.platform().name(), platform))
244 continue;
245
246 if (vendor && !matches(device.vendor(), vendor))
247 continue;
248
249 return device;
250 }
251
252 if(enforce && enforce[0] == '1')
253 BOOST_THROW_EXCEPTION(no_device_found());
254 }
255
256 // find the first gpu device
257 for(size_t i = 0; i < devices_.size(); i++){
258 const device& device = devices_[i];
259
260 if(device.type() & device::gpu){
261 return device;
262 }
263 }
264
265 // find the first cpu device
266 for(size_t i = 0; i < devices_.size(); i++){
267 const device& device = devices_[i];
268
269 if(device.type() & device::cpu){
270 return device;
271 }
272 }
273
274 // return the first device found
275 return devices_[0];
276 }
277
278 /// \internal_
279 static bool matches(const std::string &str, const std::string &pattern)
280 {
281 return str.find(pattern) != std::string::npos;
282 }
283 };
284
285 } // end compute namespace
286 } // end boost namespace
287
288 #endif // BOOST_COMPUTE_SYSTEM_HPP