GPU 프로그래밍을 공부하기에 앞서,
GPU 프로그래밍이 필요한 이유를 이해하기 위해서는
GPGPU(General-Purpose GPU)의 개념을 이해해야 한다.
그리고 GPGPU를 이야기하려면 먼저
그래픽 처리 장치(Graphics Processing Unit, GPU)가 무엇인지 알아야 한다.
그래픽카드라는 이름에서도 알 수 있듯 GPU는 컴퓨터 그래픽스 연산에 특화된 연산 장치이다.
그래픽스 연산은 화면에 그림을 그리는 연산이라 이해하면 된다.
컴퓨터 내부에서는 물체나 공간에 대한 정보 또는
이미지 정보가 인간이 눈으로 볼 수 없는 데이터 형태로 저장된다.
따라서 이를 눈으로 보기위해 데이터를 해석해서 화면에 그리는 작업이 필요하다.
이러한 그래픽 연산을 위해 개발된 연산 장치가 바로 그래픽 카드, GPU이다.
그렇다면 우리가 컴퓨터에서 사용하는 어플리케이션 중 어떤 것이 그림을 가장 열심히 그릴까?
아마 게임일 것이다.
최근 게임들은 매우 높은 품질의 그래픽 사양을 지니며,
많은 사람이 더 좋은 GPU를 마련하려는 이유가 바로 게임 때문이기도 하다.
실제로 컴퓨터 게임이 GPU의 발전에 큰 영향을 주었다고 말할 수 있다.
그런데 또 하나, GPU 핫한 이유중 하나는
딥러닝과 같은 인공지능 연구를 위한 필수 연산 장치가 되었기 때문이다.
이처럼 GPU는 그래픽 연산이 많이 필요한 게임이나 가상현실 분야뿐만 아니라
인공지능과 블록체인 분야에서도 중요한 연산 자원으로 폭넓게 사용되고 있다.
즉, GPU는 CPU대비 매우 높은 처리 능력을 가진다.
GPGPU를 통해 다양한 분야에서
많은 시간이 걸리는 연산을 빠르게 처리할 수 있다는 점이 크게 주목받는 이유다.
그리고 이는 우리가 GPU 프로그래밍 공부를 해야하는 이유이기도 하다.
병렬 처리의 개념 및 필요성
병렬의 반대말은 직렬이다.
직렬은 한 줄을 병렬은 여러 줄을 의미한다.
즉 직렬 처리는 한 명이 한 줄의 일을 처리하는 것이고,
병렬 처리는 여러 명이 여러 줄의 일을 동시에 처리하는 것을 말한다.
컴퓨터 시스템에서 일을 처리하는 주체는 CPU의 코어와 같은 연산 유닛으로,
병렬 처리는 여러 개의 연산 자원이 동시에 일을 처리하는 것을 말한다.
병렬 처리의 또 하나 중요한 정의는 하나의 큰 문제를 여러 연산 장치가 나누어 처리하는 것이다.
정리하면 병렬 처리는 하나의 문제를 여러 개의 연산 자원을 활용해서 해결하는 것으로 정의할 수 있다.
병렬 처리는 여러 문제 또는 작업을
여러 개의 연산 장치가 하나씩 맡아 처리하는 병렬 처리와 구분된다.
예를 들어,
하나의 게임을 여러 개의 CPU 코어를 사용해서 성능을 높이는 것이 병렬 처리이고
여러 개의 프로그램을 각각의 CPU 코어에서 실행한다면 병행 처리라고 할 수 있다.
병렬 처리의 필요성
- 사용자의 요구
- 컴퓨터 아키텍처의 발전 경향
- 병렬 처리 프로그래밍의 필요성
1. 사용자의 요구
컴퓨터 또는 연산 장치를 사용하는 사용자의 요구는 간단하다.
원하는 작업을 빠르고, 정확하게 처리하는 것이다.
과거에는 이러한 고성능 컴퓨팅이 요구되는 분야가 군사 분야 및 기상 분야와 같은
일부 과학 분야로 제한적이었다.
그리고 주로 연산 코어의 클럭 주파수를 높이는 방법,
즉 단일 코어 CPU의 성능을 높이는 방법으로 고성능에 대한 이러한 요구에 대응했다.
하지만 현재 컴퓨터는 우리 생활 곳곳에서 폭넓게 사용되고 있으며,
게임 및 빅 데이터 처리 등 넓은 분야에서 빠르고 정확한 고성능 컴퓨팅이 요구된다.
그리고 단일 코어의 성능을 높이기만 해서는 이러한 요구를 만족시키기 어려워 진 것이다.
사용자의 요구를 충족하기 위해서는 단일 연산 장치만 사용하기보단,
많은 수의 연산 코어 및 다수의 연산 장치를 동시에 사용하는 병렬 처리가 필요하다.
그리고 병렬 처리에서 사용자가 기대하는 것은
P개의 연산 자원을 사용해서
P배의 성능을 향상시킬 수 있는 효율적인 병렬 처리 프로그램이라고 할 수 있다.
다만 10명이 같이 일한다고 10배 빨라지지 않는 것처럼
P개의 연산 장치로 P개의 성능 향상을 얻기란 쉽지 않다.
잘 기억나지 않지만 예전에 책에서 보길
한 개당 추가적으로 1.3~5배 정도 향상 된다고 한다더라.
2. 컴퓨팅 아키텍처의 발전 경향
연산 장치 성능을 향상시키는 가장 기본적인 방법은
하나의 연산 코어에 트랜지스터를 많이 집어넣는 것이다.
실제로 2000년대 초반까지는 많은 연산 장치에서 이러한 전략을 사용하여
고집적 프로세서들이 높은 성능을 달성하는 데 성공하였다.
하지만 이러한 성능 전략에는 한계가 왔고,
많은 트랜지스터를 사용하면 많은 전력을 소모하게 된다.
전기가 흐르면 열이 발생하게 된다.
따라서 많은 트랜지스터의 사용은 높은 발열로 이어진다.
발열이 높아도 그냥 사용하면 되지 않을까 싶을 수 있는데
문제는 좁은 공간에서 많은 열이 발생하면 연산 오류를 발생시킬수 있다는 점이다.

