The hello world example gives a simple application that prints the name of the default GPU compute device on the system.
Compute devices are represented with the device
class.
#include <iostream> #include <boost/compute.hpp> int main() { // get the default device boost::compute::device device = boost::compute::system::default_device(); // print the device's name std::cout << "hello from " << device.name() << std::endl; return 0; }
Before any computation occurs, data must be transferred from the host to
the compute device. The generic copy()
function provides a simple interface for transfering data and the generic
vector<T> class
provides a container for storing data on a compute device.
The following example shows how to transfer data from an array on the host
to a vector<T>
on the device and then back to a separate std::vector<T>
on the host. At the end of the example both host_array
and host_vector contain the
same values which were copied through the memory on the compute device.
#include <vector> #include <boost/compute.hpp> int main() { // create data array on host int host_data[] = { 1, 3, 5, 7, 9 }; // create vector on device boost::compute::vector<int> device_vector(5); // copy from host to device boost::compute::copy(host_data, host_data + 5, device_vector.begin()); // create vector on host std::vector<int> host_vector(5); // copy data back to host boost::compute::copy(device_vector.begin(), device_vector.end(), host_vector.begin()); return 0; }
The following example shows how to calculate the square-root of a vector
of floats on a compute device
using the transform()
function.
#include <vector> #include <algorithm> #include <boost/compute.hpp> int main() { // generate random data on the host std::vector<float> host_vector(10000); std::generate(host_vector.begin(), host_vector.end(), rand); // create a vector on the device and transfer data from the host boost::compute::vector<float> device_vector = host_vector; // calculate sqrt of each element in-place boost::compute::transform(device_vector.begin(), device_vector.end(), device_vector.begin(), boost::compute::sqrt<float>()); // copy values back to the host boost::compute::copy(device_vector.begin(), device_vector.end(), host_vector.begin()); return 0; }
In addition to the built-in scalar types (e.g. int
and float), OpenCL also provides
vector data types (e.g. int2
and vector4). These can be
used with the Boost Compute library on both the host and device.
Boost.Compute provides typedefs for these types which take the form: boost::compute::scalarN_ where scalar
is a scalar data type (e.g. int,
float, char)
and N is the size of the
vector. Supported vector sizes are: 2, 4, 8, and 16.
The following example shows how to transfer a set of 3D points stored as
an array of floats on the host
the device and then calculate the sum of the point coordinates using the
accumulate()
function. The sum is transferred to the host and the centroid computed by
dividing by the total number of points.
Note that even though the points are in 3D, they are stored as float4 due to OpenCL's alignment requirements.
#include <iostream> #include <boost/compute.hpp> // the point centroid example calculates and displays the // centroid of a set of 3D points stored as float4's int main() { using boost::compute::float4_; // point coordinates float points[] = { 1.0f, 2.0f, 3.0f, 0.0f, -2.0f, -3.0f, 4.0f, 0.0f, 1.0f, -2.0f, 2.5f, 0.0f, -7.0f, -3.0f, -2.0f, 0.0f, 3.0f, 4.0f, -5.0f, 0.0f }; // create vector for five points boost::compute::vector<float4_> vector(5); // copy point data to the device boost::compute::copy( reinterpret_cast<float4_ *>(points), reinterpret_cast<float4_ *>(points) + 5, vector.begin() ); // calculate sum float4_ sum = boost::compute::accumulate(vector.begin(), vector.end(), float4_(0, 0, 0, 0)); // calculate centroid float4_ centroid; for(size_t i = 0; i < 3; i++){ centroid[i] = sum[i] / 5.0f; } // print centroid std::cout << "centroid: " << centroid << std::endl; }