GPU와 CUDA를 활용한 딥러닝 환경 구축

GPU 기초부터 CUDA 설치까지 완벽 가이드

딥러닝을 위한 GPU와 CUDA의 개념을 이해하고, 실제 환경 구축 방법을 알아본다. NVIDIA GPU를 활용한 딥러닝 가속화 환경을 단계별로 설정하는 방법을 다룬다.

Engineering
Infrastructure
저자

Kwangmin Kim

공개

2023년 05월 01일

1 GPU란 무엇인가?

1.1 CPU의 정의

  • CPU(Central Processing Unit)는 컴퓨터의 중앙 처리 장치
  • 모든 연산과 제어를 담당하는 핵심 부품이다.
  • 복잡한 명령어를 순차적으로 처리하는 데 최적화되어 있으며, 일반적으로 4-32개의 고성능 코어를 가지고 있다.
  • 그냥 컴퓨터의 두뇌라고 생각하면 된다.
  • 컴퓨터의 일반적이고 기본적인 모든 연산은 CPU가 처리한다.

1.1.1 CPU (Central Processing Unit)

  • 설계 철학: 복잡한 명령어를 빠르게 순차 처리
  • 코어 구조: 적은 수의 강력한 코어 (4-32개)
  • 캐시 메모리: 대용량 캐시로 지연 시간 최소화
  • 분기 예측: 복잡한 제어 흐름 처리에 최적화

1.2 GPU의 정의

  • GPU(Graphics Processing Unit)는 원래 그래픽 처리를 위해 설계된 전용 프로세서이다.
  • 하지만 현재는 딥러닝과 같은 병렬 연산이 필요한 작업에서 CPU보다 훨씬 뛰어난 성능을 보여준다.

1.2.1 GPU (Graphics Processing Unit)

  • 설계 철학: 단순한 연산을 대량으로 병렬 처리
  • 코어 구조: 많은 수의 단순한 코어 (수백-수천개)
  • 메모리: 높은 대역폭의 전용 메모리(VRAM)
  • SIMD 구조: 같은 명령을 여러 데이터에 동시 적용

1.3 딥러닝에서 GPU를 사용하는 이유

1.3.1 행렬 연산의 병렬성

딥러닝의 핵심인 행렬 곱셈은 본질적으로 병렬 처리가 가능:

\[ C_{ij} = \sum_{k=1}^{n} A_{ik} \times B_{kj} \]

\(C_{ij}\) 원소는 독립적으로 계산 가능하므로 GPU의 수천 개 코어가 동시에 처리할 수 있다.

1.3.2 대용량 데이터 처리

  • 배치 처리: GPU의 수천 개 코어가 동시에 연산 수행, 특히 합성곱(Convolution) 연산에서 큰 성능 향상
    • 합성곱: 이미지나 신호 처리에서 사용되는 수학적 연산으로, 필터(커널)를 입력 데이터 위에서 슬라이딩하며 각 위치에서 요소별 곱셈과 합을 수행하는 연산. CNN에서 특징 추출의 핵심 연산이며, 각 필터 연산이 독립적이어서 GPU의 병렬 처리에 매우 적합함
  • 높은 메모리 대역폭: CPU 대비 10-20배 빠른 메모리 접근
  • 병렬 데이터 로딩: 여러 데이터를 동시에 GPU 메모리로 전송
  • 전용 메모리(VRAM): GPU 전용 메모리로 빠른 데이터 접근, CPU-GPU 간 데이터 전송 최소화

1.3.3 성능 비교

특성 CPU GPU
코어 수 적음 (4-32개) 많음 (수백-수천개)
연산 방식 순차 처리 병렬 처리
메모리 대역폭 낮음 높음
딥러닝 성능 느림 빠름
전력 효율성 높음 낮음

2 CUDA란 무엇인가?

2.1 CUDA의 정의

  • CUDA(Compute Unified Device Architecture)는 NVIDIA에서 개발한 병렬 컴퓨팅 플랫폼 및 프로그래밍 모델
  • 딥러닝 모델을 가속화하기 위해 사용되는 프로그래밍 모델

2.2 CUDA의 핵심 개념

2.2.1 병렬 프로그래밍 모델

# CPU 코드 (순차 처리)  
for i in range(1000000):  
    result[i] = a[i] + b[i]  

# GPU 코드 개념 (병렬 처리)  
# 1000000개의 스레드가 동시에 실행  

