Level 8: GPU 프로그래밍 (CUDA 기초)

Level 8

GPU와 병렬 컴퓨팅

왜 AI에 GPU가 필요한가, CPU vs GPU, SIMD 개념

40분
GPU와 병렬 컴퓨팅 강의 영상
강의 영상 보기 (새 탭에서 재생)YouTube

📓Google Colab에서 실습하기

이 레슨은 PyTorch/GPU가 필요합니다. 노트북을 다운로드 후 Google Colab에서 열어주세요.

학습 내용

GPU와 병렬 컴퓨팅

학습 목표

이 레슨을 완료하면:

  • GPU가 왜 AI 분야에서 핵심 장비가 되었는지 설명할 수 있다
  • CPU와 GPU의 설계 철학 차이를 비유로 설명할 수 있다
  • SIMD(Single Instruction Multiple Data) 개념을 이해한다
  • 반복문 vs 벡터 연산의 속도 차이를 직접 확인한다

핵심 메시지

"CPU는 천재 교수 1명, GPU는 성실한 학생 1000명이다." 복잡한 증명 문제는 교수가 빠르지만, 시험지 1만 장 채점은 학생 1000명이 압도적으로 빠릅니다.


비유로 시작하기: 교수 vs 학생

일상에서 두 가지 상황을 상상해 봅시다.

상황 1: 어려운 수학 증명 복잡한 수학 문제를 풀어야 합니다. 이 문제는 앞 단계의 결과를 알아야 다음 단계를 진행할 수 있습니다. 뛰어난 교수 1명이 혼자 푸는 것이 가장 빠릅니다. 학생 1000명이 모여봐야, 앞 단계 결과를 기다려야 하므로 더 빨라지지 않습니다.

상황 2: 시험지 1만 장 채점 객관식 시험지 1만 장을 채점해야 합니다. 각 시험지는 독립적이므로 누가 몇 번 시험지를 채점하든 상관없습니다. 교수 1명이 혼자 하면 며칠이 걸리지만, 학생 1000명이 나누면 10장씩만 채점하면 됩니다.

상황교수 1명 (CPU)학생 1000명 (GPU)
복잡한 증명 문제빠름느림 (기다려야 함)
시험지 1만 장 채점매우 느림매우 빠름

이것이 바로 CPU와 GPU의 핵심 차이입니다.


CPU란 무엇인가

CPU(Central Processing Unit)는 컴퓨터의 두뇌 역할을 합니다. 운영체제, 웹 브라우저, 문서 편집기 등은 모두 CPU가 처리합니다.

CPU의 설계 철학: "적은 수의 강력한 코어"

CPU는 복잡한 작업을 빠르게 순차 처리하도록 설계되었습니다.

특징설명
코어 수보통 4~16개 (고급형은 64개까지)
각 코어의 능력매우 강력 (복잡한 명령 처리 가능)
클럭 속도높음 (3~5 GHz)
분기 예측있음 (if문 같은 조건 분기를 빠르게 처리)
캐시 메모리대용량 L1/L2/L3 캐시

CPU의 각 코어는 그 자체로 매우 똑똑합니다. 복잡한 조건 분기, 재귀 호출, 다양한 명령어를 자유자재로 처리할 수 있습니다. 하지만 코어 수가 적기 때문에, 같은 작업을 만 번 반복해야 할 때는 하나씩 순서대로 처리해야 합니다.

CPU가 잘하는 작업들

  • 운영체제 관리 (프로세스 스케줄링, 파일 시스템)
  • 웹 브라우저 (HTML 파싱, JavaScript 실행)
  • 복잡한 알고리즘 (정렬, 그래프 탐색, 재귀)
  • 앞 단계 결과에 다음 단계가 의존하는 순차적 계산

GPU란 무엇인가

GPU(Graphics Processing Unit)는 원래 화면에 그래픽을 그리기 위해 만들어졌습니다. 화면의 수백만 픽셀을 동시에 처리해야 하므로, 자연스럽게 대규모 병렬 처리 구조로 설계되었습니다.

GPU의 설계 철학: "많은 수의 작은 코어"