이러한 한계를 극복하고자 연산 장치 제조사들은
하나의 연산 코어에 대한 집적도를 높이면서
하나의 칩에 여러 개의 연산 코어를 담는 전략을 선택하게 된다.
최근의 CPU들은 대부분 수 개에서 많게는 수십 개의 연산 코어를 가지고 있다.
또한 고성능 연산 장치로 주목을 받고 있는 GPU는
수백에서 많게는 수천 개의 연산 코어를 하나의 CPU에 담고 있다.
이러한 컴퓨터 아키텍처의 발전 경향은 CPU와 GPU뿐만 아니라
대부분의 연산 장치에서 채용되고 있다.
대표적인 병렬 컴퓨팅 아키텍처들이다.
다중 코어 CPU와 GPU로 구성된 PC와 게임 콘솔들도 넓은 범위에서
병렬 컴퓨팅 아키텍처로 분류될 수 있으며,
여러 개의 컴퓨터를 클러스터 형태로 묶는
슈퍼컴퓨터도 병렬 처리 아키텍처 중 하나이다.
나아가 여러 개의 컴퓨팅 클러스터를 묶은 형태인
구글 데이터 센터도 병렬 처리 아키텍처로 볼 수 있다.
이러한 병렬 컴퓨팅 환경을 효율적으로 활용하려면
여러 개의 연산 자원을 동시에 사용하는 병렬 처리가 피룡하다.
즉, 점점 더 병렬화되어 가는 컴퓨팅 환경에서
고성능에 대한 사용자의 요구를 만족시키기 위해 병렬 처리가 필요하다.
3. 병렬 처리 프로그래밍의 필요성
지금까지 병렬 처리 개념과 필요성을 살펴보았다.
그렇다면 이러한 병렬 컴퓨팅 장치들을 활용하려면
반드시 GPU 프로그래밍과 같은 병렬 처리 프로그래밍을 배워야 할까?
꼭 그렇지는 않다.
일부 컴파일러의 경우 직렬 처리 코드 일부를 병렬 처리 코드로 바꾸는 기능이 있으며,
간단한 지시어를 추가하는 것만으로도
GPU를 사용한 병렬 처리가 가능하도록
도와주는 라이버러리나 도구가 존재하단다.
하지만 이러한 자동 병렬화 기능은 일부 코드에
간단한 병렬 처리 방법을 적용하는 낮은 수준의 병렬화만 지원한다.
즉, 자동 병렬화 도구들은 활용 가능한 코드 범위가 제한적이며,
효율적인 병렬 처리 장치 활용 여부가 보장되지 않는다.
실제로 병렬화 결과 성능이 더 낮아지거나,
잘못된 연산 결과가 나오는 경우도 많다.