OpenCL提供与串行执行不同的值

OpenCL提供与串行执行不同的值,c,opencl,C,Opencl,我有一个问题让我对OpenCL感到愤怒。我已经将问题缩小到一段特定的代码中,这段代码给出了问题所在,我在下面引用它。问题是,当我用OpenCL和串行方式执行这段代码并比较结果时,它们并不相同。这里,内核的唯一参数是cells变量 在测试过程中,我尝试使用先前计算的特定值(例如局部密度)设置最后一个循环中的值。然后我得到的结果是正确的。据我所知,当在循环中使用u和d_eq数组进行计算时,问题在于它们。我必须提到,这些数组是double类型的,我已经添加了所需的pragma以启用双精度 这段代码中是

我有一个问题让我对OpenCL感到愤怒。我已经将问题缩小到一段特定的代码中,这段代码给出了问题所在,我在下面引用它。问题是,当我用OpenCL和串行方式执行这段代码并比较结果时,它们并不相同。这里,内核的唯一参数是cells变量

在测试过程中,我尝试使用先前计算的特定值(例如局部密度)设置最后一个循环中的值。然后我得到的结果是正确的。据我所知,当在循环中使用u和d_eq数组进行计算时,问题在于它们。我必须提到,这些数组是double类型的,我已经添加了所需的pragma以启用双精度

这段代码中是否需要同步或类似的东西,因为它是为OpenCL工作的

    local_density = 0.0;
    for(kk = 0; kk < 9; kk++)
    {
      local_density += tmp_cells[pos].speeds[kk];
    }

    u_x = (tmp_cells[pos].speeds[1] + tmp_cells[pos].speeds[5] +
           tmp_cells[pos].speeds[8] - ( tmp_cells[pos].speeds[3] +
            tmp_cells[pos].speeds[6] + tmp_cells[pos].speeds[7]))
          / local_density;
    u_y = (tmp_cells[pos].speeds[2] + tmp_cells[pos].speeds[5] +
           tmp_cells[pos].speeds[6] - ( tmp_cells[pos].speeds[4] +
            tmp_cells[pos].speeds[7] + tmp_cells[pos].speeds[8]))
          / local_density;
    u_sq = u_x * u_x + u_y * u_y;
    u[1] =   u_x      ;
    u[2] =         u_y;
    u[3] = - u_x      ;
    u[4] =       - u_y;
    u[5] =   u_x + u_y;
    u[6] = - u_x + u_y;
    u[7] = - u_x - u_y;
    u[8] =   u_x - u_y;
    t1 = 2.0 * c_sq;
    d_equ[0] = w0 * local_density * (1.0 - u_sq / t1);
    t3 = w1 * local_density;
    t2 = t1 * c_sq;
    t1 = u_sq / t1;
    d_equ[1] = t3 * (1.0 + u[1] / c_sq + (u[1] * u[1]) / t2 - t1);
    d_equ[2] = t3 * (1.0 + u[2] / c_sq + (u[2] * u[2]) / t2 - t1);
    d_equ[3] = t3 * (1.0 + u[3] / c_sq + (u[3] * u[3]) / t2 - t1);
    d_equ[4] = t3 * (1.0 + u[4] / c_sq + (u[4] * u[4]) / t2 - t1);
    t3 = w2 * local_density;
    d_equ[5] = t3 * (1.0 + u[5] / c_sq + (u[5] * u[5]) / t2 - t1);
    d_equ[6] = t3 * (1.0 + u[6] / c_sq + (u[6] * u[6]) / t2 - t1);
    d_equ[7] = t3 * (1.0 + u[7] / c_sq + (u[7] * u[7]) / t2 - t1);
    d_equ[8] = t3 * (1.0 + u[8] / c_sq + (u[8] * u[8]) / t2 - t1);

    for(kk = 0; kk < 9; kk++)
    {
      cells[pos].speeds[kk] = (tmp_cells[pos].speeds[kk] + params->omega *
           (d_equ[kk] - tmp_cells[pos].speeds[kk]));
    }

编辑 经过几次测试后,问题是当我试图为每个单元格[pos]设置值时。速度[kk]。如果我只改变其中一个速度的值,那么我得到的结果会更好(更正确的值)。如果我试图改变不止一个,那么结果真的很糟糕

问题是,为什么我不能在结构中更改多个值而不会出现问题


编辑 在尝试在几个循环中执行整个代码后,经过一定数量的步骤后,上述代码会导致分段错误。导致问题的原因当然是更新

for(kk = 0; kk < 9; kk++)
{
  cells[pos].speeds[kk] = (tmp_cells[pos].speeds[kk] + params->omega *
       (d_equ[kk] - tmp_cells[pos].speeds[kk]));
}
for(kk=0;kk<9;kk++)
{
单元格[pos]。速度[kk]=(tmp_单元格[pos]。速度[kk]+参数->ω*
(d_eq[kk]-tmp_单元[pos]。速度[kk]);
}
如果我把这个注释掉,那么就不会有分段错误


编辑
当我将cpu作为OpenCL的执行设备时,代码执行得很好,没有问题。为什么会发生这种情况?

“当我使用OpenCL和串行方式执行此代码并比较结果时,它们不一样”它们有多大不同?它们是否仅在最低有效数字上存在差异?或者是否存在大量差异,例如一台设备的所有零?请注意,GPU和CPU上的浮点精度不同。试着使用所有的32位整数,看看你得到了什么。它们有时甚至在第二个浮点和每次代码在循环中运行时都会有所不同,因为每次的值都是从以前的值演变而来的,过了一段时间,它们就会完全错误并导致分段错误。问题是,困扰我的不仅是值的差异,还有一个事实,即如果我只为其中一个设置值(不执行最后一个循环,而是只设置其中一个循环变量的值),那么该特定变量的预期值是正确的。只有当我试图改变不止一个的时候,他们才会变得一团糟。
for(kk = 0; kk < 9; kk++)
{
  cells[pos].speeds[kk] = (tmp_cells[pos].speeds[kk] + params->omega *
       (d_equ[kk] - tmp_cells[pos].speeds[kk]));
}