Post

GPU 프로그래밍 - 개요

GPU Programming

1. 개요

이전엔 GPU라고 하면 그래픽 작업이나 게임할때 필요한 부품이었다.
하지만 최근에 AI가 급속도로 발달하면서 GPU의 필요성이 매우 높아지고 있다.

이러한 GPU를 사용하기 위해서는 Python의 Pytorch 나 Tensorflow를 이용하여 코딩할 수도 있겠지만 여기서는 C와 C++을 이용한 코드를 이용하여 프로그램을 만들어보려 한다.

코딩을 해보기에 앞서 GPU에서 구동되는 코드를 알아보려면 먼저 어떤 문제에 대해 GPU를 사용할 수 있고 GPU의 성능은 어떻게 계산할 수 있으며 어떤 종류가 있고, 또 GPU가 어떻게 이루어져있는지 구조부터 알아봐야한다.

2. GPU와 메모리가 연결된 타입 종류

크게 두 가지로 나뉜다.
GPU 용으로 별도의 메모리가 있느냐 혹은 CPU가 사용하는 메모리를 공유하느냐이다.

img.png

  • Discrete (Dedicated) GPU
    별도의 메모리가 있는 형태가 우리가 흔히들 보는 그래픽 카드를 메인 보드에 결속해서 쓰는 형태이다.
    그래픽 카드는 별도의 GPU 메모리가 달려있으며 시스템 메모리와는 PCIe를 통해서 통신을 하게 된다.

  • Integrated GPU
    시스템 메모리를 공유하는 형태는 CPU에 내장 그래픽 카드가 있는 형태이거나 혹은 Jetson 보드와 같이 Edge한 Device에서 시스템 메모리를 공유하여 CPU와 GPU가 같이 사용하는 형태이다.

3. GPU를 이용할 수 있는 문제

어떤 데이터를 가지고 어떤 문제를 해결하는 방법 대해서 총 4가지로 분류 할 수 있다.

  • SISD (Single Instruction Single Data)
  • SIMD (Single Instruction Multiple Data)
  • MISD (Multiple Instruction Single Data)
  • MIMD (Multiple Instruction Multiple Data)

SISD는 한 개의 데이터에 대한 한 개의 명령이니 전통적인 프로그램이다.
SIMD는 다수의 데이터를 동일한 명령을 통해 처리해야하는 프로그램이다.
MISD는 한 개의 데이터를 다수의 명령어로 처리하는 것으로 한 개의 스트림을 다른 코어들이 처리하는 것으로 생각할 수 있다.
MIMD는 다수의 명령으로 각기 다른 데이터를 처리해야하는 프로그램으로 CPU의 다중 코어를 이용하여 멀티스레드를 하는 것으로 생각할 수 있다.

요컨대 각기 연산에 대해서 다른 연산에 의존성을 갖지 않고 동일한 형태의 연산을 한다면 SIMD 라고 볼수 있는 것이다. 여기서 GPU를 사용하는 문제는 SIMD를 가진 문제라고 할 수 있다. 예를 들어 보자.

  • 그래픽 연산이 대표적인 예시인데, 다수의 픽셀에 대해서 동일한 연산을 하는 것으로 전형적인 SIMD 연산이다.
  • 행렬 연산 역시 SIMD 연산이다. 각각의 원소들이 다른 원소에 대해 의존성을 갖고 있지 않기 때문에 SIMD를 가진 문제로 볼 수 있다.

최근 각광받는 AI 역시 가중치와 편향을 계산할때 대략의 벡터에 대해 부동 소수점 연산이 필요하므로 SIMD를 가진 문제이고 때문에 GPU로 처리할 수 있는 문제인 것이다.

※ 사실 GPU는 SIMT를 사용한다.

위에서 GPU는 SIMD라고 해놓고 뭔 소리냐고 할 수 있는데, 설명의 용이성을 위해서 SIMD라고 했다. 기본적으로 SIMD 문제는 SIMT로 풀수있다. SIMT가 뭐냐면 Single Instruction Multiple Thread의 약자로 SIMD에서 파생된 형태로 볼 수 있다. 다만 SIMD와의 차이점은 각 스레드가 고유한 논리적 제어 흐름을 가지며 분기할 수 있다는 점이다.
이 부분에 대해서는 차후 Branch divergence (분기 분할)에서 좀 더 자세히 설명할 것이다.

4. GPU 성능 척도

흔히들 GPU 성능을 나타낼때 FLOPS(FLoating point Operations Per Second)라는 단위를 많이 사용한다.
이는 초당 부동소수점 연산을 몇번이나 하는가에 대한 것이다.

관련해서 정보를 찾아보면 FLOPS와 FLOPs 이 두 개에 대해서 나올텐데 이 두 개는 엄연히 다른 지표이다. FLOPs(FLoating point OPerations)는 부동소수점 연산을 뜻하는 것으로 사칙연산을 포함해서 root, log, exponential 등의 연산도 포함하여 1회로 취급한다.
이 FLOPs가 초당 몇번이 가능한지가 FLOPS 되겠다.

5. NVIDIA GPU 종류

가장 일반적으로 많이 사용하는 NVIDIA GPU의 종류를 살펴보겠다.
NVIDIA GPU의 종류를 본다면 뭔가 많다. 일단 아래의 표를 보도록 하자

GenerationCompute CapabilityGeForce(Gaming)Tesla(HPC)Quadro(Workstation)Chipset Codes
Tesla (2007)1.0~1.3GTS 8800C1060FX 5800G80/92/GT200
Fermi (2010)2.0~2.1GTX 480/580C2070Quadro 4000GF100/102/107/110
Kepler (2012)3.0~3.7GTX 680/780K40/K80K4000GK104/110/210
Maxwell (2014)5.0~5.3GTX 980M60/M40M6000GM200/204/206
Pascal (2016)6.0~6.2GTX 1080P100/P40P6000/100GP100/104/106
Volta (2017)7.0~7.2TITAN VV100GV 100GV100
Turing (2018)7.5RTX 2080T4RTX 8000TU102/104/106
Ampere (2020)8.0~8.7RTX 3090A100A6000GA100/102/104/106
Ada (2022)8.9RTX 4090L40/L20RTX 6000 AdaAD102/104/106
Hopper (2022)9.0H100/200GH100

일단은 크게 세 부류로 나뉜다. 게이밍을 위한 Geforce 시리즈, 슈퍼 컴퓨터를 위한 Tesla 시리즈(그래픽 기능이 빠져있다), 수퍼컴퓨터 만큼은 아니지만 더 높은 성능을 가진 워크스테이션을 위한 Quadro이다.
Quadro의 경우에는 엄청 성능의 차이는 크지 않지만 훨씬 안정적이고 bus 대역폭도 크다.

이 세 종류에서 각각의 세대(Generation)마다 별도의 코드명이 붙어있다. 사실 여기서 중요한 건 Compute Capability와 Chipset Codes이다.

Chipset Code는 Nvidia와 AMD의 그래픽 처리 장치(GPU)를 식별하는 데 사용된다 그리고 Compute Capability는 컴퓨터 기능 묶음이라고 볼수 있는데 해당 번호를 지원하면 대상 번호에 속한 모든 기능을 지원하는 형태이다. 실질적인 스펙에 대해서는 아래와 같다.

참고문헌

원문 참고문헌

  • Gerassimos Barlas, Multicore and GPU Programming – An Integrated Approach, Elsevier Inc. (Morgan Kaufmann), 2015, ISBN 978-0-12-417137-4.
This post is licensed under CC BY 4.0 by the author.