0

OpenCLで配列の最大値を見つけるという単純なタスクに問題があります。

__kernel void ndft(/* lots of stuff*/)
{
    size_t thread_id = get_global_id(0); // thread_id = [0 .. spectrum_size[

    /* MATH MAGIC */

    // Now I have    float spectrum_abs[spectrum_size]    and
    // I want the maximum as well as the index holding the maximum

    barrier();
    // this is the old, sequential code:
    if (*current_max_value < spectrum_abs[i])
    {
        *current_max_value = spectrum_abs[i];
        *current_max_freq = i;
    }
}

これで、シングルコアシステムで行うのと同じようにすべてを追加if (thread_id == 0)してループすることができますが、パフォーマンス重要な問題であるため(そうでない場合は、GPUでスペクトル計算を行わない)、それを行うためのより高速な方法があります?

上記のカーネルの最後でCPUに戻ることはオプションではありません。これは、カーネルがその後も実際に続行するためです。

4

1 に答える 1

2

並列削減を作成する必要があります。「大きな」配列を小さな断片(単一のワークグループが効果的に処理できるサイズ)に分割し、それぞれの最小-最大を計算します。

最小/最大値のセットが1つだけになるまで、これを繰り返し実行します(ホストコードとデバイスコードの両方が含まれます)。

現在の作業分散がカーネルのこの部分で機能しない限り、これを行う別のカーネルを作成する必要がある場合があることに注意してください(上記の私の質問を参照してください)。

現在の作業分散が適切である場合の代替手段は、各ワークグループ内の最小最大値を見つけて、それをグローバルメモリ(インデックス= local_id)のバッファに書き込むことです。バリア()の後、thread_id == 0で実行されているカーネルを、削減された結果全体でループさせ、その中で最大値を見つけます。これは最適なソリューションではありませんが、現在のカーネル内に適合するソリューションである可能性があります。

于 2012-05-03T21:05:48.500 に答える