CUDA 2.0(NVIDIA 590)で大きな構造の配列を処理しようとしています。共有メモリを使用したいのですが。各スレッドが配列の要素全体を処理できるように、スレッドごとに最大共有メモリを割り当てようとして、CUDA占有計算機を試しました。ただし、(ブロックあたりの共有メモリ)/(ブロックあたりのスレッド)の最大値は、100%マルチプロセッサ負荷の計算機で確認できます。32バイトであり、単一の要素(桁違い)には不十分です。(ブロックあたりの共有メモリ)/(ブロックあたりのスレッド)の可能な最大値は32バイトですか?配列の一部をグローバルメモリに割り当てるか、負荷の少ないマルチプロセッサを使用するか、どちらの代替が望ましいかを判断することはできますか?それとも実験によってしか決定できないのでしょうか?私が見ることができるさらに別の選択肢は、いくつかのパスで配列を処理することですが、それは最後の手段のように見えます。
1 に答える
CUDAカーネルを設計するときに覚えておく必要のあるハードウェアの制限がたくさんあります。考慮する必要のある制約のいくつかを次に示します。
- 1つのブロックで実行できるスレッドの最大数
- ストリーミングマルチプロセッサに一度にロードできるブロックの最大数
- ストリーミングマルチプロセッサあたりの最大レジスタ数
- ストリーミングマルチプロセッサあたりの共有メモリの最大量
これらの制限のいずれかを最初にヒットすると、占有率を制限する制約になります(「100%マルチプロセッサ負荷」で参照している最大占有率ですか?)。占有の特定のしきい値に達すると、占有に注意を払うことはそれほど重要ではなくなります。たとえば、33%の占有率は、GPUの最大理論パフォーマンスの33%しか達成できないことを意味するものではありません。Vasily Volkovは、2010 GPU Technology Conferenceで素晴らしい講演を行いました。これは、占有率についてあまり心配せず、代わりにカーネルで明示的なキャッシュトリック(およびその他のもの)を使用してメモリトランザクションを最小限に抑えることを推奨しています。あなたはここで話を見ることができます:http://www.gputechconf.com/gtcnew/on-demand-GTC.php?sessionTopic=25&searchByKeyword=occupancy&submit3%select=+&sessionEvent3%sessionYear3%sessionFormat=#193
最高のパフォーマンスを提供するカーネル設計を使用していることを確認する唯一の実際の方法は、すべての可能性をテストすることです。また、実行するデバイスの種類ごとにこのパフォーマンステストをやり直す必要があります。これは、すべてのデバイスに何らかの制約があるためです。これは明らかに面倒な場合があります。特に、デザインパターンが異なると、カーネルが根本的に異なる場合はなおさらです。テンプレートエンジンを使用して、デバイスのハードウェア仕様に従って実行時に動的にカーネルを生成することで、これをある程度回避できますが、それでも少し面倒です。