281 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //---------------------------------------------------------------------------//
 | |
| // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0
 | |
| // See accompanying file LICENSE_1_0.txt or copy at
 | |
| // http://www.boost.org/LICENSE_1_0.txt
 | |
| //
 | |
| // See http://boostorg.github.com/compute for more information.
 | |
| //---------------------------------------------------------------------------//
 | |
| 
 | |
| #ifndef BOOST_COMPUTE_SYSTEM_HPP
 | |
| #define BOOST_COMPUTE_SYSTEM_HPP
 | |
| 
 | |
| #include <string>
 | |
| #include <vector>
 | |
| #include <cstdlib>
 | |
| 
 | |
| #include <boost/throw_exception.hpp>
 | |
| 
 | |
| #include <boost/compute/cl.hpp>
 | |
| #include <boost/compute/device.hpp>
 | |
| #include <boost/compute/context.hpp>
 | |
| #include <boost/compute/platform.hpp>
 | |
| #include <boost/compute/command_queue.hpp>
 | |
| #include <boost/compute/detail/getenv.hpp>
 | |
| #include <boost/compute/exception/no_device_found.hpp>
 | |
| 
 | |
| namespace boost {
 | |
| namespace compute {
 | |
| 
 | |
| /// \class system
 | |
| /// \brief Provides access to platforms and devices on the system.
 | |
| ///
 | |
| /// The system class contains a set of static functions which provide access to
 | |
| /// the OpenCL platforms and compute devices on the host system.
 | |
| ///
 | |
| /// The default_device() convenience method automatically selects and returns
 | |
| /// the "best" compute device for the system following a set of heuristics and
 | |
| /// environment variables. This simplifies setup of the OpenCL enviornment.
 | |
| ///
 | |
| /// \see platform, device, context
 | |
| class system
 | |
| {
 | |
| public:
 | |
|     /// Returns the default compute device for the system.
 | |
|     ///
 | |
|     /// The default device is selected based on a set of heuristics and can be
 | |
|     /// influenced using one of the following environment variables:
 | |
|     ///
 | |
|     /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE -
 | |
|     ///        name of the compute device (e.g. "GTX TITAN")
 | |
|     /// \li \c BOOST_COMPUTE_DEFAULT_DEVICE_TYPE
 | |
|     ///        type of the compute device (e.g. "GPU" or "CPU")
 | |
|     /// \li \c BOOST_COMPUTE_DEFAULT_PLATFORM -
 | |
|     ///        name of the platform (e.g. "NVIDIA CUDA")
 | |
|     /// \li \c BOOST_COMPUTE_DEFAULT_VENDOR -
 | |
|     ///        name of the device vendor (e.g. "NVIDIA")
 | |
|     ///
 | |
|     /// The default device is determined once on the first time this function
 | |
|     /// is called. Calling this function multiple times will always result in
 | |
|     /// the same device being returned.
 | |
|     ///
 | |
|     /// If no OpenCL device is found on the system, a no_device_found exception
 | |
|     /// is thrown.
 | |
|     ///
 | |
|     /// For example, to print the name of the default compute device on the
 | |
|     /// system:
 | |
|     /// \code
 | |
|     /// // get the default compute device
 | |
|     /// boost::compute::device device = boost::compute::system::default_device();
 | |
|     ///
 | |
|     /// // print the name of the device
 | |
|     /// std::cout << "default device: " << device.name() << std::endl;
 | |
|     /// \endcode
 | |
|     static device default_device()
 | |
|     {
 | |
|         static device default_device = find_default_device();
 | |
| 
 | |
|         return default_device;
 | |
|     }
 | |
| 
 | |
|     /// Returns the device with \p name.
 | |
|     ///
 | |
|     /// \throws no_device_found if no device with \p name is found.
 | |
|     static device find_device(const std::string &name)
 | |
|     {
 | |
|         const std::vector<device> devices = system::devices();
 | |
|         for(size_t i = 0; i < devices.size(); i++){
 | |
|             const device& device = devices[i];
 | |
| 
 | |
|             if(device.name() == name){
 | |
|                 return device;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         BOOST_THROW_EXCEPTION(no_device_found());
 | |
|     }
 | |
| 
 | |
|     /// Returns a vector containing all of the compute devices on
 | |
|     /// the system.
 | |
|     ///
 | |
|     /// For example, to print out the name of each OpenCL-capable device
 | |
|     /// available on the system:
 | |
|     /// \code
 | |
|     /// for(const auto &device : boost::compute::system::devices()){
 | |
|     ///     std::cout << device.name() << std::endl;
 | |
|     /// }
 | |
|     /// \endcode
 | |
|     static std::vector<device> devices()
 | |
|     {
 | |
|         std::vector<device> devices;
 | |
| 
 | |
|         const std::vector<platform> platforms = system::platforms();
 | |
|         for(size_t i = 0; i < platforms.size(); i++){
 | |
|             const std::vector<device> platform_devices = platforms[i].devices();
 | |
| 
 | |
|             devices.insert(
 | |
|                 devices.end(), platform_devices.begin(), platform_devices.end()
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         return devices;
 | |
|     }
 | |
| 
 | |
|     /// Returns the number of compute devices on the system.
 | |
|     static size_t device_count()
 | |
|     {
 | |
|         size_t count = 0;
 | |
| 
 | |
|         const std::vector<platform> platforms = system::platforms();
 | |
|         for(size_t i = 0; i < platforms.size(); i++){
 | |
|             count += platforms[i].device_count();
 | |
|         }
 | |
| 
 | |
|         return count;
 | |
|     }
 | |
| 
 | |
|     /// Returns the default context for the system.
 | |
|     ///
 | |
|     /// The default context is created for the default device on the system
 | |
|     /// (as returned by default_device()).
 | |
|     ///
 | |
|     /// The default context is created once on the first time this function is
 | |
|     /// called. Calling this function multiple times will always result in the
 | |
|     /// same context object being returned.
 | |
|     static context default_context()
 | |
|     {
 | |
|         static context default_context(default_device());
 | |
| 
 | |
|         return default_context;
 | |
|     }
 | |
| 
 | |
|     /// Returns the default command queue for the system.
 | |
|     static command_queue& default_queue()
 | |
|     {
 | |
|         static command_queue queue(default_context(), default_device());
 | |
| 
 | |
|         return queue;
 | |
|     }
 | |
| 
 | |
|     /// Blocks until all outstanding computations on the default
 | |
|     /// command queue are complete.
 | |
|     ///
 | |
|     /// This is equivalent to:
 | |
|     /// \code
 | |
|     /// system::default_queue().finish();
 | |
|     /// \endcode
 | |
|     static void finish()
 | |
|     {
 | |
|         default_queue().finish();
 | |
|     }
 | |
| 
 | |
|     /// Returns a vector containing each of the OpenCL platforms on the system.
 | |
|     ///
 | |
|     /// For example, to print out the name of each OpenCL platform present on
 | |
|     /// the system:
 | |
|     /// \code
 | |
|     /// for(const auto &platform : boost::compute::system::platforms()){
 | |
|     ///     std::cout << platform.name() << std::endl;
 | |
|     /// }
 | |
|     /// \endcode
 | |
|     static std::vector<platform> platforms()
 | |
|     {
 | |
|         cl_uint count = 0;
 | |
|         clGetPlatformIDs(0, 0, &count);
 | |
| 
 | |
|         std::vector<platform> platforms;
 | |
|         if(count > 0)
 | |
|         {
 | |
|             std::vector<cl_platform_id> platform_ids(count);
 | |
|             clGetPlatformIDs(count, &platform_ids[0], 0);
 | |
| 
 | |
|             for(size_t i = 0; i < platform_ids.size(); i++){
 | |
|                 platforms.push_back(platform(platform_ids[i]));
 | |
|             }
 | |
|         }
 | |
|         return platforms;
 | |
|     }
 | |
| 
 | |
|     /// Returns the number of compute platforms on the system.
 | |
|     static size_t platform_count()
 | |
|     {
 | |
|         cl_uint count = 0;
 | |
|         clGetPlatformIDs(0, 0, &count);
 | |
|         return static_cast<size_t>(count);
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     /// \internal_
 | |
|     static device find_default_device()
 | |
|     {
 | |
|         // get a list of all devices on the system
 | |
|         const std::vector<device> devices_ = devices();
 | |
|         if(devices_.empty()){
 | |
|             BOOST_THROW_EXCEPTION(no_device_found());
 | |
|         }
 | |
| 
 | |
|         // check for device from environment variable
 | |
|         const char *name     = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE");
 | |
|         const char *type     = detail::getenv("BOOST_COMPUTE_DEFAULT_DEVICE_TYPE");
 | |
|         const char *platform = detail::getenv("BOOST_COMPUTE_DEFAULT_PLATFORM");
 | |
|         const char *vendor   = detail::getenv("BOOST_COMPUTE_DEFAULT_VENDOR");
 | |
| 
 | |
|         if(name || type || platform || vendor){
 | |
|             for(size_t i = 0; i < devices_.size(); i++){
 | |
|                 const device& device = devices_[i];
 | |
|                 if (name && !matches(device.name(), name))
 | |
|                     continue;
 | |
| 
 | |
|                 if (type && matches(std::string("GPU"), type))
 | |
|                     if (!(device.type() & device::gpu))
 | |
|                         continue;
 | |
| 
 | |
|                 if (type && matches(std::string("CPU"), type))
 | |
|                     if (!(device.type() & device::cpu))
 | |
|                         continue;
 | |
| 
 | |
|                 if (platform && !matches(device.platform().name(), platform))
 | |
|                     continue;
 | |
| 
 | |
|                 if (vendor && !matches(device.vendor(), vendor))
 | |
|                     continue;
 | |
| 
 | |
|                 return device;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // find the first gpu device
 | |
|         for(size_t i = 0; i < devices_.size(); i++){
 | |
|             const device& device = devices_[i];
 | |
| 
 | |
|             if(device.type() & device::gpu){
 | |
|                 return device;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // find the first cpu device
 | |
|         for(size_t i = 0; i < devices_.size(); i++){
 | |
|             const device& device = devices_[i];
 | |
| 
 | |
|             if(device.type() & device::cpu){
 | |
|                 return device;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // return the first device found
 | |
|         return devices_[0];
 | |
|     }
 | |
| 
 | |
|     /// \internal_
 | |
|     static bool matches(const std::string &str, const std::string &pattern)
 | |
|     {
 | |
|         return str.find(pattern) != std::string::npos;
 | |
|     }
 | |
| };
 | |
| 
 | |
| } // end compute namespace
 | |
| } // end boost namespace
 | |
| 
 | |
| #endif // BOOST_COMPUTE_SYSTEM_HPP
 | 
