| GPU 컴퓨팅 GPU computing | |
|---|---|
| 분야 | 전산과학 × 소프트웨어 |
| 실행 모델 | SIMT (Single Instruction, Multiple Threads) |
| 대표 프레임워크 | CUDA, OpenCL, HIP |
| 성능 병목 | 메모리 대역폭(memory bandwidth) |
1. 개요[편집]
CPU는 소수의 천재가 순서대로 일하는 조직, GPU는 수천 명의 성실한 일꾼이 똑같은 일을 동시에 하는 공장이다.
GPU 컴퓨팅(GPU computing, 또는 GPGPU — General-Purpose computing on GPUs)은 원래 3D 그래픽 렌더링용으로 만들어진 그래픽 처리 장치(GPU)를 일반적인 과학·공학 계산에 활용하는 기법이다. GPU는 수천 개의 단순한 연산 코어를 품고 있어, 같은 연산을 방대한 데이터에 동시에 적용하는 데이터 병렬(data-parallel) 작업에서 CPU를 압도적으로 능가한다. 분자동역학, 격자 볼츠만 방법, 전산유체역학, 딥러닝 학습이 모두 GPU 위로 옮겨간 이유다.1
핵심 철학은 병렬 컴퓨팅 일반과 같지만, GPU는 그 극단이다. CPU가 복잡한 분기 예측·거대한 캐시로 “한 스레드를 최대한 빨리” 굴리는 지연 지향(latency-oriented) 설계라면, GPU는 캐시와 제어 회로를 최소화하고 연산 유닛을 빼곡히 채운 처리량 지향(throughput-oriented) 설계다. 그래서 조건 분기가 복잡한 코드는 GPU에서 힘을 못 쓰고, 규칙적인 대량 산술 연산일수록 빛을 발한다.
2. CUDA와 SIMT 실행 모델[편집]
GPU 프로그래밍의 사실상 표준은 NVIDIA의 CUDA(Compute Unified Device Architecture)다. 개발자는 GPU에서 돌 함수(커널, kernel)를 작성하고, 이를 수만~수백만 개의 스레드로 동시에 띄운다. 스레드들은 계층적으로 조직된다 — 스레드 여러 개가 모여 블록(block), 블록 여러 개가 모여 그리드(grid)를 이룬다.
실행 방식은 SIMT(Single Instruction, Multiple Threads)라 불린다. 하드웨어는 스레드를 32개씩 묶은 워프(warp) 단위로 굴리며, 한 워프의 32개 스레드는 매 순간 똑같은 명령어를 각자의 데이터에 실행한다. 여기서 GPU 최적화의 첫 번째 함정이 나온다 — 워프 발산(warp divergence). 한 워프 안에서 if 분기가 갈리면 GPU는 두 경로를 순차적으로 실행하고 각 경로에 해당 안 되는 스레드를 놀린다. 즉 분기가 많으면 코어가 절반씩 놀아 성능이 급락한다.2 “GPU에서는 if문을 무서워하라”는 격언이 여기서 나온다.
3. 메모리 계층과 대역폭[편집]
GPU 성능을 좌우하는 것은 의외로 연산 능력이 아니라 메모리다. GPU는 이론상 초당 수십 조 번(수십 TFLOPS)의 연산을 할 수 있지만, 그만큼의 데이터를 코어에 공급하지 못하면 코어는 굶어 죽는다. 대부분의 과학 계산 커널은 연산보다 데이터 이동이 병목인 메모리 바운드(memory-bound) 상태다.
메모리는 속도-용량이 반비례하는 계층으로 되어 있다.
| 메모리 | 속도 | 용량 | 특징 |
|---|---|---|---|
| 레지스터 | 최고속 | 매우 작음 | 스레드 전용 |
| 공유 메모리 | 빠름 | 블록당 수십 KB | 블록 내 스레드 공유, 수동 관리 |
| 전역 메모리 | 느림 | 수십 GB | 모든 스레드 접근, DRAM |
최적화의 핵심은 느린 전역 메모리 접근을 줄이고, 접근하더라도 병합 접근(coalesced access) — 인접한 스레드가 인접한 주소를 읽어 한 번의 트랜잭션으로 묶이게 하는 것 — 을 지키는 것이다. 성능 한계는 흔히 연산 강도(arithmetic intensity, 바이트당 연산 수)로 판단하며, 이를 시각화한 것이 루프라인 모델(roofline model)이다. 강도가 낮으면 대역폭이 천장이고, 높아야 비로소 연산 성능이 천장이 된다.3 그래서 GPU 튜닝은 “얼마나 계산을 빨리 하느냐”보다 “얼마나 메모리를 안 건드리느냐”의 싸움이다.
4. CPU-GPU 협업과 PCIe 병목[편집]
GPU는 독립 컴퓨터가 아니라 CPU(호스트)에 딸린 가속기(디바이스)다. 데이터는 호스트 메모리에서 PCIe 버스를 타고 GPU 메모리로 넘어와야 하는데, 이 PCIe 대역폭이 GPU 내부 대역폭보다 한참 느리다. 그래서 GPU 가속의 제1원칙은 데이터를 GPU에 올려두고 CPU로 자꾸 내리지 마라는 것이다.4
매 시간 스텝마다 결과를 CPU로 복사해 후처리하는 순진한 구현은, 정작 커널은 빨라도 전체는 PCIe 전송에 발목 잡혀 느려진다. 노하우는 시뮬레이션 전체 루프를 GPU 위에 상주시키고 통신을 최소화하는 것. 다중 GPU·다중 노드로 확장할 때는 병렬 컴퓨팅의 도메인 분할·MPI와 결합하며, 최신 시스템은 NVLink나 GPUDirect로 GPU끼리 CPU를 거치지 않고 직접 통신해 이 병목을 완화한다.
5. 시뮬레이션 가속 사례[편집]
GPU가 특히 위력을 발휘하는 분야는 데이터 병렬성이 자연스럽게 드러나는 문제들이다.
- 분자동역학: 원자마다 힘 계산이 독립적이라 병렬화가 자연스럽다. GROMACS·LAMMPS·AMBER 모두 GPU 가속으로 수십 배 빨라졌다. 레너드-존스 퍼텐셜 계산이 워프에 딱 맞는다.
- 격자 볼츠만 방법: 격자 위 국소 연산 위주라 격자 볼츠만 방법은 GPU와 궁합이 거의 완벽하다. CFD 대안으로 GPU LBM이 뜬 배경.
- 레이 트레이싱: 픽셀·광선마다 독립 계산이라 레이 트레이싱은 GPU의 고향이다. 근래에는 전용 RT 코어까지 박혔다.
- 밀도범함수이론: 밀도범함수이론의 대형 행렬 연산과 평면파 기저 FFT도 GPU로 옮겨가는 추세. VASP 등 상용 코드가 GPU 포트를 제공한다.
- 파티클 시스템·물리 엔진: 파티클 시스템과 물리 엔진(PhysX)은 애초에 GPU에서 태어났다.
물론 모든 문제가 GPU에 맞는 건 아니다. 희소행렬 기반 크리로프 부분공간법처럼 불규칙한 메모리 접근이 많은 알고리즘은 GPU에서 기대만큼 안 빨라지기도 한다. “GPU 붙이면 무조건 빨라진다”는 건 영업 멘트고, 실제로는 알고리즘의 데이터 병렬성과 메모리 접근 패턴이 모든 것을 결정한다.
6. 관련 문서[편집]
- 병렬 컴퓨팅
- 전산과학
- 격자 볼츠만 방법
- 분자동역학 · GROMACS · LAMMPS
- 레이 트레이싱
- 밀도범함수이론 · VASP
- 파티클 시스템 · 물리 엔진 · PhysX
- 희소행렬 · 크리로프 부분공간법
7. Footnotes[편집]
-
아이러니하게도 GPU를 과학계산의 왕좌에 앉힌 결정타는 게임도 시뮬레이션도 아닌 딥러닝이었다. 그래픽카드 회사가 어느 날 갑자기 세계 최고 시가총액 반도체 회사가 된 건, 게이머가 아니라 행렬곱 덕분이다. ↩
-
그래서 GPU 커널을 짤 때는 데이터를 미리 정렬해서 같은 분기끼리 모아두는 트릭을 쓴다. if문 하나 없애자고 정렬 커널을 하나 더 돌리는 게 이득인 세계. 상식과 반대로 도는 곳이다. ↩
-
루프라인 모델을 처음 보면 “내 커널이 왜 이렇게 느린지”가 한 장의 그래프로 설명된다. 대각선(대역폭 천장) 밑에 점이 찍히면 아무리 코드를 최적화해도 소용없고, 알고리즘 자체의 연산 강도를 높여야 한다는 뜻이다. ↩
-
초보 GPU 개발자의 90%가 이 함정에 빠진다. 커널은 100배 빨라졌는데 전체 프로그램은 2배밖에 안 빨라진 이유를 프로파일러로 찍어보면, 시간의 대부분이
cudaMemcpy에 잡혀 있다. PCIe는 언제나 범인이다. ↩