Shayan RC
Shayan RC

Reputation: 3322

Multiply device vector by constant

I am using thrust for a project, and it seem to be missing some basic functionality :-

In c++, the easiest way to multiply a vector by a constant is using std::transform and std::bind1st like so:

std::transform(vec.begin(), vec.end(), vec.begin(),
           std::bind1st(std::multiplies<double>(),myConst)); 

But apparently bind1st and bind2nd does not work with thrust.

So, is there an easy way to multiply a vector by a constant in thrust?

PS: Currently I am using my own functor to do the multiplication like so:

thrust::for_each(vec.begin(), vec.end(), multiplyByConstant<double>(myConst))

where

    template< typename T >
    struct multiplyByConstant
    {
    const T constant;

    multiplyByConstant(T _constant) : constant(_constant) {}

     __host__ __device__
     void operator()( T& VecElem) const 
      {
        VecElem=VecElem*constant;
      }
    };

But writing a functor to do a simple multiplication seems like overkill. There surely must be an easier way.

Upvotes: 4

Views: 3667

Answers (2)

Grayscale
Grayscale

Reputation: 1532

One simple way of accomplishing this is to use Thrust's fancy iterators, which often allow you to avoid defining (as many) functors. Instead of using std::bind1st to achieve a unary function from a binary function (and instead of using a lambda expression), you can use the binary function in conjunction with a fancy iterator:

#include <thrust/transform.h>
#include <thrust/iterator/constant_iterator.h>
#include <thrust/functional.h>
...
thrust::transform(vec.begin(),
                  vec.end(), 
                  thrust::make_constant_iterator(myConst),
                  vec.begin(),
                  thrust::multiplies<int>());

The documentation for fancy iterators can be found here.

Upvotes: 5

talonmies
talonmies

Reputation: 72339

Thrust can be made to work with adaptors, but std::bind1st, std::bind2nd, std:bind can't be used. You will need to write your own __device__ adaptor function instead (see here for a little more information).

However, thrust 1.7 (should be available in CUDA 5.5 and newer) supports lambda expressions, so your example could be written as something like:

#include <thrust/functional.h>
#include <thrust/transform.h>

using namespace thrust::placeholders;
thrust::transform(vec.begin(), vec.end(), vec.begin(), myConst * _1); 

{disclaimer, written in browser, not tested, use at own risk}

If you are using an older CUDA release, then you are stuck with defining a functor.

Upvotes: 8

Related Questions