ブロックごとのスレッド、グリッドごとのブロックを決定するCUDA



Cuda Determining Threads Per Block



解決:

一般に、データに一致するようにブロック/グリッドのサイズを設定し、同時に占有率、つまり一度にアクティブになるスレッドの数を最大化する必要があります。占有率に影響を与える主な要因は、共有メモリの使用量、レジスタの使用量、およびスレッドブロックサイズです。

CUDA対応のGPUの処理機能はSM(ストリーミングマルチプロセッサ)に分割されており、SMの数は実際のカードによって異なりますが、ここでは簡単にするために単一のSMに焦点を当てます(すべて同じように動作します)。各SMには、有限数の32ビットレジスタ、共有メモリ、最大数のアクティブブロック、および最大数のアクティブスレッドがあります。これらの数値は、GPUのCC(計算機能)によって異なり、ウィキペディアの記事http://en.wikipedia.org/wiki/CUDAの中央にあります。



まず、カーネルはワープ(32スレッド)で命令を発行するため、スレッドブロックサイズは常に32の倍数である必要があります。たとえば、ブロックサイズが50スレッドの場合でも、GPUは64スレッドにコマンドを発行し、それらを無駄にするだけです。

次に、共有メモリとレジスタについて心配する前に、カードの計算機能に対応するスレッドとブロックの最大数に基づいてブロックのサイズを決定してください。これを行うには複数の方法がある場合があります...たとえば、各SMのCC 3.0カードには、16個のアクティブブロックと2048個のアクティブスレッドを含めることができます。つまり、ブロックあたり128スレッドの場合、2048スレッドの制限に達する前にSMに16ブロックを収めることができます。 256スレッドを使用する場合、8にしか適合できませんが、使用可能なすべてのスレッドを使用しているため、完全に占有されます。ただし、ブロックごとに64スレッドを使用すると、16ブロックの制限に達した場合に1024スレッドしか使用されないため、占有率は50%になります。共有メモリとレジスタの使用がボトルネックではない場合、これが(データディメンション以外の)主な懸念事項になります。



グリッドのトピックについて...グリッド内のブロックがSM全体に分散されて開始され、残りのブロックがパイプラインに配置されます。ブロックを取得するのに十分なリソースがSMにあるとすぐに、ブロックは処理のためにSMに移動されます。言い換えると、SMでブロックが完了すると、新しいブロックが移動します。特に遅いブロックではリソースの占有が少なくなるため、ブロックが小さいほど(前の例では256ではなく128)完了が速くなる可能性があるという議論をすることができます。これはコードに大きく依存します。

レジスタと共有メモリに関しては、占有を制限している可能性があるため、次にそれを見てください。共有メモリはSM全体で有限であるため、できるだけ多くのブロックがSMに収まる量で使用するようにしてください。レジスターの使用についても同じことが言えます。繰り返しになりますが、これらの数値は計算能力に依存し、ウィキペディアのページにまとめられています。幸運を!


https://docs.nvidia.com/cuda/cuda-occupancy-calculator/index.html



CUDA Occupancy Calculatorを使用すると、マルチプロセッサを計算できます 占有率 与えられたCUDAカーネルによるGPUの。マルチプロセッサの占有率は、GPUのマルチプロセッサでサポートされているワープの最大数に対するアクティブなワープの比率です。デバイス上の各マルチプロセッサには、CUDAプログラムスレッドで使用できるN個のレジスタのセットがあります。これらのレジスタは、マルチプロセッサで実行されるスレッドブロック間で割り当てられる共有リソースです。 CUDAコンパイラは、レジスタの使用量を最小限に抑えて、マシンで同時にアクティブにできるスレッドブロックの数を最大化しようとします。プログラムが、スレッドごとに使用されるレジスタにスレッドブロックサイズを掛けた値がNより大きいカーネルを起動しようとすると、起動は失敗します...


まれな例外を除いて、ブロックごとに一定数のスレッドを使用する必要があります。グリッドあたりのブロック数は、行列乗算の場合の行列の次元など、問題のサイズによって決定されます。

ブロックあたりのスレッド数の選択は非常に複雑です。ほとんどのCUDAアルゴリズムは幅広い可能性を認めており、その選択はカーネルを最も効率的に実行する理由に基づいています。スレッドスケジューリングハードウェアがどのように機能するかにより、ほとんどの場合32の倍数であり、少なくとも64です。最初の試行に適した選択肢は128または256です。