Search code examples
c++cudathrust

Thrust: Operator '*' is not supported


I have the following function for filling the vector t with steps from -time/2 to time/2 and stepsize dt:

#define THRUST_PREC thrust::complex<double>
__host__ void generate_time(thrust::device_vector<THRUST_PREC> *t, const double dt, const double time)
{
    THRUST_PREC start = -time / 2.0;
    THRUST_PREC step = dt;
    thrust::sequence((*t).begin(), (*t).end(), start, step);
}

When compiling, I get error : no operator "*" matches these operands. Why? Is there a way to fill the vector as I do, or should I fill it in the old way (aka loop)?

Edit: Full error: Error 1 error : no operator "*" matches these operands C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\thrust\system\detail\generic\sequence.inl 48 1 FFT_test


Solution

  • It looks like a bug of thrust::complex. The multiply operation between const thrust:complex<double> and signed long is not defined.

    /usr/local/cuda/bin/../targets/x86_64-linux/include/thrust/system/detail/generic/sequence.inl(48):
    error: no operator "*" matches these operands
                 operand types are: const thrust::complex<double> * signed long
               detected during:
               ....
    

    But strangely, you could use thrust::transform instead. The following code works.

    #define THRUST_PREC thrust::complex<double>
    __host__ void generate_time(thrust::device_vector<THRUST_PREC> *t, const double dt, const double time)
    {
      THRUST_PREC start = -time / 2.0;
      THRUST_PREC step = dt;
      thrust::transform(thrust::make_counting_iterator(0),
                        thrust::make_counting_iterator(0) + t->size(),
                        t->begin(),
                        start + step * _1);
    }
    

    In either way, the internal implementation uses an index (of the type signed long in thrust::sequence) to calculate the desired sequence with the expression

    start + step * index;
    

    The thing prevents thrust::sequence from working is that operator *(...) is not well overloaded.

    thrust::complex<double> a(1,1);
    double double_b = 4;
    float float_b = 4;
    int int_b = 4;
    long long_b = 4;
    
    a *= double_b; // ok
    a *= float_b;  // ok
    a *= int_b;    // ok
    a *= long_b;   // ok
    
    std::cout << a * double_b << std::endl; // ok
    std::cout << a * float_b << std::endl;  // error
    std::cout << a * int_b << std::endl;    // error
    std::cout << a * long_b << std::endl;   // error