| 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, contextclass 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
 |