DP와 DDP 소개
데이터 병렬 처리(Data Parallelism, DP)와 분산 데이터 병렬 처리(Distributed Data Parallelism, DDP)는 대규모 데이터셋과 복잡한 모델을 더 빠르게 학습하기 위해 널리 사용되는 기술입니다. 이러한 기술은 특히 딥러닝에서 중요한 역할을 합니다.
DP와 DDP가 필요한 이유
- 대규모 데이터 처리: 현대의 기계 학습 모델은 엄청난 양의 데이터를 필요로 합니다. DP와 DDP는 여러 GPU 또는 머신에 작업을 분산시켜 대규모 데이터를 효율적으로 처리할 수 있게 해줍니다.
- 시간 절약: 모델 학습 시간을 줄이기 위해, 데이터를 분할하여 여러 처리 단위에서 병렬로 작업을 수행할 수 있습니다.
- 자원 활용 최적화: 가용한 모든 컴퓨팅 자원(여러 GPU 또는 머신)을 활용하여 성능을 최대화합니다.
DP와 DDP의 차이점
- DP (Data Parallelism)
- 단일 머신 내의 여러 GPU에서 모델의 복사본을 실행하여 데이터 배치를 병렬로 처리합니다.
- GPU 간의 통신은 주로 같은 머신 내부에서 이루어집니다.
- 구현이 상대적으로 간단하며, 단일 머신 환경에서 효과적입니다.
- DDP (Distributed Data Parallelism)
- 여러 머신에 걸쳐있는 여러 GPU에서 작업을 수행합니다.
- 네트워크를 통해 머신 간 통신이 이루어져, 더 큰 규모의 데이터와 모델에 적합합니다.
- 더 복잡한 설정이 필요하지만, 더 큰 확장성과 높은 성능을 제공합니다.
DP (Data Parallelism) 사용 방법
PyTorch에서 torch.nn.DataParallel
을 사용하여 간단하게 데이터 병렬 처리를 구현할 수 있습니다. 이를 위해 모델을 DataParallel
로 감싸고 훈련 데이터를 배치로 나누어 여러 GPU에 분산시킵니다.
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
# 임의의 간단한 모델
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc = nn.Linear(10, 2) # 예시로 10개의 특성을 받아 2개로 출력
def forward(self, x):
return self.fc(x)
# 모델과 데이터 로더 초기화
model = SimpleModel()
if torch.cuda.is_available():
model = model.cuda()
model = nn.DataParallel(model) # Data Parallel 적용
# 임의의 데이터 로더 설정
dataloader = DataLoader(torch.randn(100, 10), batch_size=32)
# 훈련
for data in dataloader:
if torch.cuda.is_available():
data = data.cuda()
output = model(data)
DDP (Distributed Data Parallelism) 사용 방법
DDP는 torch.nn.parallel.DistributedDataParallel
을 사용합니다. 이 구현은 다소 복잡하며, 여러 머신에 걸쳐 작업을 수행할 때 각 프로세스를 올바르게 설정하는 것이 필요합니다. 또한, 각 머신의 GPU에서 실행되는 프로세스 간에 통신 백엔드를 설정해야 합니다.
이 예시 코드는 단일 노드의 다중 GPU 환경에 대한 것입니다. 실제 분산 환경에서는 스크립트를 각 노드에서 별도로 실행하고 적절한 rank
와 world_size
를 설정하여 각 노드에서 실행해야 합니다. 또한, 네트워크 설정, 노드 간의 통신, 환경 변수 설정 등 추가적인 고려가 필요합니다.
import os
import torch
import torch.distributed as dist
import torch.nn as nn
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.data import DataLoader, DistributedSampler
# 초기화
def setup(rank, world_size):
os.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = '12345'
dist.init_process_group("nccl", rank=rank, world_size=world_size)
# 정리
def cleanup():
dist.destroy_process_group()
# 모델 정의
class SimpleModel(nn.Module):
# ... [모델 정의와 같음]
def main(rank, world_size):
setup(rank, world_size)
model = SimpleModel().cuda(rank)
model = DDP(model, device_ids=[rank])
# 데이터 로더는 DistributedSampler를 사용하여 데이터셋을 분산
dataset = torch.randn(100, 10)
sampler = DistributedSampler(dataset, num_replicas=world_size, rank=rank)
dataloader = DataLoader(dataset, batch_size=32, sampler=sampler)
# 훈련
for data in dataloader:
output = model(data.cuda(rank))
cleanup()
# 예를 들어 2개의 GPU에서 실행한다고 가정
world_size = 2
for rank in range(world_size):
main(rank, world_size)