__device__ 函数的地址(或__host__ __device__)不能在主机代码中使用,用于设备:
thrust::transform(X.begin(), X.end(), X.begin(), functor(&g));
^
You will not get the
__device__ function
address here
stackoverflow 上有很多问题讨论了通过内核调用传递的 CUDA 设备函数地址的用法。 This answer
几个可能感兴趣的链接。
解决此问题的一种可能方法是在设备代码中获取设备功能地址,并将其传递给主机,以供您描述的用法:
$ cat t1057.cu
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/copy.h>
#include <iostream>
struct functor{
functor(float (*g)(const float&)) : _g{g} {}
__host__ __device__ float operator()(const float& x) const {
return _g(x);
}
private:
float (*_g)(const float&);
};
__host__ __device__ float g(const float& x){return 3*x;}
__device__ float (*d_g)(const float&) = g;
int main(void){
float (*h_g)(const float&) = NULL;
cudaMemcpyFromSymbol(&h_g, d_g, sizeof(void *));
thrust::device_vector<float> X(4,1);
thrust::transform(X.begin(), X.end(), X.begin(), functor(h_g));
thrust::copy_n(X.begin(), X.size(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl;
}
$ nvcc -o t1057 t1057.cu -std=c++11
$ ./t1057
3,3,3,3,
$
另一种可能的方法,利用@m.s 的一贯聪明的工作。 here 使用模板:
$ cat t1057.cu
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/copy.h>
#include <iostream>
typedef float(*fptr_t)(const float&);
template <fptr_t F>
struct functor{
__host__ __device__ float operator()(const float& x) const {
return F(x);
}
};
__host__ __device__ float g(const float& x){return 3*x;}
int main(void){
thrust::device_vector<float> X(4,1);
thrust::transform(X.begin(), X.end(), X.begin(), functor<g>());
thrust::copy_n(X.begin(), X.size(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl;
}
$ nvcc -o t1057 t1057.cu -std=c++11
$ ./t1057
3,3,3,3,
$