通过所有对的OpenCL快速迭代
我是OpenCL的新手,这让我很难思考所有GPU执行的后果。我试图写一个求和,所以我有2D点,需要计算作用在它们之间的“重力”。我对OpenCL内核的最佳想法如下:通过所有对的OpenCL快速迭代,opencl,gpu,Opencl,Gpu,我是OpenCL的新手,这让我很难思考所有GPU执行的后果。我试图写一个求和,所以我有2D点,需要计算作用在它们之间的“重力”。我对OpenCL内核的最佳想法如下: kernel void ker_fun(global const double* pts, uint pts_size, global double* fxs, global double* fys, double vertexRepulsion) { double x=pts[2*get_global_id(0)];
kernel void ker_fun(global const double* pts, uint pts_size, global double* fxs, global double* fys, double vertexRepulsion)
{
double x=pts[2*get_global_id(0)];
double y=pts[2*get_global_id(0)+1];
double fx=0;
double fy=0;
for (size_t i=get_global_id(0)+1; i<pts_size; ++i) {
double dx=x-pts[2*i]; // point[i] -> points[THIS]
double dy=y-pts[2*i+1];
double r2=pow(dx, 2)+pow(dy, 2);
r2=max(r2, 0.0001); // to prevent (r2==0) issue
double f=gravityConstant/r2;
double ratio=f/sqrt(r2);
dx*=ratio;
dy*=ratio;
fx+=dx;
fy+=dy;
atomic_add_double(&fxs[i], -dx);
atomic_add_double(&fys[i], -dy);
}
atomic_add_double(&fxs[get_global_id(0)], fx);
atomic_add_double(&fys[get_global_id(0)], fy);
kernelvoid keru_-fun(全局常数双*pts,uint pts_-size,全局双*fxs,全局双*fys,双顶点排斥)
{
双x=pts[2*获取全局id(0)];
双y=pts[2*获取全局id(0)+1];
双fx=0;
双fy=0;
对于(size\u ti=get\u global\u id(0)+1;i点[此]
双dy=y-pts[2*i+1];
双r2=功率(dx,2)+功率(dy,2);
r2=max(r2,0.0001);//防止(r2==0)问题
双f=重力恒温器/r2;
双倍比率=f/sqrt(r2);
dx*=比率;
dy*=比率;
fx+=dx;
fy+=dy;
原子加双(fxs[i],-dx);
原子加双(&fys[i],-dy);
}
原子添加双精度(&fxs[get\u global\u id(0)],fx);
原子添加双精度(&fys[get\u global\u id(0)],fy);
其中fxs
和fys
是X和X方向的力值(即我的结果),并且atomic\u add\u double
功能从该站点复制()
这个函数可以工作并计算所需的结果。但是它很慢。你能告诉我,如何用不同的更好的方法来做吗
谢谢你的时间和帮助是原子使它变慢了。也许你可以存储每个工作项的结果,然后再执行并行求和缩减步骤。@Dithermaster缓存如何。这不也是问题吗?我有一个算法,对每个点迭代,并将结果存储在私有内存中(无任何类型的同步/原子)。它甚至更慢。因此原子学很慢,但可能没那么糟糕。正如@Dithermaster所说,同步很有可能会减慢内核速度。但是,还有其他因素,如工作组大小和全局缓存管理,可能也会在您的问题中发挥作用。您能否为内核提供一个调用脚本,使用数组的值。