使用thrust::transform对thrust::complex类型进行操作

3

我尝试使用thrust::transform对类型为thrust:complex<float>的向量进行操作,但没有成功。以下示例在编译过程中出现了多页错误。

#include <cuda.h>
#include <cuda_runtime.h>
#include <cufft.h>

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/transform.h>
#include <thrust/complex.h>

int main(int argc, char *argv[]) {

  thrust::device_vector< thrust::complex<float> > d_vec1(4);
  thrust::device_vector<float> d_vec2(4);

  thrust::fill(d_vec1.begin(), d_vec1.end(), thrust::complex<float>(1,1));

  thrust::transform(d_vec1.begin(), d_vec1.end(), d_vec2.begin(), thrust::abs< thrust::complex<float> >() );
}

我正在使用CUDA 8.0在Ubuntu Xenial上,并使用clang 3.8.0-2ubuntu4进行编译,命令为nvcc --std=c++11 main.cpp -o main

主要错误如下:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:17:105: error: no matching function for call to ‘abs()’
 gin(), d_vec1.end(), d_vec2.begin(), thrust::abs< thrust::complex<float> >() );

并且

/usr/local/cuda-8.0/bin/../targets/x86_64-linux/include/thrust/detail/complex/arithmetic.h:143:20: note:   template argument deduction/substitution failed:
main.cpp:17:105: note:   candidate expects 1 argument, 0 provided
 gin(), d_vec1.end(), d_vec2.begin(), thrust::abs< thrust::complex<float> >() );
                                                                            ^

处理实数没有问题,但是处理复数就不行了。我认为我可能忽略了类型错误,但是在使用Thrust和模板时,我还处于学习曲线的陡峭部分。

1个回答

4
错误信息非常详细: thrust::abs<thrust::complex<...>>是一个函数,它希望只有一个参数,参见thrust/detail/complex/arithmetic.h#L143:
template <typename ValueType>
  __host__ __device__
  inline ValueType abs(const complex<ValueType>& z){
  return hypot(z.real(),z.imag());
}

对于您的用例,您需要通过函数对象来包装该函数:

struct complex_abs_functor
{
    template <typename ValueType>
    __host__ __device__
    ValueType operator()(const thrust::complex<ValueType>& z)
    {
        return thrust::abs(z);
    }
};

最后,将该函数应用于此处:
thrust::transform(d_vec1.begin(),
                  d_vec1.end(),
                  d_vec2.begin(),
                  complex_abs_functor());

这个方法很有效,但为什么thrust::negate<thrust::complex<float>>()可以直接在thrust::transform()中调用,而thrust::abs()需要在一个函数对象中进行封装呢?还有关于只期望一个参数的抱怨——thrust::transform()不是在设置对输入向量执行并行操作,并将结果写入输出向量吗? - Andreas Yankopolus
2
@AndreasYankopolus negate 已经是一个函数对象,因此不需要包装。你所做的是在thrust::transform中调用了没有参数的thrust::abs(),但它要求你提供一个函数对象(=函数对象,一个提供operator()的类/结构体的实例)。 - m.s.
现在看了thrust/functional.h和thrust/complex.h中的定义,现在明白了。 - Andreas Yankopolus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接