PrevUpHomeNext

Tutorial

Hello World
Transferring Data
Transforming Data
Vector Data Types

The hello world example gives a simple application that prints the name of the default compute device on the system.

Compute devices are represented with the device class.

#include <iostream>

#include <boost/compute/device.hpp>
#include <boost/compute/system.hpp>

namespace compute = boost::compute;

int main()
{
    // get the default device
    compute::device device = 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/algorithm/copy.hpp>
#include <boost/compute/container/vector.hpp>

namespace compute = boost::compute;

int main()
{
    // create data array on host
    int host_data[] = { 1, 3, 5, 7, 9 };

    // create vector on device
    compute::vector<int> device_vector(5);

    // copy from host to device
    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
    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/algorithm/transform.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/functional/math.hpp>

namespace compute = boost::compute;

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
    compute::vector<float> device_vector = host_vector;

    // calculate sqrt of each element in-place
    compute::transform(device_vector.begin(),
                       device_vector.end(),
                       device_vector.begin(),
                       compute::sqrt<float>());

    // copy values back to the host
    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/algorithm/copy.hpp>
#include <boost/compute/algorithm/accumulate.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/types/builtin.hpp>

namespace compute = boost::compute;

// the point centroid example calculates and displays the
// centroid of a set of 3D points stored as float4's
int main()
{
    using 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
    compute::vector<float4_> vector(5);

    // copy point data to the device
    compute::copy(
        reinterpret_cast<float4_ *>(points),
        reinterpret_cast<float4_ *>(points) + 5,
        vector.begin()
    );

    // calculate sum
    float4_ sum = 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;
}


PrevUpHomeNext