IT TIP

블록 당 스레드, 그리드 당 블록을 결정하는 CUDA

itqueen 2021. 1. 10. 19:44
반응형

블록 당 스레드, 그리드 당 블록을 결정하는 CUDA


저는 CUDA 패러다임이 처음입니다. 내 질문은 블록 당 스레드 수와 그리드 당 블록을 결정하는 것입니다. 약간의 예술과 시험이 이것에 작용합니까? 내가 찾은 것은 많은 예제가 이러한 것들을 위해 겉보기에 임의의 숫자를 선택했다는 것입니다.

모든 크기의 행렬을 곱셈 방법에 전달할 수있는 문제를 고려하고 있습니다. 따라서 C의 각 요소 (예 : C = A * B)는 단일 스레드로 계산됩니다. 이 경우 스레드 / 블록, 블록 / 그리드를 어떻게 결정합니까?


일반적으로 데이터와 일치하도록 블록 / 그리드의 크기를 조정하고 동시에 점유율, 즉 한 번에 활성화되는 스레드 수를 최대화하려고합니다. 점유에 영향을 미치는 주요 요인은 공유 메모리 사용량, 레지스터 사용량 및 스레드 블록 크기입니다.

CUDA 지원 GPU에는 처리 기능이 SM (스트리밍 멀티 프로세서)으로 분할되어 있으며 SM의 수는 실제 카드에 따라 다르지만 여기서는 단순성을 위해 단일 SM에 초점을 맞출 것입니다 (모두 동일하게 작동 함). 각 SM에는 한정된 수의 32 비트 레지스터, 공유 메모리, 최대 활성 블록 수 및 최대 활성 스레드 수가 있습니다. 이 숫자는 GPU의 CC (컴퓨팅 기능)에 따라 다르며 Wikipedia 기사 http://en.wikipedia.org/wiki/CUDA 중간에서 찾을 수 있습니다 .

우선, 커널이 워프 (32 개 스레드)로 명령어를 발행하기 때문에 스레드 블록 크기는 항상 32의 배수 여야합니다. 예를 들어 블록 크기가 50 개 스레드 인 경우 GPU는 여전히 64 개 스레드에 명령을 내리고 낭비하는 것입니다.

둘째, 공유 메모리 및 레지스터에 대해 걱정하기 전에 카드의 컴퓨팅 기능에 해당하는 최대 스레드 및 블록 수를 기준으로 블록 크기를 조정하십시오. 때때로이를 수행하는 여러 가지 방법이 있습니다. 예를 들어, 각 SM은 16 개의 활성 블록과 2048 개의 활성 스레드를 가질 수있는 CC 3.0 카드입니다. 즉, 블록 당 128 개의 스레드가있는 경우 2048 스레드 제한에 도달하기 전에 SM에 16 개의 블록을 넣을 수 있습니다. 256 개의 스레드를 사용하는 경우 8 개만 들어갈 수 있지만 여전히 사용 가능한 모든 스레드를 사용하고 있으며 여전히 전체 점유율을 유지합니다. 그러나 블록 당 64 개의 스레드를 사용하면 16 개의 블록 제한에 도달 할 때 1024 개의 스레드 만 사용되므로 점유율은 50 %에 불과합니다. 공유 메모리 및 레지스터 사용량이 병목 현상이 아닌 경우 이것이 주요 관심사 여야합니다 (데이터 차원 제외).

그리드의 주제에 대해 ... 그리드의 블록은 시작을 위해 SM에 분산되고 나머지 블록은 파이프 라인에 배치됩니다. 해당 SM에 블록을 가져갈 충분한 리소스가있는 즉시 블록은 처리를 위해 SM으로 이동됩니다. 즉, SM에서 블록이 완료되면 새 블록이 이동됩니다. 특히 느린 블록이 더 적은 리소스를 소모하므로 더 작은 블록 (이전 예에서 256 대신 128)이 더 빨리 완료 될 수 있다는 주장을 할 수 있습니다. 이것은 코드에 크게 의존합니다.

레지스터 및 공유 메모리와 관련하여 점유를 제한 할 수 있으므로 다음을 살펴보십시오. 공유 메모리는 전체 SM에 대해 유한하므로 가능한 한 많은 블록이 SM에 맞도록 허용하는 양으로 사용하십시오. 레지스터 사용도 마찬가지입니다. 다시 말하지만,이 수치는 컴퓨팅 기능에 따라 다르며 위키피디아 페이지에서 표로 확인할 수 있습니다. 행운을 빕니다!


https://docs.nvidia.com/cuda/cuda-occupancy-calculator/index.html

CUDA 점유 계산기를 사용하면 주어진 CUDA 커널에 의해 GPU 의 다중 프로세서 점유 를 계산할 수 있습니다 . 멀티 프로세서 점유는 GPU의 멀티 프로세서에서 지원되는 최대 워프 ​​수에 대한 활성 워프의 비율입니다. 장치의 각 멀티 프로세서에는 CUDA 프로그램 스레드에서 사용할 수있는 N 개의 레지스터 세트가 있습니다. 이러한 레지스터는 다중 프로세서에서 실행되는 스레드 블록 사이에 할당되는 공유 리소스입니다. CUDA 컴파일러는 기계에서 동시에 활성화 될 수있는 스레드 블록 수를 최대화하기 위해 레지스터 사용을 최소화하려고합니다. 프로그램이 스레드 당 사용 된 레지스터와 스레드 블록 크기가 N보다 큰 커널을 시작하려고하면 시작이 실패합니다.


드문 경우를 제외하고는 블록 당 일정한 수의 스레드를 사용해야합니다. 그리드 당 블록 수는 행렬 곱셈의 경우 행렬 차원과 같은 문제 크기에 의해 결정됩니다.

블록 당 스레드 수를 선택하는 것은 매우 복잡합니다. 대부분의 CUDA 알고리즘은 광범위한 가능성을 인정하며 커널을 가장 효율적으로 실행하는 요소에 따라 선택됩니다. 스레드 스케줄링 하드웨어가 작동하는 방식으로 인해 거의 항상 32의 배수, 최소 64입니다. 첫 번째 시도를위한 좋은 선택은 128 또는 256입니다.


또한 동일한 블록의 스레드가 동일한 공유 메모리에 액세스 할 수 있기 때문에 공유 메모리를 고려해야합니다. 많은 공유 메모리가 필요한 것을 설계하는 경우 블록 당 더 많은 스레드가 유리할 수 있습니다.

예를 들어 컨텍스트 전환 측면에서 32의 배수는 동일하게 작동합니다. 따라서 1D의 경우 64 개 스레드가있는 1 개 블록 또는 32 개 스레드가있는 2 개 블록을 시작하면 전역 메모리 액세스에 차이가 없습니다. 그러나 당면한 문제가 자연적으로 1 개의 길이 -64 벡터로 분해되면 첫 번째 옵션이 두 번째 옵션보다 더 좋습니다 (메모리 오버 헤드가 적고 모든 스레드가 동일한 공유 메모리에 액세스 할 수 있음).

참조 URL : https://stackoverflow.com/questions/4391162/cuda-determining-threads-per-block-blocks-per-grid

반응형