3

特定の行列の最大値を計算する CUDA カーネルを作成しており、可能性を評価しています。私が見つけることができる最良の方法は次のとおりです。

すべてのスレッドが共有メモリに値を格納するように強制し、その後削減アルゴリズムを使用して最大値を決定します (長所: 最小の発散 短所: 共有メモリは 2.0 デバイスで 48Kb に制限されます)。

読み取り操作と書き込み操作の両方があるため、アトミック操作を使用できなかったため、同期スレッドによってスレッドを同期できませんでした。

他のアイデアが頭に浮かびますか?

4

7 に答える 7

6

また、CUDA 4.0 の一部であるか、ここから入手できる CUDA Thrust に付属するリダクション ルーチンを使用することもできます。

このライブラリは 2 人の nVidia エンジニアによって書かれており、手作業で大幅に最適化されたコードと比較して優れています。グリッド/ブロック サイズの自動調整も行われていると思います。

RAW デバイス ポインターをラップすることで、独自のカーネルと簡単にインターフェイスできます。

これは厳密には迅速な統合の観点からです。理論については、tkerwin の回答を参照してください。

于 2011-05-09T12:40:49.213 に答える
5

これは、CUDA でリダクションを実行する通常の方法です。

各ブロック内で、

1) 各スレッドの共有メモリに現在の縮小値を保持します。したがって、各スレッドはグローバルメモリから n (個人的には 16 から 32 の間が好きです) の値を読み取り、これらから削減された値を更新します。

2) ブロック内で縮小アルゴリズムを実行して、ブロックごとに 1 つの最終縮小値を取得します。

この方法では、(スレッド数) * sizeof (dataty) バイトより多くの共有メモリは必要ありません。

各ブロックは減らされた値であるため、最終値を取得するには 2 回目の減縮パスを実行する必要があります。

たとえば、ブロックごとに 256 のスレッドを起動し、スレッドごとに 16 の値を読み取る場合、ブロックごとに (256 * 16 = 4096) 要素を減らすことができます。

したがって、100 万個の要素がある場合、最初のパスで約 250 ブロックを起動する必要があり、2 回目で 1 ブロックだけ起動する必要があります。

この構成で要素数 > (4096)^2 の場合は、おそらく 3 番目のパスが必要になります。

グローバル メモリの読み取りが結合されるように注意する必要があります。グローバル メモリの書き込みを結合することはできませんが、これはパフォーマンス ヒットの 1 つです。

于 2011-05-07T23:04:37.167 に答える
4

NVIDIA には、リダクションを行う CUDA デモがあります。それに付随するホワイトペーパーがあり、設計の背後にある動機を説明しています。

于 2011-05-07T22:05:47.343 に答える
2

このドキュメントは、CUDA を使用した並列削減の基本を学ぶのに非常に役立ちます。ちょっと古いので、パフォーマンスをさらに向上させるには追加のトリックが必要です。

于 2012-08-20T17:37:29.190 に答える
0

K20 または Titan を使用している場合は、動的並列処理をお勧めします。シングル スレッド カーネルをランチングします。これは、#items ワーカー カーネル スレッドをランチングしてデータを生成し、次に #items/first-round-reduction-factor スレッドをランチングして最初のラウンド削減を行い、ランチングを続けます。結果が出るまで。

于 2013-05-02T20:58:36.240 に答える
0

このatomicAdd関数を使用することもできますが、上記のアプローチよりも効率が大幅に低下します。http://supercomputingblog.com/cuda/cuda-tutorial-4-atomic-operations/

于 2011-09-18T18:29:22.563 に答える