콘텐츠로 이동

디바이스 관리

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 / False
print(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, 또는 cpu

torch.device 객체는 디바이스 정보를 명시적으로 표현합니다.

import torch
# 문자열로 생성
cpu_device = torch.device('cpu')
cuda_device = torch.device('cuda') # 기본 GPU (인덱스 0)
cuda1 = torch.device('cuda:1') # 두 번째 GPU
mps_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')
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.float16
print(x_fp16.device) # device(type='cuda', index=0)
import torch
x = torch.randn(3, 3)
# CPU → GPU
x_gpu = x.cuda() # 기본 GPU(cuda:0)
x_gpu1 = x.cuda(1) # 두 번째 GPU
# GPU → CPU
x_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_gpu
import torch
import 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'>
import torch
x = torch.randn(3, 3, requires_grad=True).cuda()
# detach() 없이 .numpy() 불가
# x.cpu().numpy() # 오류!
# 올바른 방법
x_np = x.detach().cpu().numpy()

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 torch
import 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)