1. ホーム
  2. cuda

[解決済み] CUDAのグリッド寸法、ブロック寸法、スレッド構成を理解する(簡単な説明)【終了しました。

2022-04-24 16:16:36

質問

GPUで実行されるスレッドはどのように構成されているのですか?

どのように解決するのか?

ハードウェア

GPUデバイスが例えば4つのマルチプロセッシングユニットを持ち、それぞれ768スレッドを実行できる場合、ある瞬間には4*768以上のスレッドが実際に並列実行されることはありません(さらにスレッドを計画すると、順番待ちとなります)。

ソフトウェア

スレッドはブロック単位で構成されています。ブロックはマルチプロセッシング・ユニットによって実行されます。 ブロックのスレッドは、1次元(x)、2次元(x,y)、3次元(x,y,z)のインデックスを使用して特定(インデックス)することができますが、いずれの場合にもx y この例では、z <= 768です(x,y,zには他の制限もありますので、ガイドとお使いのデバイスの能力を参照してください)。

当然ながら、4*768スレッド以上必要な場合は、4ブロック以上必要です。 ブロックは1次元、2次元、3次元のインデックスを持つこともあります。ブロックは1次元、2次元、3次元のインデックスが付けられます。 この例では、GPUには4つのマルチプロセッサがあり、4つのブロックしかない。 同時に実行される)。

512x512の画像を処理する簡単な例です。

1つのスレッドで1つのピクセル(i,j)を処理させたいとします。

64スレッドずつのブロックを使用することができます。そうすると、512*512/64 = 4096 ブロックが必要です。 (512×512スレッド=4096×64)。

画像のインデックス付けを容易にするため)スレッドをブロックディム=8×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ブロックのキュー」のようなものがあり、ブロックは64スレッドを実行するためにGPUのマルチプロセッサの1つが割り当てられるのを待っている状態になっています。

カーネルでは、スレッドが処理する画素(i,j)はこのように計算されます。

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;