summaryrefslogtreecommitdiff
path: root/boost/compute/system.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/compute/system.hpp')
-rw-r--r--boost/compute/system.hpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/boost/compute/system.hpp b/boost/compute/system.hpp
new file mode 100644
index 0000000000..f205fece7d
--- /dev/null
+++ b/boost/compute/system.hpp
@@ -0,0 +1,278 @@
+//---------------------------------------------------------------------------//
+// 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<cl_platform_id> platform_ids(count);
+ clGetPlatformIDs(count, &platform_ids[0], 0);
+
+ std::vector<platform> platforms;
+ 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