123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- //---------------------------------------------------------------------------//
- // 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")
- /// \li \c BOOST_COMPUTE_DEFAULT_ENFORCE -
- /// If this is set to "1", then throw a no_device_found() exception
- /// if any of the above environment variables is set, but a matching
- /// device was not found.
- ///
- /// 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");
- const char *enforce = detail::getenv("BOOST_COMPUTE_DEFAULT_ENFORCE");
- 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;
- }
- if(enforce && enforce[0] == '1')
- BOOST_THROW_EXCEPTION(no_device_found());
- }
- // 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
|