Using transformations with templates.

36 views
Skip to first unread message

david....@eigendynamics.com

unread,
May 25, 2017, 8:05:14 AM5/25/17
to boost-compute
Hi,

I want to apply a transformation using the compute::transform function to power each element of a vector. However I am having a hard time trying to use the functions of compute::math with more than one input, am I supposed to copy to the GPU the whole vector with both parameters a and b (a^b) or can I pass a float to that function.

The transform_sqrt.cpp from the examples.
std::vector<float> host_vector(10000);
std::generate(host_vector.begin(), host_vector.end(), rand);

// create a vector on the device
compute::vector<float> device_vector(host_vector.size(), context);

// transfer data from the host to the device
compute::copy(
host_vector.begin(), host_vector.end(), device_vector.begin(), queue
);

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

Did anybody manage to do something like:


compute::transform(
device_vector.begin(),
device_vector.end(),
device_vector.begin(),
compute::pow<<float><int>> (), where the int is the exponent
queue
);
And if so, how?



Jakub Szuppe

unread,
May 25, 2017, 8:48:34 AM5/25/17
to boost-compute
compute::vector<float> a_device_vector(host_vector.size(), context);
compute::vector<float> b_device_vector(host_vector.size(), context);
compute::vector<float> output_device_vector(host_vector.size(), context);

compute::transform(

 a_device_vector.begin(),
 a_device_vector.end(),
 b_device_vector.begin(),
 output_device_vector.begin(), // can also be a_device_vector.begin() or b_device_vector.begin()
 compute::pow<float>(), 
 queue
);

Should work just fine. If you look here https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/pow.html you see
that x and y in OpenCL pow() function have the same type. The same goes for Boost.Compute. However, if you want to
use pown(), you can use it like that:

compute::vector<compute::int_> int_b_device_vector(host_vector.size(), context);

compute::transform(
 a_device_vector.begin(),
 a_device_vector.end(),
 int_b_device_vector.begin(),
 output_device_vector.begin(), // can be a_device_vector.end() or b_device_vector.end()
 compute::pow<float>(), 
 queue
);

And it should also work. In https://github.com/boostorg/compute/issues/664 you can see
that Boost.Compute functors currently do not check types.

david....@eigendynamics.com

unread,
May 26, 2017, 6:30:15 AM5/26/17
to boost-compute

Hi Jakub,

It worked perfectly  now that I've looked back  I noticed that it's documented in the examples in vector_addition.cpp, but I wasn't able to wrap my head around the fact that you only pass int_b_device_vector.begin() without passing the end.

Thanks a lot.

david....@eigendynamics.com

unread,
May 26, 2017, 8:42:18 AM5/26/17
to boost-compute
Hello,

Just a quick follow up,

Today I tried to compute the distance of a vector of of float_4 type, with compute::transform. Is this even possible to do or do i have to process the whole thing in  a loop?

    compute::vector <compute::float4_>  vector_a = {(compute::float4_)(0.f, 0.f ,12.0f ,-1.0f)};
    compute::vector <compute::float4_> vector_b = {(compute::float4_)(1.f, 3.f ,-2.0f ,-1.0f)};

    compute::vector <compute::float_ >  vector_c;


    compute::transform(
            vector_a.begin(),
            vector_a.end(),
            vector_b.begin(),
            vector_c.begin(),
            compute::distance<compute::float4_>(), //If i don't put it like this I cannot compile
            queue
    );

//Printing info on the screen
    compute::copy(
        vector_c.begin(), vector_c.end() , vector_c.begin(), queue
    );
    for (size_t j=0 ; j < vector_c.size() ; j ++) {
      std::cout << vector_c[j] << '\n';
    }

    return 0;

Jakub Szuppe

unread,
May 26, 2017, 8:50:18 AM5/26/17
to david....@eigendynamics.com, boost-compute
Sorry, but I don't understand your question. I don't know what's wrong here. 

If you want to calculate distances between float4 values from vector_a and vector_b, that's the way to do it. 
However, you should allocate memory in vector_c, that is specify it's size in its constructor. 

--
You received this message because you are subscribed to the Google Groups "boost-compute" group.
To unsubscribe from this group and stop receiving emails from it, send an email to boost-compute+unsubscribe@googlegroups.com.
To post to this group, send email to boost-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/boost-compute/3d25e6ee-4ece-4d3f-b9bb-5c91f9052950%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

david....@eigendynamics.com

unread,
May 29, 2017, 4:14:48 AM5/29/17
to boost-compute, david....@eigendynamics.com
Oh sorry about that. Yes It should be allocated, however the program keeps throwing me an exception anyways, the exception is :

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::compute::opencl_error> >'
  what():  Invalid Memory Object
Aborted (core dumped)


It happens on the compute::transform() call
The code is: (formatted here)


#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/compute/algorithm/transform.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/functional/math.hpp>
#include <boost/compute/functional/geometry.hpp>
// #include </boost/compute/functional/geometry.hpp>
namespace compute = boost::compute;
 
 
int main()
{
    // get default device and setup context
    compute::device device = compute::system::default_device();
    compute::context context(device);
    compute::command_queue queue(context, device);
 
 
    compute::vector <compute::float4_>  vector_a = {(compute::float4_)(0.0f, 0.0f ,12.0f ,0.0f)};
    compute::vector <compute::float4_> vector_b = {(compute::float4_)(1.0f, 3.0f ,-2.0f ,0.0f)};
 
    compute::vector <compute::float_ >  vector_c = {(compute::float_)(1.0f)};
    std::cout << "/* message */" << '\n';
    compute::transform(
            vector_a.begin(),
            vector_a.end(),
            vector_b.begin(),
            vector_c.begin(),
            compute::distance<compute::float4_>(),
            queue
    );
 
  std::cout << "/* message2 */" << '\n';

Jakub Szuppe

unread,
May 29, 2017, 9:02:30 AM5/29/17
to boost-compute
You use different boost::compute::context (OpenCL context wrapper) to allocate device vectors (boost::compute::vector),
and different context to run algorithm.

For memory you use default context (compute::system::default_context()), and for running transform you use use command_queue 
from context you created. That's why you get that error. Try replacing your context and command_queue with default ones:

compute::context context = compute::system::default_context();
compute::command_queue& queue = compute::system::default_queue();

david....@eigendynamics.com

unread,
May 30, 2017, 5:31:51 AM5/30/17
to boost-compute
That was tricky,

The declaration of the vectors was incorrect as well I think. But it finally worked, thank you.

Reply all
Reply to author
Forward
0 new messages