0

質問: CUDA で、ネストされた for ループのパフォーマンスを改善する一般的な方法はありますか?

背景: 2D 画像フィルター アルゴリズムの CUDA 実装に取り​​組んでいます。入力の各ピクセルに対して、出力の値は、(2*r+1) * (2*r+1)隣接するピクセルを調べることによって計算されます。はr画像ごとに一定ですが、フィルターの形状は各ピクセルの値に依存するため、真の畳み込み演算に変換したり、2 つの 1D 演算に分解したりすることはできません。

r入力の各ピクセルにスレッドが割り当てられるスキャッター アプローチ (これは、私が思いついたどのギャザー アプローチよりも高速です) に基づいて、コンパイル時にフィルター半径がわかっている場合のかなり効率的な実装があります。出力は、共有メモリに保持されるタイルに分割されます。アルゴリズムの中心にあるのは、各スレッドによって実行されるネストされた for ループです。

for(int i=-r; i<r+1; i++) {
    for(int j=-r; j<r+1; j++) {
        // Calculate and scatter value to output[offsetJ + j][offsetI + i]
    }
}

r動的に割り当てられた共有メモリを使用して、実行時に与えられたコードを一般化しました。生成された結果は依然として正しいですが、 の値に応じて、実行が 1.5 ~ 3 倍遅くなりますr。テストを通じて、スローダウンは上記の for ループの条件の実行時の決定によるものであると結論付けました。つまり、コンパイラはループをアンロールできません。

この特定のケースでパフォーマンスを改善する方法について提案がある場合、または同様の実装のヒントを知っている場合は、歓迎します。これまでの私の唯一のアイデアは、 の値ごとに異なるカーネルをコンパイルするかr、内部ループを取り除くことです (ただし、これがどのように役立つかはわかりません)。

4

1 に答える 1

0

コメントから収集したように、唯一のオプションは手動展開 (この場合はおそらく適用されません)、テンプレートの使用、およびランタイム コード生成のようです。この特定のケースでの最適なオプションはr、1 ~ 25 の範囲で、いくつかの異なるケース用に明示的なテンプレートを作成し、その間の値をゼロでパディングすることです。rのすべての値が等しく共通である場合、複雑さは の二次関数的に増加するためr、上限で範囲をより密にサンプリングすることが合理的と思われます。たとえば、r8、14、18、21、23、および 25 に等しいテンプレートを作成します。

于 2013-07-26T15:54:11.043 に答える