2.2.2 메모리 계층 구조

  • 스레드(Thread): GPU에서 실제 연산을 수행하는 최소 실행 단위
    • CPU의 스레드와 달리 GPU 스레드는 매우 가벼움 (컨텍스트 스위칭 비용이 거의 없음)
    • 수천 개의 스레드가 동시에 실행되어 병렬 처리 수행
    • 각 스레드는 고유한 ID를 가지며, 이를 통해 처리할 데이터를 구분
  • 글로벌 메모리: 모든 스레드가 접근 가능, 느림
  • 공유 메모리: 블록 내 스레드 공유, 빠름
  • 레지스터: 개별 스레드 전용, 가장 빠름

2.2.3 스레드 계층 구조

Grid (전체 작업)  
├── Block 1  
│   ├── Thread 1  
│   ├── Thread 2  
│   └── ...  
├── Block 2  
└── ...  

3 GPU와 CUDA의 관계

3.1 GPU (하드웨어)

  • 물리적 장치: 실제 그래픽 카드에 탑재된 프로세서
  • 병렬 처리 능력: 수천 개의 코어로 동시 연산 수행
  • 하드웨어 자원: 메모리, 연산 유닛 등 물리적 자원 제공

3.2 CUDA (소프트웨어 플랫폼)

  • 프로그래밍 도구: GPU의 병렬 처리 능력을 활용할 수 있게 해주는 소프트웨어
  • 개발 환경: GPU 프로그래밍을 위한 컴파일러, 라이브러리, API 제공
  • NVIDIA 전용: NVIDIA GPU에서만 동작

3.3 딥러닝에서의 역할

  1. GPU: 실제 행렬 연산을 병렬로 처리
  2. CUDA: PyTorch, TensorFlow 등이 GPU를 쉽게 사용할 수 있도록 지원
  • GPU는 하드웨어이고 CUDA는 그 하드웨어를 활용하기 위한 소프트웨어 플랫폼
  • CUDA가 있어야 딥러닝 프레임워크들이 GPU의 성능을 제대로 활용할 수 있다.

4 딥러닝에서 GPU 활용

4.1 주요 딥러닝 프레임워크의 GPU 지원

4.1.1 PyTorch

import torch  

# GPU 사용 가능 여부 확인  
print(torch.cuda.is_available())  

# 텐서를 GPU로 이동  
tensor = torch.randn(1000, 1000)  
tensor_gpu = tensor.cuda()  

# 모델을 GPU로 이동  
model = MyModel()  
model = model.cuda()  

4.1.2 TensorFlow

import tensorflow as tf  

# GPU 사용 가능 여부 확인  
print(tf.config.list_physical_devices('GPU'))  

# GPU 메모리 증가 설정  
gpus = tf.config.experimental.list_physical_devices('GPU')  
if gpus:  
    tf.config.experimental.set_memory_growth(gpus[0], True)  

5 GPU 환경 구축 가이드

5.1 하드웨어 요구사항 확인

5.1.1 GPU 확인 방법

# Windows  
nvidia-smi  

# Linux  
lspci | grep -i nvidia  
  • 이 명령어가 실행되면 GPU 정보와 CUDA 버전이 표시된다.
  • 만약 “nvidia-smi is not recognized” 오류가 나면 NVIDIA 드라이버를 설치해야 한다.
# 나의 예시  
+-----------------------------------------------------------------------------------------+  
| NVIDIA-SMI 561.19                 Driver Version: 561.19         CUDA Version: 12.6     |  
|-----------------------------------------+------------------------+----------------------+  
| GPU  Name                  Driver-Model | Bus-Id          Disp.A | Volatile Uncorr. ECC |  
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |  
|                                         |                        |               MIG M. |  
|=========================================+========================+======================|  
|   0  NVIDIA GeForce RTX 2070 ...  WDDM  |   00000000:01:00.0  On |                  N/A |  
| N/A   53C    P8             10W /   89W |     727MiB /   8192MiB |      5%      Default |  
|                                         |                        |                  N/A |  
+-----------------------------------------+------------------------+----------------------+  