특징설명
코어 수수천 개 (NVIDIA RTX 4090: 16,384개)
각 코어의 능력단순 (간단한 산술 연산에 특화)
클럭 속도CPU보다 낮음 (1~2 GHz)
분기 예측없음 (조건 분기에 약함)
메모리 대역폭매우 높음 (초당 수백 GB~수 TB)

GPU의 각 코어는 CPU 코어보다 훨씬 단순합니다. 하지만 수천 개의 코어가 동시에 작동하므로, 단순한 계산을 대량으로 처리할 때 압도적인 성능을 보여줍니다.

GPU가 잘하는 작업들

  • 행렬/벡터 연산 (각 원소가 독립적)
  • 이미지/영상 처리 (각 픽셀이 독립적)
  • 딥러닝 학습 및 추론 (대규모 행렬 곱셈)
  • 물리 시뮬레이션 (각 입자가 독립적)

CPU vs GPU 한눈에 비교

항목CPUGPU
비유천재 교수 1명성실한 학생 1000명
코어 수적음 (4~64개)많음 (수천~만 개)
코어 성능각각 매우 강력각각 단순
처리 방식순차적 (Sequential)병렬적 (Parallel)
적합한 작업복잡한 논리, 조건 분기단순 연산의 대량 반복
클럭 속도높음 (3~5 GHz)낮음 (1~2 GHz)
메모리 대역폭~100 GB/s~1,000 GB/s 이상

왜 AI에 GPU가 필요한가

딥러닝의 핵심 연산은 행렬 곱셈입니다. 신경망에서 일어나는 일을 단순화하면 이렇습니다.

text
# 신경망의 순전파 (한 층의 계산) output = activation(W @ input + b) # W: 가중치 행렬 (예: 1000 x 1000) # input: 입력 벡터 # @: 행렬 곱셈 # 이 과정에서 수백만 번의 곱셈과 덧셈이 필요합니다

행렬 곱셈이 왜 GPU에 적합할까요? 1000 x 1000 크기의 행렬 두 개를 곱하면, 결과 행렬의 각 원소 계산은 서로 독립적입니다. 즉, 1,000,000개의 독립적인 내적 연산이 존재합니다. 이것은 "시험지 채점" 상황과 똑같습니다.

작업CPU (Intel i9)GPU (RTX 4090)GPU가 몇 배 빠른가
4096 x 4096 행렬 곱셈~45초~0.1초약 450배
ResNet-50 학습 1 epoch~180분~3분약 60배
GPT-2 추론 (배치 32)~12초~0.2초약 60배

이런 엄청난 차이 때문에, 현대 AI 연구와 산업에서 GPU는 필수 장비가 되었습니다.


SIMD: 하나의 명령으로 여러 데이터를 처리하기

GPU의 병렬 처리를 이해하는 핵심 개념이 **SIMD(Single Instruction Multiple Data)**입니다. 말 그대로, 하나의 명령어(Instruction)로 여러 개의 데이터(Data)를 동시에 처리하는 방식입니다.

비유: 체육 선생님의 호루라기

체육 시간에 선생님이 "앞으로 나란히!" 하고 호루라기를 불면, 학생 30명이 동시에 같은 동작을 합니다. 하지만 각자 서 있는 위치는 다릅니다.

  • 하나의 명령 = "앞으로 나란히!" (호루라기)
  • 여러 데이터 = 각 학생의 현재 위치
  • 동시 실행 = 모든 학생이 한꺼번에 같은 동작 수행

일반 순차 처리 vs SIMD 비교

text
[순차 처리 - CPU 스타일] 시간 1: A[0] + B[0] = C[0] 시간 2: A[1] + B[1] = C[1] 시간 3: A[2] + B[2] = C[2] 시간 4: A[3] + B[3] = C[3] => 4단계 필요 [SIMD 처리 - GPU 스타일] 시간 1: A[0]+B[0]=C[0], A[1]+B[1]=C[1], A[2]+B[2]=C[2], A[3]+B[3]=C[3] => 1단계에 모두 처리!

