質問: 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
、内部ループを取り除くことです (ただし、これがどのように役立つかはわかりません)。