clEnqueueNDRangeKernel不会在全局范围

时间:2017-06-23 21:35:29

标签: opencl

我有一个内核。

__kernel void unprimed_grid_int(__global double *ar_u,          
                                __global double *ap_u,          
                                __global double *az_u,          
                                __global const double *x_p,     
                                __global const double *y_p,     
                                __global const double *z_p,     
                                __global const double *jx_p,    
                                __global const double *jy_p,    
                                __global const double *jz_p,    
                                const uint nr,                
                                const uint nz,                  
                                const uint nv,         
                                const double rmin,      
                                const double dr,     
                                const double zmin,      
                                const double dz,     
                                const double dv,   
                                const double dvol, 
                                const uint p_size, 
                                const uint offset) { 

    const size_t i = get_global_id(0);

    const size_t ri = (i + offset)%nr;
    const size_t zi = ((i + offset)/nr)%nz;
    const size_t vi = ((i + offset)/(nr*nz))%nv;

    const double r = ri*dr + rmin;
    const double z = zi*dz + zmin;
    const double v = vi*dv;

    const double x = r*cos(v);
    const double y = r*sin(v);

    double ax = 0.0;
    double ay = 0.0;
    double az = 0.0;

    for (uint j = 0; j < p_size; j++) {
        const double dx = x_p[j] - x;
        const double dy = y_p[j] - y;
        const double dz = z_p[j] - z;

        const double rp = sqrt(dx*dx + dy*dy + dz*dz);

        ax += jx_p[j]/rp;
        ay += jy_p[j]/rp;
        az += jz_p[j]/rp;
    }

    ax *= dvol;
    ay *= dvol;
    az *= dvol;

    ar_u[i] += x/r*ax + y/r*ay;
    ap_u[i] += -y/r*ax + x/r*ay;                               
    az_u[i] += az;                                              
}

我来自

    const size_t offset = 0;
    clEnqueueNDRangeKernel(device->queue, device->kernels["int"], 1, &offset, &device->u_chunk, NULL, static_cast<cl_uint>(wait.size()), wait.data(), &event);

全局工作大小(device->u_chunk)为734208.但是,在我的GPU上运行时,内核只运行在前2560个工作项上。我通过打印get_global_size(0)的值检查了内核中的全局工作大小。如果我添加一个print语句来检查get_global_id(0)的哪些项,它会在整个范围内运行。

什么会导致内核无法在整个范围内运行?

更新

要添加一个添加例子的示例,这里是代码输出的图表。 Plot of the ap_u buffer 正如您所看到的,内核并未在整个范围内运行。为了进一步证明这一点,我运行了其中一个答案建议的测试用例。我修改了我的内核以添加一个额外的参数。

__kernel void unprimed_grid_int(..., __global uint *test) {
   ...
   if (get_global_id(0) == 5) { //  Reran with 5 changed to 700000
      test[0] == 10;
   }
}

对于输出看起来截止的下面的全局id值(2560),我读回正确的值10.对于高于截止值的全局id值,我得到的返回值不正确。

2 个答案:

答案 0 :(得分:2)

我认为,它实际上会遍历所有项目,但打印所有值都无法正常工作,因为有很多线程。

为了确保它有效,您还可以添加一个整数变量作为内核的参数,并执行以下操作:

{{1}}

然后,在执行内核之后,如果处理了所有项目,它应该是10或你使用的任何数字。

答案 1 :(得分:0)

我弄清楚为什么我的内核不能在全球范围内运行。问题源于内核中的for循环。 p_size大约为700000次迭代。这导致内核需要很长时间才能执行。由于我的GPU已连接到显示器the kernel is timing out,因此UI doesn't lock up