+-----------------------------------------------------------------------------------------+  
| Processes:                                                                              |  
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |  
|        ID   ID                                                               Usage      |  
|=========================================================================================|  
|    0   N/A  N/A      2340    C+G   ...5n1h2txyewy\ShellExperienceHost.exe      N/A      |  
|    0   N/A  N/A     14556    C+G   C:\Windows\explorer.exe                     N/A      |  
|    0   N/A  N/A     15068    C+G   ...cal\Microsoft\OneDrive\OneDrive.exe      N/A      |  
|    0   N/A  N/A     19280    C+G   ....Search_cw5n1h2txyewy\SearchApp.exe      N/A      |  
|    0   N/A  N/A     20256    C+G   ..._v10z8vjag6ke6\OMENAudioControl.exe      N/A      |  
|    0   N/A  N/A     20340    C+G   ...CBS_cw5n1h2txyewy\TextInputHost.exe      N/A      |  
|    0   N/A  N/A     21916    C+G   ...ta\Local\Programs\cursor\Cursor.exe      N/A      |  
|    0   N/A  N/A     23780    C+G   ...on\137.0.3296.83\msedgewebview2.exe      N/A      |  
|    0   N/A  N/A     25400    C+G   ...812_x64__8wekyb3d8bbwe\ms-teams.exe      N/A      |  
|    0   N/A  N/A     26072    C+G   ...\HncUtils\Service\HncUpdateTray.exe      N/A      |  
|    0   N/A  N/A     26104    C+G   ...siveControlPanel\SystemSettings.exe      N/A      |  
|    0   N/A  N/A     26248    C+G   ....Search_cw5n1h2txyewy\SearchApp.exe      N/A      |  
|    0   N/A  N/A     29228    C+G   ...on\137.0.3296.83\msedgewebview2.exe      N/A      |  
|    0   N/A  N/A     31772    C+G   ...oogle\Chrome\Application\chrome.exe      N/A      |  
|    0   N/A  N/A     32572    C+G   ...812_x64__8wekyb3d8bbwe\ms-teams.exe      N/A      |  
|    0   N/A  N/A     35516    C+G   ...__8wekyb3d8bbwe\WindowsTerminal.exe      N/A      |  
|    0   N/A  N/A     35628    C+G   ...t.LockApp_cw5n1h2txyewy\LockApp.exe      N/A      |  
|    0   N/A  N/A     38204    C+G   ...crosoft\Edge\Application\msedge.exe      N/A      |  
|    0   N/A  N/A     40680    C+G   ...oogle\Chrome\Application\chrome.exe      N/A      |  
+-----------------------------------------------------------------------------------------+  
  • 모델: RTX 2070 (아마도 RTX 2070 Super로 보임)
  • VRAM: 8GB (8192MiB)
  • 현재 메모리 사용량: 727MB / 8192MB (약 9% 사용 중)
  • GPU 사용률: 5% (거의 유휴 상태)
  • 전력 소모: 10W / 89W (매우 낮음, 절전 모드)

5.1.2 권장 GPU 사양

  • 입문용: GTX 1660 Super (6GB VRAM)
    • 할 수 있는 것들:
      • 간단한 CNN 모델 (MNIST, CIFAR-10)
      • 작은 데이터셋으로 실습
      • 기본적인 PyTorch/TensorFlow 튜토리얼
      • 배치 크기 16-32 정도
    • 제한사항:
      • 큰 모델(ResNet-50, Transformer) 훈련 어려움
      • ImageNet 같은 대용량 데이터셋 처리 힘듦
      • 배치 크기를 작게 해야 함 (메모리 부족)
  • 중급용: RTX 3070 (8GB VRAM)
    • 할 수 있는 것들:
      • 중간 크기 모델 훈련 (ResNet-34, EfficientNet-B0)
      • 전이학습(Transfer Learning) 실험
      • 개인 프로젝트, 캐글 대회 참여
      • 배치 크기 32-64
    • 제한사항:
      • 매우 큰 모델(GPT, BERT Large) 훈련 어려움
      • 긴 시퀀스 처리 제한적
      • 상용 서비스 수준의 모델 훈련은 힘듦
  • 고급용: RTX 4090 (24GB VRAM)
    • 할 수 있는 것들:
      • 대형 모델 훈련 (BERT, GPT-2 Small)
      • 고해상도 이미지 처리
      • 복잡한 연구 실험
      • 배치 크기 128-256
      • 상용 서비스 프로토타입
      • 가능한 실험:
        • 대용량 데이터셋 처리
        • 복잡한 모델 훈련
        • 최신 모델 실험
        • 빠른 추론 최적화
GPU 가격대 전력 소모 성능/가격 비율
GTX 1660 Super 30-40만원 125W 높음
RTX 3070 60-80만원 220W 중간
RTX 4090 200-250만원 450W 낮음

