通过所有对的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)];

我是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)];
    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所说,同步很有可能会减慢内核速度。但是,还有其他因素,如工作组大小和全局缓存管理,可能也会在您的问题中发挥作用。您能否为内核提供一个调用脚本,使用数组的值。