有没有办法将 CUDA 数学函数自动包装在仿函数中,以便人们可以应用 thrust::transform
无需手动编写仿函数?类似于(我收集的)功能 std::function
提供?thrust::placeholders
似乎不喜欢数学函数。std::function
似乎不可用。
示例代码:
#include <thrust/transform.h>
#include <thrust/device_vector.h>
#include <iostream>
#include <functional>
#include <math.h>
struct myfunc{
__device__
double operator()(double x,double y){
return hypot(x,y);
}
};
int main(){
double x0[10] = {3.,0.,1.,2.,3.,4.,5.,6.,7.,8.};
double y0[10] = {4.,0.,1.,2.,3.,4.,5.,6.,7.,8.};
thrust::device_vector<double> x(x0,x0+10);
thrust::device_vector<double> y(y0,y0+10);
thrust::device_vector<double> r(10);
for (int i=0;i<10;i++) std::cout << x0[i] <<" "; std::cout<<std::endl;
for (int i=0;i<10;i++) std::cout << y0[i] <<" "; std::cout<<std::endl;
// this works:
thrust::transform(x.begin(),x.end(),y.begin(),r.begin(), myfunc());
// this doesn't compile:
using namespace thrust::placeholders;
thrust::transform(x.begin(),x.end(),y.begin(),r.begin(), hypot(_1,_2));
// nor does this:
thrust::transform(x.begin(),x.end(),y.begin(),r.begin(), std::function<double(double,double)>(hypot));
for (int i=0;i<10;i++) std::cout << r[i] <<" "; std::cout<<std::endl;
}
最佳答案
将我的评论转换为这个答案:
正如@JaredHoberock 已经说过的,没有自动的方法来实现你想要的。总是有一些语法/打字开销。
减少编写单独仿函数的这种开销的一种方法(就像您对 my_func
所做的那样)是使用 lambda。从 CUDA 7.5 开始,有一个 experimental device lambda feature这允许您执行以下操作:
auto h = []__device__(double x, double y){return hypot(x,y);};
thrust::transform(x.begin(),x.end(),y.begin(),r.begin(), h);
您需要添加以下 nvcc 编译器开关来编译它:
nvcc --expt-extended-lambda ...
另一种方法是使用以下
Wrapper
将函数转换为仿函数:template<typename Sig, Sig& S>
struct Wrapper;
template<typename R, typename... T, R(&function)(T...)>
struct Wrapper<R(T...), function>
{
__device__
R operator() (T&... a)
{
return function(a...);
}
};
然后你会像这样使用它:
thrust::transform(x.begin(),x.end(),y.begin(),r.begin(), Wrapper<double(double,double), hypot>());
关于lambda - CUDA 推力快捷数学函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32871874/