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
							 |