スレッドはGPUによって実行されるようにどのように編成されていますか?
スレッドは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を想定します。
https://www.tutorialspoint.com/cuda/cuda_threads.htm
ブロックは512を超えるアクティブスレッドを持つことができないため、__syncthreads
限られた数のスレッドのみを同期できます。つまり、600スレッドで以下を実行するとします。
func1();
__syncthreads();
func2();
__syncthreads();
その場合、カーネルは2回実行する必要があり、実行順序は次のようになります。
注意:
主なポイントは__syncthreads
ブロック全体の操作であり、すべてのスレッドを同期するわけではありません。
__syncthreads
512スレッドを超えるブロックを作成して、ワープにスケジューリングを処理させることができるため、同期できるスレッドの正確な数についてはわかりません。私の理解では、より正確です:func1は少なくとも最初の512スレッドに対して実行されます。
この回答を編集する前に(2010年に戻って)、14x8x32スレッドがを使用して同期されて__syncthreads
いることを測定しました。
より正確な情報を得るために、誰かがこれをもう一度テストしていただければ幸いです。
__syncthreads
は問題ではなく、ブロック全体の操作であり、実際にすべてのスレッドを同期しないという事実はCUDA学習者にとって厄介です。だから、私はあなたが私に与えた情報に基づいて私の答えを更新しました。ほんとうにありがとう。