0

OpenCL で私を怒らせる問題があります。問題を特定のコードに絞り込み、以下に引用します。問題は、このコードを OpenCL とシリアルで実行し、結果を比較すると、それらが同じではないことです。ここで、カーネルへの引数である唯一のものは、cells 変数です。

テスト中に、以前に計算された特定の値 (例: local_density) を使用して、最後のループの値を設定しようとしました。それから私が得た結果は正しかった。私が理解していることから、計算のループで使用される場合、問題は u および d_equ 配列にあります。これらの配列は double 型であり、倍精度を有効にするために必要なプラグマを追加したことに言及する必要があります。

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]));
    }

誰かが細胞のタイプを知りたい場合、それはタイプです

typedef struct {
  double speeds[NSPEEDS];
} t_speed;

編集

いくつかのテストの後、問題は、各セル [pos].speeds[kk] の値を設定しようとしたときです。速度の 1 つの値のみを変更すると、得られる結果はより良くなります (より正確な値)。複数を変更しようとすると、結果は非常に悪くなります。

問題は、構造体の複数の値を問題なく変更できないのはなぜですか?


編集

いくつかのループでコード全体を実行しようとした後、一定量のステップの後、上記のコードはセグメンテーション違反につながります。問題の原因はもちろん更新です。

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]));
}

これをコメントアウトすると、セグメンテーション違反は発生しません。


編集

CPU を OpenCL の実行デバイスとしてターゲットにすると、コードは問題なく正常に実行されます。なぜこれが起こるのですか?

4

0 に答える 0