web-dev-qa-db-ja.com

OpenCLでローカルメモリを使用するにはどうすればよいですか?

私は最近OpenCLで遊んでいますが、グローバルメモリのみを使用するシンプルなカーネルを書くことができます。ここで、ローカルメモリの使用を開始したいのですが、get_local_size()およびget_local_id()を使用して一度に1つの「チャンク」の出力を計算する方法がわかりません。

たとえば、AppleのOpenCL Hello Worldサンプルカーネルをローカルメモリを使用するものに変換したいとします。どうしますか?元のカーネルソースは次のとおりです。

__kernel square(
    __global float *input,
    __global float *output,
    const unsigned int count)
{
    int i = get_global_id(0);
    if (i < count)
        output[i] = input[i] * input[i];
}

この例を簡単にローカルメモリの使用方法を示すものに変換できない場合は、他の簡単な例でも実行できます。

41
splicer

NVIDIAまたはAMD SDKのサンプルをご覧ください。正しい方向を示しているはずです。行列転置は、たとえばローカルメモリを使用します。

スクエアリングカーネルを使用すると、中間バッファーにデータをステージングできます。追加パラメーターを渡すことを忘れないでください。

__kernel square(
    __global float *input,
    __global float *output,
    __local float *temp,
    const unsigned int count)
{
    int gtid = get_global_id(0);
    int ltid = get_local_id(0);
    if (gtid < count)
    {
        temp[ltid] = input[gtid];
        // if the threads were reading data from other threads, then we would
        // want a barrier here to ensure the write completes before the read
        output[gtid] =  temp[ltid] * temp[ltid];
    }
}
31
Tom

ローカルメモリのサイズが一定の場合、これを行う別の可能性があります。カーネルパラメーターリストでポインターを使用せずに、ローカルバッファーを__localと宣言するだけでカーネル内で宣言できます。

__local float localBuffer[1024];

これにより、clSetKernelArg呼び出しが少なくなるため、コードが削除されます。

27

OpenCLでは、ローカルメモリは、ワークグループ内のすべてのワークアイテム間でデータを共有するためのものです。また、通常、ローカルメモリデータを使用する前にバリア呼び出しを行う必要があります(たとえば、1つの作業項目が他の作業項目によって書き込まれたローカルメモリデータを読み取りたい場合)。障壁はハードウェアに高価です。データの読み取り/書き込みを繰り返すには、ローカルメモリを使用する必要があることに注意してください。銀行の紛争はできる限り避けるべきです。

ローカルメモリに注意しないと、グローバルメモリを使用するよりもパフォーマンスが低下する場合があります。

5
Hunter Wang