2

画像キューブ (450x450x1500) である大きなデータセットに取り組んでいます。個々のデータ要素で動作するカーネルがあります。各データ要素は、6 つの中間結果 (フロート) を生成します。私のブロックは 1024 スレッドで構成されています。6 つの中間結果は、各スレッド (6 つの float 配列) によって共有メモリに格納されます。ただし、中間結果をそれぞれ加算して合計 (6 つの合計値) を生成する必要があります。これらの 6 つの float 配列をグローバル メモリに保存し、ホスト コードから推力または他のライブラリからリダクションを実行するのに十分なグローバル メモリがありません。

共有メモリ内の配列のカーネル関数内から呼び出すことができるリダクション ルーチンはありますか?

この問題を解決する最善の方法は何ですか? 私は CUDA プログラミングの初心者であり、提案を歓迎します。

4

4 に答える 4

2

これはありそうにないようです:

これらの 6 つの float 配列をグローバル メモリに保存し、ホスト コードから推力または他のライブラリからリダクションを実行するのに十分なグローバル メモリがありません。

データを共有メモリに保存するのに十分なスペースがあるのに、グローバル メモリには保存できないとは思えません。

とにかく、CUBは、スレッドブロック内から呼び出すことができ、共有メモリに格納されたデータを操作できるリダクション ルーチンを提供します。

または、独自の合計削減コードを作成することもできます。それはそれほど難しいことではありません.SOについては、this oneなど、多くの質問があります。

または、 cuda サンプル コードを適合させることもできます。

于 2013-09-17T21:54:59.877 に答える
1

アップデート

皆さんのコメントを見て、1回や数回のリダクションではなく、450x450x6回のリダクションを行う必要があることを理解しました。

この場合、より簡単な解決策があります。

1500-D ベクトルごとに比較的複雑な並列リダクションを実装する必要はありません。リダクションする 450x450x6 ベクトルが既にあるので、従来のシリアル リダクション方法を使用して、これらすべてのベクトルを並列にリダクションできます。

16x16 スレッドのブロックを使用して画像の特定の領域を処理し、29x29 ブロックのグリッドを使用して 450x450 画像全体をカバーできます。

各スレッドで、1500 フレームを反復処理できます。各反復では、最初に 6 つの中間結果を計算してから、それらを合計に追加できます。すべての反復が終了したら、6 つの合計をグローバル メモリに書き込むことができます。

これでカーネルの設計は終了です。また、共有メモリは必要ありません。

パフォーマンスが非常に優れていることがわかります。これはメモリに依存する操作であるため、単純にすべてのイメージ キューブ データに 1 回アクセスするよりもそれほど長くはかかりません。

キューブ全体に十分なグローバル メモリがない場合は、[1500][225][225] の 4 つのサブキューブに分割し、各サブキューブでカーネル ルーチンを呼び出すことができます。変更する必要があるのは、グリッド サイズだけです。

于 2013-09-18T02:40:06.440 に答える
0

私がそれを正しく理解していれば、各スレッドは「のみ」6のフロートを合計する必要があります。

パフォーマンスが向上するという意味で、一般的に並列削減によってそれを行う価値があるかどうかはわかりません。

ケプラーをターゲットにしている場合、中間結果が何らかの方法でストリーミング マルチプロセッサのレジスタに適合するようにブロック サイズを適切に設定すると、シャッフル操作を使用できます。

また、Robert Crovella が指摘したように、グローバル メモリの量は共有メモリの量よりも確実に大きいため、中間結果を格納する可能性についてのあなたの発言は奇妙に思えます。

于 2013-09-18T11:23:12.253 に答える
0

CUDA での並列削減を徹底的に説明しているthisをご覧ください。

于 2013-09-17T23:41:34.767 に答える