CUDAパラダイムは初めてです。私の質問は、ブロックごとのスレッド数とグリッドごとのブロック数を決定することです。ちょっとしたアートとトライアルがこれに影響しますか?私が見つけたのは、多くの例がこれらのことのために選ばれたように見える任意の数であるということです。
私は、任意のサイズの行列を乗算メソッドに渡すことができる問題を考えています。そのため、Cの各要素(C = A * Bなど)は単一のスレッドで計算されます。この場合、スレッド/ブロック、ブロック/グリッドをどのように決定しますか?
一般に、データに合わせてブロック/グリッドのサイズを調整し、同時に占有率、つまり一度にアクティブになるスレッドの数を最大化します。占有に影響する主な要因は、共有メモリの使用、レジスタの使用、およびスレッドブロックサイズです。
CUDA対応GPUの処理機能はSM(ストリーミングマルチプロセッサ)に分割され、SMの数は実際のカードによって異なりますが、ここでは簡単にするために単一のSMに焦点を当てます(すべて同じように動作します)。各SMには、有限数の32ビットレジスタ、共有メモリ、アクティブなブロックの最大数、およびアクティブなスレッドの最大数があります。これらの数値は、GPUのCC(計算機能)に依存し、Wikipediaの記事 http://en.wikipedia.org/wiki/CUDA の中央にあります。
まず、カーネルはワープ(32スレッド)で命令を発行するため、スレッドブロックサイズは常に32の倍数にする必要があります。たとえば、ブロックサイズが50スレッドの場合、GPUは引き続き64スレッドにコマンドを発行するため、無駄になります。
第二に、共有メモリとレジスタについて心配する前に、カードの計算能力に対応するスレッドとブロックの最大数に基づいてブロックのサイズを決めてください。これを行うには複数の方法があります。たとえば、各SMに16個のアクティブブロックと2048個のアクティブスレッドを含めることができるCC 3.0カードなどです。つまり、ブロックごとに128スレッドがある場合、2048スレッドの制限に達する前にSMに16ブロックを収めることができます。 256スレッドを使用する場合、8にしか適合できませんが、利用可能なすべてのスレッドを使用しているため、完全に占有されます。ただし、ブロックごとに64スレッドを使用すると、16ブロックの制限に達したときに1024スレッドしか使用されないため、占有率は50%になります。共有メモリとレジスタの使用がボトルネックではない場合、これは主な懸念事項です(データディメンション以外)。
グリッドのトピックについて...グリッド内のブロックはSMに分散して開始され、残りのブロックはパイプラインに配置されます。ブロックを取得するのに十分なリソースがSMにあるとすぐに、ブロックはSMに移動して処理されます。つまり、SMでブロックが完了すると、新しいブロックが移動します。特に遅いブロックのほうがリソースが少なくなるため、より小さいブロック(前の例では256の代わりに128)を使用すると、より速く完了する可能性がありますが、これはコードに大きく依存しています。
レジスタと共有メモリについては、占有を制限している可能性があるため、次を見てください。共有メモリはSM全体で有限であるため、可能な限り多くのブロックがSMに収まる量で使用するようにしてください。同じことがレジスタの使用にも当てはまります。繰り返しますが、これらの数値は計算能力に依存しており、ウィキペディアのページに集計されています。がんばろう!
http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls
CUDA Occupancy Calculatorを使用すると、特定のCUDAカーネルによるGPUのマルチプロセッサーoccupancyを計算できます。マルチプロセッサ占有率は、GPUのマルチプロセッサでサポートされているワープの最大数に対するアクティブワープの比率です。デバイス上の各マルチプロセッサには、CUDAプログラムスレッドが使用できるN個のレジスタセットがあります。これらのレジスタは、マルチプロセッサで実行されるスレッドブロック間で割り当てられる共有リソースです。 CUDAコンパイラは、レジスタの使用を最小限に抑えて、マシンで同時にアクティブにできるスレッドブロックの数を最大化しようとします。プログラムがスレッドごとに使用されるレジスタにスレッドブロックサイズを掛けたカーネルを起動しようとすると、起動は失敗します...
まれな例外を除き、ブロックごとに一定数のスレッドを使用する必要があります。グリッドごとのブロック数は、マトリックス乗算の場合のマトリックス次元など、問題のサイズによって決まります。
ブロックごとのスレッド数の選択は非常に複雑です。ほとんどのCUDAアルゴリズムはさまざまな可能性を認めており、選択はカーネルを最も効率的に実行するものに基づいています。スレッドスケジューリングハードウェアがどのように機能するかにより、ほとんど常に32の倍数、少なくとも64です。最初の試行の適切な選択は、128または256です。
同じブロック内のスレッドは同じ共有メモリにアクセスできるため、共有メモリも考慮する必要があります。大量の共有メモリを必要とするものを設計している場合、ブロックごとのスレッド数を増やすと有利な場合があります。
たとえば、コンテキストの切り替えに関しては、32の倍数でもまったく同じように機能します。そのため、1Dの場合、64スレッドで1ブロック、または32スレッドで2ブロックを起動しても、グローバルメモリアクセスに違いはありません。ただし、手元の問題が自然に1つの長さ64のベクトルに分解される場合、最初のオプションは2番目のオプションよりも優れています(メモリオーバーヘッドが少なく、すべてのスレッドが同じ共有メモリにアクセスできます)。