CUDA Warps and Occupancy

yeonsoo·2023년 2월 27일
1

SM은 streaming multi-processor with multiple processing cores
각 SM은 32개의 프로세스 코어를 가짐.
Single Instruction Multiple Thread (SIMT) 개념으로 실행됨

그리드 라는건 독립적인 블록들로 이루어짐
블록은 그 블록 내에서 서로 교류 가능한 쓰레드 들로 이루어짐
32개의 쓰레드는 워프 라는 단위를 이룸
인스트럭션은 워프 단위로 issued
피연산자가 준비되지 않을 경우 워프 전체가 정지됨

  • 워프가 정지되면 다른 워프로 context switch가 일어나는데, 이는 매우 빠르게 실행되어야함

레지스터와 공유메모리는 블록이 활성화되어있는 동안은 그 블록에 묶여있음
한번 블록이 활성화되면 그 블록 내 모든 쓰레드가 완료될때까지 살아있다

최상의 전역 메모리 대역폭을 달성하기 위해서는 지연을 감추기 위한 transaction in flight를 충분히 가져야 함
이는

  • 점유를 높이거나
  • instruction 레벨의 병렬을 늘림으로써

달성 가능

*메모리 대역폭이란? 프로세서가 반도체 메모리에서 데이터를 읽거나 쓰는 속도. byte/s 단위.

cuda occupancy calculator와 visual profiler를 사용하면 메모리 대역폭/점유율을 확인할 수 있다.

점유율 = 활성 워프 / 최대 활성 워프
전체 블록 하나에 리소스가 할당됨

  • 리소스는 유한함
  • 각 쓰레드당 너무 많은 리소스를 쓰면 점유율을 제한할 수 있음
    점유는
  • 레지스터 사용량
  • 공유메모리 사용량
  • 블록 크기
    에 따라 제한될 수 있다.

점유율 제한 요인:

  • 레지스터 사용량
    --ptxas-options=-v 와 함께 컴파일하면 확인 가능
    SM 당 32k 레지스터 (Fermi의 경우)
    예시1) 커널은 각 쓰레드별 20개의 레지스터를 사용 (+1 임시)
    활성 쓰레드 = 32k/21 = 1560 쓰레드 (가능)
    -> 1536 쓰레드 (in SM) 사용시 1의 점유율
    예시2) 커널이 각 쓰레드별 63개의 레지스터를 사용 (+1 임시)
    활성 쓰레드 = 32k/64 = 512 쓰레드 가능
    -> 512/1536 = .3333 점유율
    Can control register usage with the nvcc flag: --maxrregcount

  • 공유메모리
    마찬가지로 --ptxas-options=-v 로 컴파일시 각 블록당 공유메모리를 확인 가능
    Fermi의 경우 16K 또는 48K의 공유메모리 있음
    예시1) 48K 공유메모리의 경우
    커널이 쓰레드별로 32바이트의 공유메모리 사용시
    48K/32 = 1536 쓰레드 가능
    -> occupancy=1
    예시2) 16K 공유메모리의 경우 16K/32=512 쓰레드. 이때 1536 쓰레드 할당 시 occ=.333
    공유메모리를 너무 크게 잡지 말 것.

  • 블록 사이즈
    각 SM은 최대 8개의 활성 블록을 가짐
    작은 블록 크기는 전체 쓰레드의 개수를 제한함
    블록 개수를 많게 하고, 쓰레드 개수는 일반적으로 128-256으로 하도록 한다

점유율은 보통의 경우 66%정도면 최대 대역폭을 만족함
점유율을 높이려고 애쓰는것보다 instruction level parallelism (ILP)를 살펴보는게 훨씬 효과가 크다
Vasily Volkov’s GTC2010 talk “Better Performance at Lower Occupancy”
https://www.nvidia.com/content/gtc-2010/pdfs/2238_gtc2010.pdf

출처: https://on-demand.gputechconf.com/gtc-express/2011/presentations/cuda_webinars_WarpsAndOccupancy.pdf

profile
to be enterprising

0개의 댓글