지난 포스트의 DataParallel 모듈은 하나의 machine에 붙어있는 multi-gpu를 사용하여 훈련하는 방법이지만 최근에는 하드웨어 리소스를 충분히 활용하기 위해 하나의 machine 만이 아닌 여러 개의 machine을 동시에 활용하여 deep neural networks를 훈련시키는 distributed data parallel 방법 또한 필수적으로 사용되고 있는 상황입니다. 즉, $N$개의 machine에 $G$개의 gpu가 달려있다면 총 $N\times G$개의 gpu를 딥러닝 훈련에 사용하겠다는 것이죠. Figure 1은 2개의 machine과 각 machine 별로 4개의 gpu가 달려 있는 분산 환경을 나타내며 DDP (Distributed Data Parallel)는 각 gpu 별로 모델 훈련을 시키는 process (train.py)를 가동시킵니다.
분산 병렬 시스템을 이해하고 활용하기 위해서는 몇 가지 용어에 대한 이해가 필요합니다. 먼저 분산 환경에서는 gpu가 달려있는 machine을 node라는 용어로 지칭합니다. Figure 1에서도 machine 대신 NODE1, NODE2로 표기된 것을 볼 수 있습니다. 그리고 분산 환경에서 사용할 총 gpu 개수 $N\times G$를 world size $W$라 하고 각 node 별로 돌아가는 process 개수 (gpu 개수)를 local world size $L$로 표기합니다.
마지막으로는 가장 중요한 rank라는 개념입니다. Rank는 단순히 말해서 DDP 에서 가동되는 process id 입니다. Rank도 world size와 마찬가지로 global rank, local rank로 나뉘는데 global rank는 전체 node에 가동되는 process id 이고 local rank는 각 node 별 process id 입니다. 따라서 global rank는 $[0,W-1]$ 사이의 정수값을 가질 것이고 local rank는 $[0,L-1]$ 사이의 정수값을 가지겠죠. (물론 이 상황은 각 process 마다 하나의 gpu를 점유하고 있는 일반적인 상황을 가정한 겁니다. Figure 1은 하나의 process가 2개의 gpu를 점유하고 있습니다.)
Pytorch 에서는 분산 병렬을 위한 torch.nn.DistributedDataParallel 모듈을 지원하고 DDP 모듈은 여러 개의 node 뿐만 아니라 단일 node (single node) 에서도 동작합니다. DDP는 여러 개의 process를 multiprocessing으로 spawn하고 각 process 별로 DataParallel과 마찬가지로 allreduce collective communication 방법을 활용하여 각 process 별 gradient와 buffer 값을 파라미터 별로 hook을 등록하여 동기화시킵니다. 단, 하나의 gpu를 여러 개의 process가 동시에 점유하지는 못합니다. 그렇다면 일반적으로 하나의 node (machine)의 여러 개의 gpu를 사용하고 싶다면 DataParallel 모듈을 그냥 사용하면 되지 않을까 싶습니다.
하지만 Pytorch의 공식문서에서는 single node에서도 DataParallel 대신 DistributedDataParallel을 쓰라고 권고하고 있습니다. DataParalle이 DistributedDataParallel에 비해 사용하기 훨씬 간편한데, 왜일까요?
DataParallel과 DistributedDataParallel의 가장 결정적인 차이는 DataParallel은 single process, multi-thread 방식으로 single node에서만 동작하고 DistributedDataParallel single/multi machine 여부 상관 없이 multi process로 동작한다는 점입니다. 따라서 파이썬의 GIL (Global Interpreter Lock)로 인해 DataParallel이 DistributedDataParallel에 비해 더 느릴 수밖에 없습니다. (thread간 프로세스 점유싸움과 입출력 scatter/gather로 인한 overhead, 매 iteration 마다 모델을 삭제하고 복사하는 과정 등)
또한, 최근 딥러닝 모델이 커지면서 하나의 모델이 하나의 gpu에 온전히 올라가지 못하는 상황도 빈번히 발생하는데, DistributedDataParallel은 하나의 큰 모델을 여러 개의 작은 모델로 쪼개 각 모델을 여러 gpu에 올려 훈련시키는 model parallel (모델 병렬) 또한 가능합니다. 즉, DistributedDataParallel은 각 gpu 별로 process를 가동시킴으로써 multi thread에 의존하는 DataParallel에 비해 더 빠르고 multi nodes, model parallel 등 다양한 고급 기능들까지 확장해서 사용할 수 있는 것이죠. 다만... 사용방법이 DataParallel에 비해서 많이 복잡합니다.
여담으로 제가 Pytorch를 처음 접했던 2018년도에는 DDP 사용이 지금에 비해서도 극악으로 복잡해서 잘 사용하지 않고 병렬은 거의 DataParallel로 사용했습니다. 사실 DDP의 존재도 몰랐었죠. 이후 병렬 처리를 딱히 쓸 일이 없어 잊고 있다가 몇 개월 전 누군가가 DP와 DDP의 차이가 뭐냐고 물어봤던 적이 있습니다. 데이터, 모델 등의 모든 조건이 동일한데 DDP가 더 빠르다고... 이 글을 보신 여러분들의 훌륭한 답변을 기대합니다!
참조
'Machine Learning Models > Pytorch' 카테고리의 다른 글
Pytorch 텐서 복사 - clone, detach 차이 (0) | 2023.05.04 |
---|---|
Pytorch - DistributedDataParallel (2) - 동작 원리 (1) | 2021.10.28 |
Pytorch - DataParallel (0) | 2021.10.22 |
Pytorch - ModuleList vs List (0) | 2021.08.09 |
Pytorch - backward(retain_graph=True) (2) (1) | 2021.08.01 |