디바이스 관리
디바이스란?
섹션 제목: “디바이스란?”PyTorch 텐서는 특정 디바이스(device) 에 할당되어 있습니다. 디바이스는 텐서 데이터가 물리적으로 저장되고 연산이 실행되는 하드웨어를 의미합니다.
| 디바이스 | 식별자 | 특징 |
|---|---|---|
| CPU | 'cpu' | 모든 환경에서 사용 가능, 범용 연산 |
| NVIDIA GPU | 'cuda' 또는 'cuda:0' | 병렬 연산 가속, VRAM 사용 |
| Apple Silicon | 'mps' | M1/M2/M3 칩의 GPU 가속 |
import torch
x = torch.tensor([1.0, 2.0, 3.0])print(x.device) # device(type='cpu')디바이스 가용성 확인
섹션 제목: “디바이스 가용성 확인”코드를 이식 가능하게 작성하려면 런타임에 디바이스를 감지해야 합니다.
import torch
# CUDA (NVIDIA GPU) 확인print(torch.cuda.is_available()) # True / Falseprint(torch.cuda.device_count()) # GPU 개수print(torch.cuda.get_device_name(0)) # 'NVIDIA RTX 4090' 등
# MPS (Apple Silicon) 확인print(torch.backends.mps.is_available()) # True / False
# 실전 패턴: 자동 디바이스 선택if torch.cuda.is_available(): device = torch.device('cuda')elif torch.backends.mps.is_available(): device = torch.device('mps')else: device = torch.device('cpu')
print(device) # cuda, mps, 또는 cputorch.device() 사용법
섹션 제목: “torch.device() 사용법”torch.device 객체는 디바이스 정보를 명시적으로 표현합니다.
import torch
# 문자열로 생성cpu_device = torch.device('cpu')cuda_device = torch.device('cuda') # 기본 GPU (인덱스 0)cuda1 = torch.device('cuda:1') # 두 번째 GPUmps_device = torch.device('mps')
# 텐서 생성 시 디바이스 지정x = torch.zeros(3, 4, device=cuda_device)print(x.device) # device(type='cuda', index=0)
# 문자열도 직접 사용 가능 (내부에서 자동 변환)y = torch.ones(3, 4, device='cuda:0')텐서 이동: .to(), .cuda(), .cpu()
섹션 제목: “텐서 이동: .to(), .cuda(), .cpu()”.to(device) — 범용 이동
섹션 제목: “.to(device) — 범용 이동”import torch
x = torch.tensor([1.0, 2.0, 3.0]) # CPU에 생성
# device 객체로 이동device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')x_gpu = x.to(device)print(x_gpu.device) # device(type='cuda', index=0)
# dtype과 device를 동시에 변경x_fp16 = x.to(device=device, dtype=torch.float16)print(x_fp16.dtype) # torch.float16print(x_fp16.device) # device(type='cuda', index=0).cuda() / .cpu() — 단축 메서드
섹션 제목: “.cuda() / .cpu() — 단축 메서드”import torch
x = torch.randn(3, 3)
# CPU → GPUx_gpu = x.cuda() # 기본 GPU(cuda:0)x_gpu1 = x.cuda(1) # 두 번째 GPU
# GPU → CPUx_cpu = x_gpu.cpu()
# 이미 해당 디바이스에 있으면 복사 없이 자신을 반환x_same = x_cpu.cpu()print(x_same is x_cpu) # True (같은 객체)디바이스 간 이동 주의사항
섹션 제목: “디바이스 간 이동 주의사항”1. 서로 다른 디바이스의 텐서는 연산 불가
섹션 제목: “1. 서로 다른 디바이스의 텐서는 연산 불가”import torch
if torch.cuda.is_available(): x_cpu = torch.tensor([1.0, 2.0]) x_gpu = torch.tensor([3.0, 4.0]).cuda()
# 오류 발생! # result = x_cpu + x_gpu # RuntimeError: Expected all tensors to be on the same device
# 올바른 방법: 같은 디바이스로 맞추기 result = x_cpu.to(x_gpu.device) + x_gpu2. GPU → CPU 이동 후 NumPy 변환
섹션 제목: “2. GPU → CPU 이동 후 NumPy 변환”import torchimport numpy as np
x_gpu = torch.randn(3, 3).cuda()
# GPU 텐서는 바로 NumPy 변환 불가# x_np = x_gpu.numpy() # 오류!
# CPU로 옮긴 후 변환x_np = x_gpu.cpu().numpy()print(type(x_np)) # <class 'numpy.ndarray'>3. requires_grad 텐서의 이동
섹션 제목: “3. requires_grad 텐서의 이동”import torch
x = torch.randn(3, 3, requires_grad=True).cuda()
# detach() 없이 .numpy() 불가# x.cpu().numpy() # 오류!
# 올바른 방법x_np = x.detach().cpu().numpy()멀티 GPU 환경
섹션 제목: “멀티 GPU 환경”GPU가 여러 개일 때 현재 기본 디바이스를 설정할 수 있습니다.
import torch
print(torch.cuda.device_count()) # 사용 가능한 GPU 수
# 현재 기본 GPU 변경torch.cuda.set_device(1) # GPU 1을 기본으로
# 컨텍스트 매니저로 일시적 변경with torch.cuda.device(2): x = torch.randn(3, 3) # GPU 2에 생성 print(x.device) # device(type='cuda', index=2)권장 코드 패턴
섹션 제목: “권장 코드 패턴”모든 환경에서 동작하는 이식 가능한 코드를 위한 패턴입니다.
import torchimport torch.nn as nn
# 디바이스 자동 선택device = torch.device( 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu')print(f"사용 디바이스: {device}")
# 모델과 데이터를 같은 디바이스로model = nn.Linear(10, 5).to(device)
for batch_x, batch_y in dataloader: # 데이터를 모델과 같은 디바이스로 이동 batch_x = batch_x.to(device) batch_y = batch_y.to(device)
output = model(batch_x) loss = criterion(output, batch_y)