1

各ワークグループがローカル メモリに結果のベクトルを生成する OpenCL カーネルがあります。次に、後でホストに取得できるように、これらすべての結果をグローバル メモリに合計する必要があります。
これをテストするために、次のカーネル コードを作成しました。

//1st thread in each workgroup initializes local buffer
if(get_local_id(0) == 0){
    for(i=0; i<HYD_DIM; i++){
        pressure_Local[i] = (float2){1.0f, 0.0f};
    }
}

//wait for all workgroups to finish accessing any memory
barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);

/// sum all the results into global storage
for(i=0; i<get_num_groups(0); i++){

    //1st thread in each workgroup writes the group's local buffer to global memory
    if(i == get_group_id(0) && get_local_id(0) == 0){
        for(j=0; j<HYD_DIM; j++){
            pressure_Global[j] += pressure_Local[j];
            // barrier(CLK_GLOBAL_MEM_FENCE);
        }
    }

    //flush global memory buffers:
    barrier(CLK_GLOBAL_MEM_FENCE);
}

本質的に、グローバル メモリ内のベクトルのすべての要素がワークグループの数 (私の場合は 128) と等しいと予想していました。実際には、それらは通常 60 ~ 70 の間で変化し、結果は実行ごとに変化します。
誰かが私が欠けているもの、またはこれを正しく行う方法を教えてもらえますか?

4

1 に答える 1

2

opencl を使用して異なるワーク グループ間で同期することはできません。CLK_GLOBAL_MEM_FENCE はそのようには機能しません。これは、メモリ操作 (ワーク グループによってアクセスされる) の順序が維持されることを保証するだけです。OCL 1.2 仕様のセクション「6.12.8 同期関数」を参照してください。

ワークグループごとに異なるグローバルメモリのブロックを使用することで、問題を解決できます。グローバルにデータを書き込むと、カーネルが完成します。次に、データを単一のブロックに減らしたい場合は、別のカーネルを作成してグローバルからデータを読み取り、それを結果の他のブロックとマージできます。マージのレイヤーはいくつでも実行できますが、最終的なマージは 1 つの作業グループで行う必要があります。

gpu/opencl リダクション アルゴリズムを検索します。ここから始めましょう。ケーススタディ: 単純還元

于 2012-09-21T17:42:38.503 に答える