我目前正在学习并行编程,并决定使用OpenCL编写一个简单的N体模拟。在尝试编程内核时,我遇到了死胡同:
__kernel void nbody_kernel (__global double* x_in, __global double* y_in, __global double* z_in,
__global double* x_out, __global double* y_out, __global double* z_out,
__global double* v_x, __global double* v_y, __global double* v_z,
__global double* m, int n) {
int id = get_group_id(0)*get_local_size(0)+get_local_id(0);
if (id < n) {
double dx, dy, dz;
double invr, force;
double ax, ay, az;
ax = ay = az = 0;
for (int j = 0; j < n; ++j) {
dx = x_in[j] - x_in[id];
dy = y_in[j] - y_in[id];
dz = z_in[j] - z_in[id];
invr = 1.0 / sqrt(dx*dx + dy*dy + dz*dz + eps);
force = kappa*m[j]*invr*invr*invr;
ax += force*dx;
ay += force*dy;
az += force*dz;
}
x_out[id] = x_in[id] + v_x[id]*dt + 0.5*ax*dt*dt;
y_out[id] = y_in[id] + v_y[id]*dt + 0.5*ay*dt*dt;
z_out[id] = z_in[id] + v_z[id]*dt + 0.5*az*dt*dt;
v_x[id] += ax*dt;
v_y[id] += ay*dt;
v_z[id] += az*dt;
}
}
运行上面的代码后,x_out / y_out / z_out值似乎是NaN(至少printf似乎这么认为)。
我已经将问题诊断为for循环:如果我使用常量(例如2),则内核按预期运行。使用变量(__constant或参数)时,似乎只会出现问题。
我究竟做错了什么?
编辑:哦,如果它很重要:我正在运行OpenCL 1.1。
编辑2:我已经检查过“n”参数是否正确传递。
编辑3:计算中使用的常量在.cl文件中定义和初始化,如下所示:
__constant double kappa = 1;
__constant double eps = 0.0001;
__constant double dt = 0.1;
我正在创建和传递数据缓冲区,如下所示:
d_x0 = clCreateBuffer(context, CL_MEM_READ_WRITE, num * sizeof(double), NULL, &status);
clEnqueueWriteBuffer(command_queue, d_x0, CL_TRUE, 0, num * sizeof(double), x_in, 0, NULL, NULL);
clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_x0);
至于n,我正在使用:
clSetKernelArg(kernel, 10, sizeof(cl_int), &num);
编辑4:我玩过,如果我将加速度定义为ax = force*dx;
,它似乎正常工作。在程序到达ax += force*dx;
之前,ax / ay / az未设置为0会出现问题吗?