スレッドはどのように編成されてGPUで実行されますか?
たとえば、GPUデバイスに4つのマルチプロセッシングユニットがあり、それぞれが768スレッドを実行できる場合、特定の瞬間に実際に並列で実行されるのは4 * 768スレッド以下です(さらに多くのスレッドを計画している場合、それらは待機します彼らの番)。
スレッドはブロックで構成されています。ブロックは、マルチプロセッシングユニットによって実行されます。ブロックのスレッドは、1Dimension(x)、2Dimensions(x、y)、または3Dimインデックス(x、y、z)を使用して識別(インデックス)できますが、いずれの場合もx y z <= 768この例では(x、y、zには他の制限が適用されます。ガイドとデバイスの機能を参照してください)。
明らかに、4 * 768以上のスレッドが必要な場合は、4ブロック以上必要です。ブロックには、1D、2D、または3Dのインデックスを付けることもできます。 GPUに入るのを待機しているブロックのキューがあります(この例では、GPUには4つのマルチプロセッサがあり、同時に実行されるのは4つのブロックのみであるため)。
1つのスレッドで1つのピクセル(i、j)を処理するとします。
それぞれ64スレッドのブロックを使用できます。次に、512 * 512/64 = 4096ブロックが必要です(したがって、512x512スレッド= 4096 * 64になります)
BlockDim = 8 x 8(ブロックあたり64スレッド)を持つ2Dブロックのスレッドを整理する(イメージのインデックス付けを容易にする)のは一般的です。私は、それをthreadsPerBlockと呼ぶことを好みます。
dim3 threadsPerBlock(8, 8); // 64 threads
2D gridDim = 64 x 64ブロック(4096ブロックが必要)。私はそれをnumBlocksと呼ぶことを好みます。
dim3 numBlocks(imageWidth/threadsPerBlock.x, /* for instance 512/8 = 64*/
imageHeight/threadsPerBlock.y);
カーネルは次のように起動します。
myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );
最後に、「4096ブロックのキュー」のようなものがあります。このブロックでは、GPUのマルチプロセッサの1つが割り当てられて64スレッドが実行されるのを待っています。
カーネルでは、スレッドによって処理されるピクセル(i、j)は次のように計算されます。
uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;
9800GT GPU:14個のマルチプロセッサがあり、それぞれが8個のスレッドプロセッサを持ち、warpsizeが32であると仮定すると、各スレッドプロセッサは最大32個のスレッドを処理します。 14 * 8 * 32 = 3584は、実際のcuncurrentスレッドの最大数です。
このカーネルを3584を超えるスレッド(たとえば4000スレッドで実行する場合、ブロックとグリッドの定義方法は重要ではありません。gpuはそれらを同じように扱います):
func1();
__syncthreads();
func2();
__syncthreads();
これらの2つの関数の実行順序は次のとおりです。
1.func1は最初の3584スレッドに対して実行されます
2. func2は最初の3584スレッドに対して実行されます
3. func1は残りのスレッドに対して実行されます
4. func2は残りのスレッドに対して実行されます