この質問の序文には、カーネルが使用するCUDA C Programming Guide
、
少ないレジスタ、複数のスレッドとスレッドブロック を引用 パフォーマンスを向上させることができ、マルチプロセッサ、上に存在する可能性がある、ということです。
ここで、__launch_bounds__
とmaxregcount
は2つの異なるメカニズムによる制限レジスタの使用です。
__launch_bounds__
nvcc
性能とカーネルの起動設定の一般性のバランスをとるを通じて__global__
機能で使用するレジスタの数を決定します。別の言い方をすると、使用されるレジスタの数のこのような選択は、ブロック当たりのスレッド数とマルチプロセッサあたりのブロック数の違いに対して「有効性を保証します」。しかし、コンパイル時にブロックあたりのスレッドの最大数とマルチプロセッサあたりの最小ブロック数の可能な近似的な考え方が利用可能であれば、この情報を使ってそのような起動のためにカーネルを最適化することができます。 nvcc
が「最適」な方法でこのような起動設定用レジスタの数を選択することができるように言い換える
#define MAX_THREADS_PER_BLOCK 256
#define MIN_BLOCKS_PER_MP 2
__global__ void
__launch_bounds__(MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP)
fooKernel(int *inArr, int *outArr)
{
// ... Computation of kernel
}
は、おそらく起動構成のコンパイラに通知します。
パラメータは必須ですが、MIN_BLOCKS_PER_MP
パラメータはオプションです。また、ブロックあたりのスレッド数がMAX_THREADS_PER_BLOCK
より大きいカーネルを起動すると、カーネルの起動に失敗することにも注意してください。
次のように制限機構がProgramming Guide
に記載されている:
を発射範囲が指定されている場合、コンパイラは、まずカーネルが確保する を使用すべきレジスタの数にそれらから 上限L
を導出しますブロック (minBlocksPerMultiprocessor
が指定されていない場合)のminBlocksPerMultiprocessor
ブロックは、 maxThreadsPerBlock
のスレッドをマルチプロセッサに置くことができます。 では通常、より多くの地元の費用を最初のレジスタの使用がL
よりも高い場合、それは以下L
になるまで
は、コンパイラはそれをさらに低減し
- : コンパイラは、次の方法での使用を登録最適化メモリ使用量および/またはより高い数の 命令;
したがって、__launch_bounds__
は流出を登録するためにつながることができます。
maxrregcount
maxrregcount
単にレジスタの使用を再配置するようにコンパイラに強制することによって、__launch_bounds__
と分散で、ユーザにより設定された数のために用いレジスタの数をhardlimitsコンパイラフラグです。コンパイラが課された制限値を下回ることができない場合、コンパイラはそれをローカルメモリに単に流し込みます。これは実際にはDRAM
です。このローカル変数でさえも、グローバル変数DRAM
に格納され、メモリ変数はL1、L2にキャッシュされます。
多分簡単な答えです:スレッドごとに40個のレジスタが必要になります。 - 答えに間違って書き留めた場合:GPUに関する情報を提供してください。たぶんあなたの計算で単純な間違いをしただけかもしれません。カーネルを起動した場合と、カーネルを起動した場合のブロックサイズはどれくらいですか? (私はブロックの数が十分に高いと仮定します) – Shadow
@Shadowスレッドごとに約40のregs - 私の間違い/タイプミスです。 GPUについては、CC 5.3を使用するMaxwellアーキテクチャのGPU上で動作しています。 << >>はそれぞれ(132,0,0)と(16,16,0)で、同時に2048スレッドを実行できます(Tegra TX1)。カーネルはどちらの場合も正しく実行されますが、__launch_bounds__を使用するとspillageが発生しますが、スレッド使用量ごとのレジスタはどちらの場合も同じですが、-maxrregcountでは使用できません。 –
Kelsius
両方のバージョンのランタイムを比較しましたか? – Shadow