5.2 NVIDIA 드라이버 설치

5.2.1 Windows

  1. NVIDIA 공식 사이트에서 드라이버 다운로드
  2. 설치 파일 실행 후 지시에 따라 설치
  3. 재부팅 후 nvidia-smi 명령어로 확인

5.2.2 Linux (Ubuntu)

# 자동 설치 (권장)  
sudo ubuntu-drivers autoinstall  

# 수동 설치  
sudo apt update  
sudo apt install nvidia-driver-525  
sudo reboot  

# 설치 확인  
nvidia-smi  

6 Python 딥러닝 환경 구축

6.1 Conda 환경 생성

# 새 환경 생성  
conda create -n nblog python=3.11  
conda activate nblog  

6.2 CUDA Toolkit 설치

6.2.1 버전 호환성 확인

PyTorch 버전 CUDA 버전 Python 버전
2.1.x 11.8, 12.1 3.8-3.11
2.0.x 11.7, 11.8 3.8-3.11
1.13.x 11.6, 11.7 3.7-3.10

6.2.2 CUDA와 Pytorch 설치

#  
## 1. PyTorch 설치 (CUDA 12.1 권장)  
#pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121  
#  
## 2. transformers 및 관련 패키지  
#pip install transformers  
#pip install accelerate  
#pip install datasets  # 데이터셋 사용시  

import torch  

print(f"PyTorch 버전: {torch.__version__}")  
print(f"CUDA 사용 가능: {torch.cuda.is_available()}")  
print(f"CUDA 버전 (PyTorch): {torch.version.cuda}")  
print(f"GPU 이름: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'None'}")  

6.2.3 TensorFlow 설치

pip install tensorflow[and-cuda]  

# pytorch 설치 후 텐서플로우 설치 시 제거  
#pip uninstall tensorflow tensorflow-gpu tensorflow-cpu  
#pip uninstall tensorboard tensorboard-plugin-wit  
## 캐시 정리  
#pip cache purge  

6.2.4 설치 확인

import torch  

if torch.cuda.is_available():  
    device = torch.device("cuda")  
    print(f"GPU: {torch.cuda.get_device_name(0)}")  
    
    # 간단한 텐서 연산  
    a = torch.randn(1000, 1000).to(device)  
    b = torch.randn(1000, 1000).to(device)  
    
    # GPU에서 행렬 곱셈  
    c = torch.matmul(a, b)  
    
    print("✅ GPU 텐서 연산 성공!")  
    print(f"결과 shape: {c.shape}")  
    print(f"GPU 메모리 사용량: {torch.cuda.memory_allocated()/1024**2:.1f} MB")  
    
    # 메모리 정리  
    torch.cuda.empty_cache()  
# 더 가벼운 모델로 테스트  
model_name = "prajjwal1/bert-tiny"  # 매우 작은 모델  

try:  
    from transformers import AutoTokenizer, AutoModel  
    
    print("모델 다운로드 중...")  
    tokenizer = AutoTokenizer.from_pretrained(model_name)  
    model = AutoModel.from_pretrained(model_name).to(device)  
    
    print("GPU에서 추론 실행 중...")  
    text = "GPU 테스트입니다"  
    inputs = tokenizer(text, return_tensors="pt")  
    inputs = {k: v.to(device) for k, v in inputs.items()}  
    
    with torch.no_grad():  
        outputs = model(**inputs)  
    
    print("✅ 작은 모델로 GPU 테스트 성공!")  
    print(f"출력 shape: {outputs.last_hidden_state.shape}")  
    print(f"GPU 메모리 사용량: {torch.cuda.memory_allocated()/1024**2:.1f} MB")  
    
except Exception as e:  
    print(f"여전히 오류: {e}")  
import torch  
from transformers import AutoModel, AutoTokenizer  

print("=== PyTorch GPU 테스트 ===")  
print(f"PyTorch 버전: {torch.__version__}")  
print(f"CUDA 사용 가능: {torch.cuda.is_available()}")  