NVIDIA GPU는 이 SIMD 개념을 확장한 SIMT(Single Instruction Multiple Threads) 아키텍처를 사용합니다. 32개의 스레드를 하나의 Warp로 묶어서 같은 명령어를 동시에 실행합니다.

text
[NVIDIA GPU의 Warp 실행] Warp = 32개의 스레드가 한 묶음 스레드 0: A[0] + B[0] = C[0] 스레드 1: A[1] + B[1] = C[1] 스레드 2: A[2] + B[2] = C[2] ... 스레드 31: A[31] + B[31] = C[31] => 32개의 덧셈이 한 번에 동시 실행!

실행해보기: 반복문 vs 벡터 연산 속도 비교

직접 코드를 실행해서, 순차 처리(반복문)와 병렬 처리(벡터 연산)의 속도 차이를 체감해 봅시다. NumPy의 벡터 연산은 내부적으로 SIMD 명령어를 활용합니다.

python
import numpy as np import time # 1000만 개의 숫자로 테스트 n = 10_000_000 a = np.random.rand(n) b = np.random.rand(n) # 방법 1: Python 반복문 (순차 처리, CPU 스타일) start = time.time() c_loop = np.zeros(n) for i in range(n): c_loop[i] = a[i] + b[i] loop_time = time.time() - start # 방법 2: NumPy 벡터 연산 (병렬 처리, SIMD 활용) start = time.time() c_vec = a + b vec_time = time.time() - start # 결과 비교 print("=" * 50) print("반복문 vs 벡터 연산 속도 비교") print("=" * 50) print(f"데이터 크기: {n:,}개") print(f"반복문 처리 시간: {loop_time:.4f}초") print(f"벡터 연산 시간: {vec_time:.6f}초") print(f"속도 차이: 벡터 연산이 {loop_time/vec_time:.1f}배 빠름") print() print("결과가 같은지 확인:", np.allclose(c_loop, c_vec))

위 코드를 실행하면 벡터 연산이 수십~수백 배 빠른 것을 확인할 수 있습니다. Python 반복문은 한 번에 하나씩 처리하지만, NumPy는 내부적으로 C 코드와 SIMD 명령어를 활용해 여러 데이터를 동시에 처리하기 때문입니다.

실제 GPU는 이것보다 훨씬 더 많은 코어를 사용하므로, 속도 차이가 수백~수천 배까지 벌어집니다.


실행해보기: 행렬 곱셈 크기별 속도 차이

행렬이 커질수록 병렬 처리의 이점이 더 커지는 것을 확인해 봅시다.

python
import numpy as np import time sizes = [100, 500, 1000, 2000] print("행렬 크기별 곱셈 시간 비교") print("=" * 55) print(f"{'크기':>10} | {'NumPy 시간':>12} | {'연산 수':>15}") print("-" * 55) for size in sizes: A = np.random.rand(size, size) B = np.random.rand(size, size) start = time.time() C = A @ B elapsed = time.time() - start ops = size * size * size * 2 print(f"{size}x{size:>4} | {elapsed:>10.4f}초 | {ops:>13,}회") print() print("행렬이 커질수록 연산 수가 급격히 증가합니다.") print("이것이 GPU가 AI에서 필수인 이유입니다!")

메모리 대역폭: 또 하나의 핵심 차이

GPU가 CPU보다 빠른 이유는 코어 수만이 아닙니다. 메모리 대역폭(단위 시간당 읽고 쓸 수 있는 데이터 양)도 GPU가 압도적으로 높습니다.

비유: 도서관 통로의 너비

CPU의 메모리 접근은 좁은 복도(2차선 도로)를 통하는 것과 같고, GPU의 메모리 접근은 넓은 고속도로(64차선 도로)를 통하는 것과 같습니다. 아무리 빠른 차(코어)가 많아도, 도로가 좁으면 데이터를 가져오는 데 병목이 생깁니다.

메모리 유형대역폭비유
DDR4 (일반 PC, CPU)~50 GB/s2차선 도로
DDR5 (최신 PC, CPU)~100 GB/s4차선 도로
GDDR6 (게이밍 GPU)~500 GB/s16차선 고속도로
HBM2e (데이터센터 GPU)~2,000 GB/s64차선 초고속도로

