web-dev-qa-db-ja.com

CUDAでのレジスタ使用の制限:__ launch_bounds__ vs maxrregcount

NVIDIA CUDA Cプログラミングガイド から:

レジスタの使用は、maxrregcountコンパイラオプションまたは起動境界で説明されている起動境界を使用して制御できます。

私の理解から(そして私が間違っている場合は訂正してください)、-maxrregcount.cuファイル全体が使用できるレジスタの数を制限しますが、__launch_bounds__修飾子は各__global__カーネルのmaxThreadsPerBlockminBlocksPerMultiprocessorを定義します。これら2つは同じタスクを実行しますが、2つの異なる方法で実行します。

私の使用法では、パフォーマンスを最大化するために、スレッドごとに40レジスタが必要です。したがって、-maxrregcount 40を使用できます。 __launch_bounds__(256, 6)を使用して40レジスタを強制することもできますが、これによりレジスタのロードとストアが流出します。

これらのレジスタの流出を引き起こす2つの違いは何ですか?

8
Kelsius

この質問の序文は、CUDA C Programming Guideを引用して、

カーネルが使用するレジスタが少ないほど、マルチプロセッサ上に存在するスレッドとスレッドブロックが増える可能性があり、パフォーマンスを向上させることができます。

現在、__launch_bounds__maxregcountは、2つの異なるメカニズムによってレジスタの使用を制限しています。

__launch_bounds__

nvccは、カーネル起動セットアップのパフォーマンスと一般性のバランスをとることにより、__global__関数で使用されるレジスターの数を決定します。別の言い方をすれば、使用されるレジスタの数をこのように選択すると、ブロックあたりのスレッド数とマルチプロセッサあたりのブロック数が異なる場合に「有効性が保証」されます。ただし、コンパイル時にブロックあたりの最大スレッド数と(場合によっては)マルチプロセッサあたりの最小ブロック数のおおよそのアイデアが利用できる場合は、この情報を使用して、そのような起動用にカーネルを最適化できます。言い換えると

#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
}

nvccがそのような起動構成のレジスタ数を「最適な」方法で選択できるように、起動構成の可能性をコンパイラに通知します。

MAX_THREADS_PER_BLOCKパラメーターは必須ですが、MIN_BLOCKS_PER_MPパラメーターはオプションです。また、カーネルがMAX_THREADS_PER_BLOCKより大きいブロックあたりのスレッド数で起動された場合、カーネルの起動は失敗することに注意してください。

制限メカニズムは、Programming Guideで次のように説明されています。

起動境界が指定されている場合、コンパイラはまず、カーネルが使用するレジスタ数の上限Lを導き出し、minBlocksPerMultiprocessorスレッドのminBlocksPerMultiprocessorブロック(またはmaxThreadsPerBlockが指定されていない場合は単一のブロック)がマルチプロセッサ上に存在できるようにします。次に、コンパイラは次の方法でレジスタの使用を最適化します。

  • 初期レジスタ使用量がLよりも高い場合、コンパイラはそれがL以下になるまでそれをさらに減らしますが、通常はローカルメモリ使用量の増加や命令数の増加を犠牲にします。

したがって、__launch_bounds__はレジスタの流出につながる可能性があります。

maxrregcount

maxrregcountは、コンパイラにレジスタの使用を再配置させることにより、使用されるレジスタの数を__launch_bounds__とは異なり、ユーザーが設定した数に単純にハード制限するコンパイラフラグです。コンパイラが課せられた制限を下回らない場合、コンパイラは単にローカルメモリ(実際にはDRAM)にそれをこぼします。このローカル変数でさえ、グローバルDRAMメモリ変数に格納され、L1、L2にキャッシュできます。

13
JackOLantern