[cuda] CUDA 그리드 치수, 블록 치수 및 스레드 구성 이해 (간단한 설명) [닫기]

GPU는 스레드를 어떻게 실행하도록 구성되어 있습니까?



답변

하드웨어

GPU 장치에 예를 들어 4 개의 멀티 프로세싱 장치가 있고 각각 768 개의 스레드를 실행할 수있는 경우 주어진 순간에 4 * 768 개의 스레드 만 실제로 병렬로 실행됩니다 (더 많은 스레드를 계획하는 경우 대기 중) 그들의 차례).

소프트웨어

스레드는 블록으로 구성됩니다. 블록은 다중 처리 장치에 의해 실행됩니다. 1Dimension (x), 2Dimensions (x, y) 또는 3Dim 인덱스 (x, y, z)를 사용하여 블록의 스레드를 식별 (인덱싱) 할 수 있지만 어떤 경우에도 xy z <= 768 (다른 제한 사항이 적용됨) x, y, z에 대해서는 가이드 및 장치 기능을 참조하십시오).

분명히 4 * 768 이상의 스레드가 필요한 경우 4 개 이상의 블록이 필요합니다. 블록은 1D, 2D 또는 3D로 색인 될 수도 있습니다. GPU에 들어가기 위해 대기중인 블록이 있습니다 (이 예에서는 GPU에 4 개의 멀티 프로세서가 있고 동시에 4 개의 블록 만 실행되기 때문에).

이제 간단한 사례 : 512×512 이미지 처리

하나의 스레드가 하나의 픽셀 (i, j)을 처리하기를 원한다고 가정하십시오.

각각 64 개의 스레드 블록을 사용할 수 있습니다. 그런 다음 512 * 512 / 64 = 4096 블록이 필요합니다 (따라서 512 x 512 스레드 = 4096 * 64)

blockDim = 8 x 8 (블록 당 64 스레드)을 갖는 2D 블록의 스레드를 구성 (이미지 색인화를 쉽게하기 위해)하는 것이 일반적입니다. 나는 그것을 ThreadPerBlock이라고 부른다.

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의 멀티 프로세서 중 하나에 블록이 할당되기를 기다리고 있습니다.

커널에서 스레드에 의해 처리 될 픽셀 (i, j)은 다음과 같이 계산됩니다.

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


답변

9800GT GPU를 가정 해보십시오.

  • 14 개의 멀티 프로세서 (SM)가 있습니다
  • 각 SM에는 8 개의 스레드 프로세서 (AKA 스트림 프로세서, SP 또는 코어)가 있습니다
  • 블록 당 최대 512 개의 스레드 허용
  • warpsize는 32입니다. 즉, 각 14×8 = 112 스레드 프로세서는 최대 32 개의 스레드를 예약 할 수 있습니다.

https://www.tutorialspoint.com/cuda/cuda_threads.htm

블록은 512보다 많은 활성 스레드를 가질 수 없으므로 __syncthreads제한된 수의 스레드 만 동기화 할 수 있습니다. 즉, 600 개의 스레드로 다음을 실행하는 경우 :

func1();
__syncthreads();
func2();
__syncthreads();

커널은 두 번 실행해야하며 실행 순서는 다음과 같습니다.

  1. func1은 처음 512 개의 스레드에 대해 실행됩니다.
  2. func2는 처음 512 개의 스레드에 대해 실행됩니다.
  3. 나머지 스레드에 대해 func1이 실행됩니다.
  4. 나머지 스레드에 대해 func2가 실행됩니다.

노트 :

요점은 __syncthreads블록 전체 작업이며 모든 스레드를 동기화하지는 않습니다.


__syncthreads512 개가 넘는 스레드로 블록을 만들고 워프가 일정을 처리하도록 할 수 있기 때문에 동기화 할 수 있는 정확한 스레드 수에 대해 잘 모르겠습니다 . 이해하기에는 더 정확합니다 : func1은 적어도 처음 512 스레드에 대해 실행 됩니다 .

이 답변을 편집하기 전에 (2010 년) 14x8x32 스레드가을 사용하여 동기화되었음을 측정했습니다 __syncthreads.

누군가가 더 정확한 정보를 위해 이것을 다시 테스트한다면 대단히 감사하겠습니다.


답변