if torch.cuda.is_available():  
    print(f"CUDA 버전: {torch.version.cuda}")  
    print(f"GPU: {torch.cuda.get_device_name(0)}")  
    
    # transformers 테스트  
    device = torch.device("cuda")  
    model_name = "distilbert-base-uncased"  
    
    try:  
        tokenizer = AutoTokenizer.from_pretrained(model_name)  
        model = AutoModel.from_pretrained(model_name).to(device)  
        
        text = "GPU test with transformers"  
        inputs = tokenizer(text, return_tensors="pt")  
        inputs = {k: v.to(device) for k, v in inputs.items()}  
        
        with torch.no_grad():  
            outputs = model(**inputs)  
        
        print("✅ transformers GPU 테스트 성공!")  
        print(f"출력 shape: {outputs.last_hidden_state.shape}")  
        print(f"GPU 메모리 사용량: {torch.cuda.memory_allocated()/1024**2:.1f} MB")  
        
    except Exception as e:  
        print(f"❌ 오류: {e}")  
else:  
    print("❌ CUDA를 사용할 수 없습니다.")  

7 성능 최적화 팁

# 배치 크기 조정  

# VRAM에 따른 권장 배치 크기  
# 6GB VRAM: batch_size = 16-32  
# 8GB VRAM: batch_size = 32-64  
# 12GB VRAM: batch_size = 64-128  

batch_size = 32  # VRAM 용량에 맞게 조정  

# 혼합 정밀도 훈련  
# PyTorch AMP 사용  
from torch.cuda.amp import autocast, GradScaler  

scaler = GradScaler()  

for data, target in dataloader:  
    optimizer.zero_grad()  
    
    with autocast():  
        output = model(data)  
        loss = criterion(output, target)  
    
    scaler.scale(loss).backward()  
    scaler.step(optimizer)  
    scaler.update()  

7.1 GPU 메모리 관리

# PyTorch 메모리 정리  
torch.cuda.empty_cache()  

# 메모리 사용량 확인  
print(f"Allocated: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")  
print(f"Reserved: {torch.cuda.memory_reserved() / 1024**3:.2f} GB")  

8 실제 성능 벤치마크

8.1 간단한 벤치마크 코드

import torch  
import time  

def benchmark_gpu():  
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  
    
    # 큰 행렬 생성  
    a = torch.randn(5000, 5000).to(device)  
    b = torch.randn(5000, 5000).to(device)  
    
    # 성능 측정  
    start_time = time.time()  
    for _ in range(100):  
        c = torch.mm(a, b)  
    end_time = time.time()  
    
    print(f"Device: {device}")  
    print(f"Time: {end_time - start_time:.2f} seconds")  
    print(f"GPU Memory: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")  

benchmark_gpu()  

8.2 실제 딥러닝 모델 성능 비교

import torch  
import torch.nn as nn  
import time  

class SimpleModel(nn.Module):  
    def __init__(self):  
        super().__init__()  
        self.layers = nn.Sequential(  
            nn.Linear(1000, 2000),  
            nn.ReLU(),  
            nn.Linear(2000, 1000),  
            nn.ReLU(),  
            nn.Linear(1000, 10)  
        )  
    
    def forward(self, x):  
        return self.layers(x)  

def train_benchmark(device):  
    model = SimpleModel().to(device)  
    optimizer = torch.optim.Adam(model.parameters())  
    criterion = nn.CrossEntropyLoss()  
    
    # 더미 데이터  
    data = torch.randn(1000, 1000).to(device)  
    targets = torch.randint(0, 10, (1000,)).to(device)  
    
    start_time = time.time()  
    
    for epoch in range(100):  
        optimizer.zero_grad()  
        outputs = model(data)  
        loss = criterion(outputs, targets)  
        loss.backward()  
        optimizer.step()  
    
    end_time = time.time()  
    print(f"{device} training time: {end_time - start_time:.2f} seconds")  

# CPU vs GPU 비교  
train_benchmark('cpu')  
train_benchmark('cuda')  

9 결론

GPU와 CUDA를 활용한 딥러닝 환경 구축은 다음과 같은 이점을 제공합니다:

  1. 훈련 시간 단축: 10-100배 빠른 모델 훈련
  2. 더 큰 모델 실험: 메모리 효율성으로 복잡한 모델 실험 가능
  3. 실시간 추론: 빠른 GPU 연산으로 실시간 서비스 구현

딥러닝을 시작하는 분들에게는 적절한 GPU 환경 구축이 필수적입니다. 하드웨어 선택부터 소프트웨어 설치까지 체계적으로 접근하면 효율적인 딥러닝 개발 환경을 구축할 수 있습니다.

Subscribe

Enjoy this blog? Get notified of new posts by email: