일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- stl
- C++
- SpMM
- 클라우드
- sycl
- jhDNN
- CUDA
- DRAM
- deep_learning
- Qubit
- Compression
- nvidia
- 딥러닝
- 양자역학의공준
- 쿠버네티스
- FPGA
- jhVM
- 반도체
- kubernetes
- 반도체기초
- convolution
- quantum_computing
- dnn
- CuDNN
- HA
- flash_memory
- cloud
- Semiconductor
- GPU
- POD
- Today
- Total
Computing
GPU 프로그램이 느린 이유 - 1 : Memory Bound 본문
GPU 프로그램이 빠른 이유
GPU는 대표적인 manycore processor들 중 하나[1]로, 4개 혹은 8개의 core를 가지는 일반 CPU와는 다르게 수 천개의 core를 가지고 있다. 이렇게 많은 core를 이용하여 각 데이터를 독립적으로 계산하는 data parallellim을 달성한다.
Fig 1.는 CPU와 GPU의 하드웨어 디자인 방향이 어떻게 다른 지를 보여준다. 초록색 영역은 ALU (arithmetic logic unit)으로 실제 계산이 이뤄지는 영역이며, 각 ALU(초록 박스 하나하나)는 독립적으로 instruction stream(thread)을 계산할 수 있다.. 노란색 영역은 Control logic 영역으로 명령어를 해석하고 instruction 실행 최적화를 계산한다. 예를 들어 branch prediction, out-of-order execution을 계산한다. 빨간색 영역은 cache 영역으로 메인 메모리에 있는 데이터는 access time(latency)가 길기 때문에 CPU core 내의 cache에 저장하여 빠르게 데이터에 접근할 수 있도록 한다.
Fig 1.에서 CPU는 실제 계산하는 영역보다 control logic과 cache 영역이 상대적으로 크다. 즉 CPU는 소수의 instruction stream 을 빠르게 처리하는 것을 목표로 설계되었다(초기에는 하나의 instruction stream을 빠르게 처리하는 것을 목표로 설계됨).
반면에 GPU는 control logic과 cache의 영역이 ALU 영역보다 작다. GPU는 많은 instruction stream을 한번에 처리하는 것을 목표로 설계되었으며, control logic과 cache 영역이 작기에 instruction stream을 빠르게 처리하기 위한 최적화는 약하다.
정리하자면 사실 GPU 프로그램이 CPU 프로그램에 비해 빠르다고 할 수 없다. 어떤 계산을 하는 지에 따라 계산 성능이 달라진다. 하나의 데이터를 빠르게 처리해야 할 경우 CPU를 이용한 프로그램이 더 빠를 것이며, 수 많은 데이터를 독립적으로 처리해야 할 경우 GPU를 이용한 프로그램이 효과적일 것이다.
우리가 일반적으로 GPU을 이용해 가속하는 문제들인 딥러닝이나 그래픽스, simulation 등에서는 GPU 프로그램이 매우 빠른 성능을 보여준다. 이는 GPU가 강한 data parallelism을 활용할 수 있는 문제이기 때문이다. Fully connected layer와 같은 matrix multiplication 문제 C = A*B에서 각 C의 element를 구하는 것은 독립적으로 계산할 수 있다(A,B는 read-only이기 때문에). C의 크기가 충분히 크다면 GPU는 수천 개의 core를 모두 활용하여 빠르게 C를 구할 수 있을 것이다.
GPU 프로그램이 느린 이유
Matrix multiplication와 같은 선형대수, 그래픽스, AI 문제에서 data parallelism을 활용하면 수 백배 이상의 성능 향상을 보일 수 있다. GPU 프로그램이 수 천개의 core를 가졌기에 core 수만큼 (수 천배까지) 빨라질 수 있지 않을까 생각할 수 있지만, 일반적인 경우 거의 불가능하다. 경우에 따라서 CPU single core로 실행하는 것 대비 10배 정도의 성능 달성도 힘들 수 있다. 이는 GPU core 하나가 CPU core 하나보다 느리기 때문에 core 개수만큼의 성능 향상이 어려운 것이도 하지만, 그것 이외에도 많은 이유가 있다. 이번 포스터에서는 그 이유 중 하나인 memory bound 문제에 대해서 정리하고자 한다. GTC 2021에서 발표한 좋은 자료[3]가 있기에 이 자료를 바탕으로 정리한다.
Slow GPU Kernel - Memory Bound 병목
Fig 2.는 CPU와 GPU 각 디바이스의 FP64 operation 계산 성능 및 memory read 성능을 보여준다. FP64 operation 계산 성능은 FP64 GigaFLOPs로 나타내는데, 초당 몇 Giga개의 FP64 operation을 계산할 수 있는 지를 의미한다. Memory read 성능은 memory bandwidth로 나타내며, 초당 몇 GB를 읽는 지를 의미한다. GPU는 CPU에 비해 계산 성능 및 메모리 접근 성능 모두 월등한 성능을 보여준다. 계산 성능의 경우 막대한 core 수를 이용하여 높은 성능을 달성하였으며, 메모리의 경우 GPU 칩과 직접 연결된, 특수 고안된 HBM(high bandwidth memory)를 통해 높은 성능을 달성하였다.
이때 Compute intensity라는 성능 측정 parameter가 보인다. Compute intensity는 다음과 같은 공식으로 나타낸다.
Compute Intensity는 데이터 하나당 얼마만큼의 계산을 효율적으로 수행할 수 있는가를 나타낸다. GPU의 경우 초당 19500G 개의 FP64 계산을 실행할 수 있다. 또한 초당 1555GB (약 194G개의 FP64)를 읽어올 수 있다. 정리하자면 GPU는 초당 194G개의 데이터를 읽을 수 있으며, 이것들을 이용해 19500G개의 계산을 할 수 있다. 1초동안 데이터 하나당 최대 100개의 계산을 할 수 있는 계산 능력이 되는 것이다.
그러나 데이터 하나가 100개의 연산에서 쓰이는 경우는 거의 없다. 데이터 하나를 가지고 10개의 계산만을 한다면 90개 계산을 더 할 수 있는 시간을 낭비하는 것이다. 따라서 높은 Compute Intensity는 메모리 성능의 한계를 의미한다.
글로벌 메모리에 저장된 데이터를 읽어와 실제 계산이 일어나는 ALU까지 가져오는 시간을 memory latency라고 한다. 위 Fig 3.은 DAXPY(Y=aX+Y) 계산에서, GPU의 memory latency와 계산 시간을 비교한 것이다. x[0], y[0]를 읽기 시작하여(load 시점), 데이터가 준비된 시점(ready 시점)까지 많은 시간(=memory latencty)이 걸리며, 실제 계산하는 시간은 memory latency에 비해 작다.
CPU와 GPU 모두 Compute Intensity가 높은 것을 알 수 있다. 이를 해결하기 위해서 CPU와 GPU는 여러 가지 방식으로 아키텍처가 설계되었지만, 서로가 약간은 다른 지향점으로 진화해 왔다. 가장 대표적인 방식으로, CPU는 cache를, GPU는 context switching을 이용한 latency hiding이 있다. CPU는 큰 cache를 이용하여 미리 메인 메모리의 데이터를 CPU core에 가까운 칩 내의 cache에 저장한다. GPU는 cache가 작은 대신 hardware context switching가 매우 빠르게 설계되었다. 이를 활용하여 한 thread가 memory에 접근하고 있는 동안, 다른 thread로 context switching하여 계산 core를 이용해 계산을 진행한다. 이를 통해 memory load 과정에서도 ALU을 busy하게 유지할 수 있다.
Reference
[1] https://en.wikipedia.org/wiki/Manycore_processor
[3] Stephen Jones, HOW GPU COMPUTING WORKS, GTC 2021
'가속기 Accelerator > GPU' 카테고리의 다른 글
CUDA Graphs : 개념 설명 및 구현 예제 (0) | 2022.04.18 |
---|---|
cuBLAS MatMul Tutorial (0) | 2022.03.28 |
CUDA PTX - 2 : Inline PTX Assembly (0) | 2022.03.21 |
CUDA PTX - 1 : Introduction (0) | 2022.03.19 |