SM은 streaming multi-processor with multiple processing cores
각 SM은 32개의 프로세스 코어를 가짐.
Single Instruction Multiple Thread (SIMT) 개념으로 실행됨
그리드 라는건 독립적인 블록들로 이루어짐
블록은 그 블록 내에서 서로 교류 가능한 쓰레드 들로 이루어짐
32개의 쓰레드는 워프 라는 단위를 이룸
인스트럭션은 워프 단위로 issued
피연산자가 준비되지 않을 경우 워프 전체가 정지됨
레지스터와 공유메모리는 블록이 활성화되어있는 동안은 그 블록에 묶여있음
한번 블록이 활성화되면 그 블록 내 모든 쓰레드가 완료될때까지 살아있다
최상의 전역 메모리 대역폭을 달성하기 위해서는 지연을 감추기 위한 transaction in flight를 충분히 가져야 함
이는
달성 가능
*메모리 대역폭이란? 프로세서가 반도체 메모리에서 데이터를 읽거나 쓰는 속도. 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