2012-03-31 9 views
1

このような問題が発生しています。基本的に、私はホスト上で割り当てられた2Dグリッドを持っている:特定のシステムサイズを超えた場合のOpenCLランダムカーネルの動作

のOpenCLデバイス上でそれを置くために、通常のOpenCLの手順をFolllowing
double* grid = (double*)malloc(sizeof(double)*(ny*nx) * 9); 

cl_mem cl_grid = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(double) * (ny*nx) * 9, grid, &error); 

エンキューと打ち上げ:では

clEnqueueNDRangeKernel(queue, foo, 1, NULL, &global_ws, &local_ws, 0, NULL, NULL); 

カーネル関数、単純演算はグリッドの第1列で実行されます。

__kernel void foo(__constant ocl_param* params, __global double* grid) 
{ 
    const int ii = get_global_id(0); 
    int jj; 
    jj=0; 

    if (ii < params->ny) { 
     grid[getIndexUsingMacro(ii,jj)] += params->someNumber; 
    } 
} 

最後に、バッファーとチェック値を読み戻します。

clEnqueueReadBuffer(queue, cl_grid, CL_TRUE, 0, sizeof(double) * 9 * nx * ny, checkGrid, 0, NULL, NULL); 

問題は、グリッドサイズ(すなわちNX * NY * 9)16384×9×8バイト= 1152キロバイトを超える場合である(*倍精度を用いているため8)。私はglobal_wsとlocal_ws(Iは1にそれらを設定するとエラーがまだスローされます)のために設定したものに関係なく、カーネルを起動していないとき

  • は、CPU上でのOpenCLを使用している場合、エラーCL_OUT_OF_RESOURCESがスローされます。 CPUは8GBのRAMと3MBのキャッシュを備えたIntel i5 2415mです。

  • GPU(NVIDIA TESLA M2050)でopenCLを使用しても、エラーは発生しません。しかし、バッファから値を読み戻すとき、グリッドはまったく変更されません。つまり、カーネル関数に送られる前の値とまったく同じ値を持つグリッドを返します。

nx = 30、ny = 546、nx * ny = 16380を設定すると、すべて正常に動作します。予想通りに結果が変更されたグリッドが返されました。しかし、ny = 547、nx * ny = 16410の場合、上記のようにCPUとGPUの両方で問題が発生します。問題は、もしnxとnyを入れ替えても同じです。したがって、nx = 547、ny = 30なら、それは起こります。皆さんはここで何が問題になるかもしれないかを提案できますか?これは、同期の問題のように見える

感謝

答えて

1

。同じindexの値を持つgrid[index] += valueは、いくつかの作業項目で同時に実行できます。この操作はアトミックではなく、これらの作業項目はすべてgrid[index]をロードし、それらの値を追加して戻します。これにより、処理が少しずつ失われる可能性があります。

これを解決するには、単一のワークグループ内にある場合はbarrierを使用してこれらの作業項目を同期させるか、それ以外の場合はさらにカーネルをエンキューします。

もう1つの可能性は、1つの作業項目だけがグリッドの特定の要素を変更できることです(通常は最善の解決策です)。

複数の作業項目がグリッドの共通サブセットで作業する必要がある場合は、ローカルメモリとローカルメモリバリアを使用すると便利です。

+0

1つのワークグループだけをエンキューしない限り、バリアを使用して安全に障壁を使用することはできません。 OpenCLの障壁は、ワークグループ内のすべてのワークアイテムに対して同期を提供しますが、ワークグループ間のアクセスは同期されません。 – sbabbi

+0

さて、それは私が意味することです: "彼らは単一の作業グループにいる"。 –

関連する問題