19

cuda を使用した NVIDIA GPU アーキテクチャのスレッドを理解するのに問題があります。

誰でもこれらの情報を明確にすることができます: 8800 gpu には、それぞれ 8 個の SP を持つ 16 個の SM があります。128 個の SP があります。

スタンフォードのビデオ プレゼンテーションを見ていましたが、すべての SP が 96 スレッドを同時に実行できるとのことでした。これは、(SP) が 96/32=3 のワープを同時に実行できることを意味しますか?

さらに、すべての SP は 96 のスレッドを実行でき、すべての SM に 8 つの SP があるためです。これは、すべての SM が 96*8=768 スレッドを同時に実行できるということですか?? しかし、すべての SM が一度に 1 つのブロックを実行でき、ブロック内のスレッドの最大数が 512 である場合、768 のスレッドを同時に実行し、最大 512 のスレッドを持つ目的は何ですか?

より一般的な質問は次のとおりです。ブロック、スレッド、およびワープは、SM および SP にどのように配布されますか? すべての SM が一度に 1 つのブロックを実行し、ブロック内のスレッドがワープ (32 スレッド) に分割され、SP がワープを実行することを読みました。

4

2 に答える 2

68

NVIDIA の Web サイトでウェビナーを確認してください。ライブ セッションに参加したり、事前に録画されたセッションを視聴したりできます。以下は簡単な概要ですが、ウェビナーを視聴することを強くお勧めします。ウェビナーは、図を見て同時に説明できるため、非常に役立ちます。

GPU で関数 (カーネル) を実行すると、スレッドブロックグリッドとして実行されます。

  • スレッドは最も細かい粒度であり、各スレッドはブロック内に一意の識別子 (threadIdx) を持ち、操作するデータを選択するために使用されます。スレッドは、比較的多数のレジスタを持つことができ、レジスタ ファイルのスピルや大きな自動変数に使用される、ローカル メモリと呼ばれるメモリのプライベート領域も持ちます。
  • ブロックは、バッチで一緒に実行されるスレッドのグループです。このレベルの粒度の主な理由は、ブロック内のスレッドが高速な共有メモリを使用して通信することで連携できるためです。各ブロックには一意の識別子 (blockIdx) があり、threadIdx と組み合わせてデータの選択に使用されます。
  • グリッドは、GPU 操作を一緒に実行するブロックのセットです。

それが論理階層です。GPU に関数を実装するには、論理階層を理解するだけで十分ですが、パフォーマンスを得るには、SM と SP であるハードウェアも理解する必要があります。

GPU は SM で構成され、各 SM には多数の SP が含まれます。現在、SM ごとに 8 個の SP と GPU ごとに 1 ~ 30 個の SM がありますが、本当に高度になるまで、実際の数は大きな問題ではありません。

パフォーマンスを考慮する最初のポイントは、ワープです。ワープは 32 個のスレッドのセットです (たとえば、ブロックに 128 個のスレッドがある場合、スレッド 0 ~ 31 は 1 つのワープに、32 ~ 63 は次のワープに、というようになります。ワープはいくつかの理由で非常に重要です。 、最も重要なことは次のとおりです。

  • ワープ内のスレッドは一緒にバインドされます。ワープ内の 1 つのスレッドが if-else ブロックの「if」側に進み、他のスレッドが「else」側に進む場合、実際には 32 個のスレッドすべてが両方の側に進みます。機能的には問題はありません。分岐すべきでないスレッドは無効になるため、常に正しい結果が得られますが、両側が長い場合、パフォーマンスの低下が重要になります。
  • ワープ内のスレッド (実際にはハーフ ワープですが、ワープに適していれば、次の世代でも安全です) メモリからデータを一緒にフェッチするため、すべてのスレッドが同じスレッド内でデータをフェッチすることを保証できる場合'segment' の場合、1 つのメモリ トランザクションのみを支払うことになり、それらがすべてランダムなアドレスからフェッチされる場合は、32 のメモリ トランザクションを支払うことになります。詳細についてはAdvanced CUDA Cのプレゼンテーションを参照してください。
  • ワープ内のスレッド (現在の GPU ではハーフワープ) は一緒に共有メモリにアクセスします。注意しないと、メモリにアクセスするためにスレッドが互いにキューに入れなければならない「バンク競合」が発生します。

ワープとは何かを理解したら、最後のポイントは、ブロックとグリッドが GPU にどのようにマッピングされるかです。

各ブロックは 1 つの SM で開始され、完了するまでそこに残ります。完了するとすぐにリタイアし、SM で別のブロックを起動できます。GPU にスケーラビリティを提供するのは、この動的スケジューリングです。SM が 1 つの場合、すべてのブロックが 1 つの大きなキューの同じ SM で実行されます。SM が 30 の場合、ブロックは SM 間で動的にスケジュールされます。そのため、GPU 関数を起動するときは、グリッドが多数のブロック (少なくとも数百) で構成されていることを確認して、任意の GPU 間でスケーリングできるようにする必要があります。

最後のポイントは、SM はいつでも複数のブロックを実行できるということです。これは、ブロックが (現在) 512 スレッドまでしかないのに、SM が 768 スレッド (または一部の GPU ではそれ以上) を処理できる理由を説明しています。基本的に、SM に使用可能なリソース (レジスタと共有メモリ) がある場合、追加のブロック (最大 8 つ) を使用します。Occupancy Calculator スプレッドシート (SDK に含まれています) は、いつでも実行できるブロックの数を決定するのに役立ちます。

ブレイン ダンプで申し訳ありません。ウェビナーをご覧ください。簡単になるはずです。

于 2010-02-06T16:19:05.373 に答える
3

最初は少し混乱しますが、各SPが4ウェイSMTのようなことを行うことを知っておくと役立ちます。つまり、4スレッドを循環し、クロックごとに1つの命令を発行し、各命令で4サイクルのレイテンシを実現します。これが、8つのSPで実行されるワープごとに32のスレッドを取得する方法です。

ワープ、ブロック、スレッドなどの残りのすべてを調べるのではなく、この種の質問が定期的に発生し、すでにいくつかの良い説明があるnVidiaCUDAフォーラムを参照します。

于 2010-02-05T13:48:44.367 に答える