Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:04:32

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
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 #include <boost/compute/cl.hpp>
0021 #include <boost/compute/device.hpp>
0022 #include <boost/compute/context.hpp>
0023 #include <boost/compute/platform.hpp>
0024 #include <boost/compute/command_queue.hpp>
0025 #include <boost/compute/detail/getenv.hpp>
0026 #include <boost/compute/exception/no_device_found.hpp>
0027 
0028 namespace boost {
0029 namespace compute {
0030 
0031 /// \class system
0032 /// \brief Provides access to platforms and devices on the system.
0033 ///
0034 /// The system class contains a set of static functions which provide access to
0035 /// the OpenCL platforms and compute devices on the host system.
0036 ///
0037 /// The default_device() convenience method automatically selects and returns
0038 /// the "best" compute device for the system following a set of heuristics and
0039 /// environment variables. This simplifies setup of the OpenCL enviornment.
0040 ///
0041 /// \see platform, device, context
0042 class system
0043 {
0044 public:
0045     /// Returns the default compute device for the system.
0046     ///
0047     /// The default device is selected based on a set of heuristics and can be
0048     /// influenced using one of the following environment variables:
0049     ///
0050     /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE -
0051     ///        name of the compute device (e.g. "GTX TITAN")
0052     /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE_TYPE
0053     ///        type of the compute device (e.g. "GPU" or "CPU")
0054     /// \li \c BOOST_COMPUTE_DEFAULT_PLATFORM -
0055     ///        name of the platform (e.g. "NVIDIA CUDA")
0056     /// \li \c BOOST_COMPUTE_DEFAULT_VENDOR -
0057     ///        name of the device vendor (e.g. "NVIDIA")
0058     /// \li \c BOOST_COMPUTE_DEFAULT_ENFORCE -
0059     ///        If this is set to "1", then throw a no_device_found() exception
0060     ///        if any of the above environment variables is set, but a matching
0061     ///        device was not found.
0062     ///
0063     /// The default device is determined once on the first time this function
0064     /// is called. Calling this function multiple times will always result in
0065     /// the same device being returned.
0066     ///
0067     /// If no OpenCL device is found on the system, a no_device_found exception
0068     /// is thrown.
0069     ///
0070     /// For example, to print the name of the default compute device on the
0071     /// system:
0072     /// \code
0073     /// // get the default compute device
0074     /// boost::compute::device device = boost::compute::system::default_device();
0075     ///
0076     /// // print the name of the device
0077     /// std::cout << "default device: " << device.name() << std::endl;
0078     /// \endcode
0079     static device default_device()
0080     {
0081         static device default_device = find_default_device();
0082 
0083         return default_device;
0084     }
0085 
0086     /// Returns the device with \p name.
0087     ///
0088     /// \throws no_device_found if no device with \p name is found.
0089     static device find_device(const std::string &name)
0090     {
0091         const std::vector<device> devices = system::devices();
0092         for(size_t i = 0; i < devices.size(); i++){
0093             const device& device = devices[i];
0094 
0095             if(device.name() == name){
0096                 return device;
0097             }
0098         }
0099 
0100         BOOST_THROW_EXCEPTION(no_device_found());
0101     }
0102 
0103     /// Returns a vector containing all of the compute devices on
0104     /// the system.
0105     ///
0106     /// For example, to print out the name of each OpenCL-capable device
0107     /// available on the system:
0108     /// \code
0109     /// for(const auto &device : boost::compute::system::devices()){
0110     ///     std::cout << device.name() << std::endl;
0111     /// }
0112     /// \endcode
0113     static std::vector<device> devices()
0114     {
0115         std::vector<device> devices;
0116 
0117         const std::vector<platform> platforms = system::platforms();
0118         for(size_t i = 0; i < platforms.size(); i++){
0119             const std::vector<device> platform_devices = platforms[i].devices();
0120 
0121             devices.insert(
0122                 devices.end(), platform_devices.begin(), platform_devices.end()
0123             );
0124         }
0125 
0126         return devices;
0127     }
0128 
0129     /// Returns the number of compute devices on the system.
0130     static size_t device_count()
0131     {
0132         size_t count = 0;
0133 
0134         const std::vector<platform> platforms = system::platforms();
0135         for(size_t i = 0; i < platforms.size(); i++){
0136             count += platforms[i].device_count();
0137         }
0138 
0139         return count;
0140     }
0141 
0142     /// Returns the default context for the system.
0143     ///
0144     /// The default context is created for the default device on the system
0145     /// (as returned by default_device()).
0146     ///
0147     /// The default context is created once on the first time this function is
0148     /// called. Calling this function multiple times will always result in the
0149     /// same context object being returned.
0150     static context default_context()
0151     {
0152         static context default_context(default_device());
0153 
0154         return default_context;
0155     }
0156 
0157     /// Returns the default command queue for the system.
0158     static command_queue& default_queue()
0159     {
0160         static command_queue queue(default_context(), default_device());
0161 
0162         return queue;
0163     }
0164 
0165     /// Blocks until all outstanding computations on the default
0166     /// command queue are complete.
0167     ///
0168     /// This is equivalent to:
0169     /// \code
0170     /// system::default_queue().finish();
0171     /// \endcode
0172     static void finish()
0173     {
0174         default_queue().finish();
0175     }
0176 
0177     /// Returns a vector containing each of the OpenCL platforms on the system.
0178     ///
0179     /// For example, to print out the name of each OpenCL platform present on
0180     /// the system:
0181     /// \code
0182     /// for(const auto &platform : boost::compute::system::platforms()){
0183     ///     std::cout << platform.name() << std::endl;
0184     /// }
0185     /// \endcode
0186     static std::vector<platform> platforms()
0187     {
0188         cl_uint count = 0;
0189         clGetPlatformIDs(0, 0, &count);
0190 
0191         std::vector<platform> platforms;
0192         if(count > 0)
0193         {
0194             std::vector<cl_platform_id> platform_ids(count);
0195             clGetPlatformIDs(count, &platform_ids[0], 0);
0196 
0197             for(size_t i = 0; i < platform_ids.size(); i++){
0198                 platforms.push_back(platform(platform_ids[i]));
0199             }
0200         }
0201         return platforms;
0202     }
0203 
0204     /// Returns the number of compute platforms on the system.
0205     static size_t platform_count()
0206     {
0207         cl_uint count = 0;
0208         clGetPlatformIDs(0, 0, &count);
0209         return static_cast<size_t>(count);
0210     }
0211 
0212 private:
0213     /// \internal_
0214     static device find_default_device()
0215     {
0216         // get a list of all devices on the system
0217         const std::vector<device> devices_ = devices();
0218         if(devices_.empty()){
0219             BOOST_THROW_EXCEPTION(no_device_found());
0220         }
0221 
0222         // check for device from environment variable
0223         const char *name     = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE");
0224         const char *type     = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
0225         const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
0226         const char *vendor   = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
0227         const char *enforce  = detail::getenv("BOOST_COMPUTE_DEFAULT_ENFORCE");
0228 
0229         if(name || type || platform || vendor){
0230             for(size_t i = 0; i < devices_.size(); i++){
0231                 const device& device = devices_[i];
0232                 if (name && !matches(device.name(), name))
0233                     continue;
0234 
0235                 if (type && matches(std::string("GPU"), type))
0236                     if (!(device.type() & device::gpu))
0237                         continue;
0238 
0239                 if (type && matches(std::string("CPU"), type))
0240                     if (!(device.type() & device::cpu))
0241                         continue;
0242 
0243                 if (platform && !matches(device.platform().name(), platform))
0244                     continue;
0245 
0246                 if (vendor && !matches(device.vendor(), vendor))
0247                     continue;
0248 
0249                 return device;
0250             }
0251 
0252             if(enforce && enforce[0] == '1')
0253                 BOOST_THROW_EXCEPTION(no_device_found());
0254         }
0255 
0256         // find the first gpu device
0257         for(size_t i = 0; i < devices_.size(); i++){
0258             const device& device = devices_[i];
0259 
0260             if(device.type() & device::gpu){
0261                 return device;
0262             }
0263         }
0264 
0265         // find the first cpu device
0266         for(size_t i = 0; i < devices_.size(); i++){
0267             const device& device = devices_[i];
0268 
0269             if(device.type() & device::cpu){
0270                 return device;
0271             }
0272         }
0273 
0274         // return the first device found
0275         return devices_[0];
0276     }
0277 
0278     /// \internal_
0279     static bool matches(const std::string &str, const std::string &pattern)
0280     {
0281         return str.find(pattern) != std::string::npos;
0282     }
0283 };
0284 
0285 } // end compute namespace
0286 } // end boost namespace
0287 
0288 #endif // BOOST_COMPUTE_SYSTEM_HPP