딥러닝은 대량의 데이터를 메모리에서 읽고, 연산하고, 결과를 저장하는 과정의 반복입니다. 따라서 메모리 대역폭이 높은 GPU가 딥러닝에 훨씬 유리합니다.


CPU와 GPU는 경쟁이 아니라 협력

현대 AI 시스템에서 CPU와 GPU는 서로 다른 역할을 맡아 함께 일합니다.

역할담당이유
데이터 로드 (파일 읽기)CPU파일 시스템 접근, 조건 분기 많음
데이터 전처리 (변환, 정규화)CPU다양한 로직 처리 필요
학습 루프 제어CPU에포크 관리, 로깅, 체크포인트
순전파/역전파 연산GPU대규모 행렬 곱셈
가중치 업데이트GPU수백만 파라미터 동시 업데이트
결과 저장 및 로깅CPU파일 시스템, 네트워크 접근
실제 딥러닝 학습의 흐름: CPU: 데이터 로드 -> 전처리 -> GPU로 전송 -----> 결과 수신 -> 로그 기록 | | GPU: 데이터 수신 -> 연산 -> 결과 반환 (순전파/역전파/업데이트)

실행해보기: 독립적 연산의 위력

병렬 처리가 빛나는 핵심 조건은 각 연산이 서로 독립적이어야 한다는 것입니다. 아래 코드로 독립적 연산 vs 의존적 연산의 차이를 확인해 봅시다.

python
import numpy as np import time n = 5_000_000 # 독립적 연산: 각 원소를 개별적으로 변환 (GPU에 적합) data = np.random.rand(n) start = time.time() result_independent = np.sin(data) * 2 + np.cos(data) independent_time = time.time() - start # 의존적 연산: 앞 결과에 다음이 의존 (CPU에 적합) start = time.time() result_dependent = np.zeros(n) result_dependent[0] = data[0] for i in range(1, min(n, 50000)): result_dependent[i] = result_dependent[i-1] * 0.99 + data[i] * 0.01 dependent_time = time.time() - start print("독립적 연산 vs 의존적 연산") print("=" * 50) print(f"독립적 연산 ({n:,}개): {independent_time:.4f}초") print(f"의존적 연산 (50,000개): {dependent_time:.4f}초") print() print("독립적 연산은 100배 많은 데이터를 처리하고도") print("비슷하거나 더 빠릅니다!") print() print("핵심 교훈:") print("- 독립적 연산 -> 병렬화 가능 -> GPU가 유리") print("- 의존적 연산 -> 순차 처리 필수 -> CPU가 유리")

핵심 요약

개념설명비유
CPU적은 수의 강력한 코어로 순차 처리천재 교수 1명
GPU수천 개의 작은 코어로 병렬 처리성실한 학생 1000명
SIMD하나의 명령으로 여러 데이터 동시 처리호루라기 한 번에 전체 학생 동작
메모리 대역폭단위 시간당 데이터 전송량도로의 차선 수
병렬 처리 조건각 연산이 서로 독립적이어야 함시험지 채점 (각 장이 독립적)
AI와 GPU행렬 곱셈 = 독립적 연산의 덩어리시험지 1만 장 채점과 같은 구조

학습 체크리스트

  • CPU와 GPU의 설계 철학 차이를 비유로 설명할 수 있다
  • SIMD 개념을 "호루라기" 비유로 설명할 수 있다
  • 딥러닝에서 GPU가 필수인 이유를 행렬 곱셈과 연결할 수 있다
  • 반복문 vs 벡터 연산 속도 차이를 직접 확인했다
  • 독립적 연산 vs 의존적 연산의 차이를 이해한다

레슨 정보

레벨
Level 8: GPU 프로그래밍 (CUDA 기초)
예상 소요 시간
40분
참고 영상
YouTube 링크

💡실습 환경 안내

이 레벨은 PyTorch/GPU가 필요하여 Google Colab 사용을 권장합니다.

Colab은 무료 GPU를 제공하여 PyTorch, CNN, Transformer 등을 실행할 수 있습니다.