AICA X NVIDIA Cluster GPU 교육 시리즈
4. 분산학습을 통한 가속화
홍광수 박사 (솔루션 아키텍트, NVIDIA))
NVIDIA x AICA Cluster GPU 활용 캠프 (2024/08/26 - 09/05)
•
분산처리의 기본 개념과 알고리즘을 알아본다.
•
딥러닝에서의 병렬처리 알고리즘을 알아본다.
◦
Data / Model / Tensor / Hybrid Parallelism
•
실제 코드에서 분산학습을 적용하는 방법을 알아본다.
분산처리의 기본 개념
•
서버 2개 (host0, host1) 안에 GPU 2장씩 있다고 가정하면:
◦
local_rank : 로컬 식별자 (local_rank 0)
◦
global_rank: 글로벌 식별자 (rank 0, …, rank 3)
Task 간의 통신: Communication among tasks
•
Point-to-point Communication
◦
Single sender, single receiver
◦
Relatively easy to implement efficiently
•
Collective Communication
◦
Multiple senders and / or receiver
◦
Patterns include broadcast, scatter, gather, reduce, all-to-all, …
◦
Difficult to implement efficiently.
Collective Communication
•
Broadcast: 데이터를 전체 rank에 걸쳐서 전송하는 것.
•
AllGather: 각 rank의 데이터를 하나로 합친 후 다시 broadcast 하는 것.
•
ReduceScatter: 각 위치의 데이터를 rank에 나누어 걸쳐서 전송.
•
AllReduce: 전반적으로 걸쳐있는 데이터를 summation한 후 broadcast.
그렇다면 어떻게 데이터를 전송할 것인가?
Ring Based All-Reduce:
•
Process 1의 데이터를 2로 옮기고, 3으로 4로 옮겨서 sumation을 한다.
•
전체 index를 골고루 나누어 summation할 수 있다.
•
“Topology를 ring으로 구축한다.”
•
딥러닝 학습 시 이렇게 링으로 구축 후 collective communication을 한다.
Double Tree Based All-Reduce:
•
트리 기반으로 Topology를 구성한 후 summation한다.
그렇다면 이런 것들을 개발자가 잘 알 필요가 있을까?
→ NCCL 라이브러리 안에 이미 잘 구현이 되어있다!
1.
Topology Detection: 하드웨어의 구성이나 연결성을 탐색하여 Topology를 구성한다.
2.
Graph Search: 어떤 통신량이 적고 효율적인지 탐색한다.
3.
Graph Connect
4.
CUDA Kernels
•
링 알고리즘을 기반으로 multi-ring을 구축한 후 Node간 통신을 구축한다.
•
사실 개발자는 코드 한줄로 해결이 되지만 개념은 이해하는 것이 필요하다.
•
NCCL을 사용하면 GPU Direct RDMA 기술을 자동적으로 사용할 수 있다.
Distributed Processing in Deep Learning
Data Parallelism
•
딥러닝의 학습은 Forward pass, loss computation, gradiant back propagation 과정을 거치며 이는 single GPU를 기반으로 구축되어있다.
•
Data Parallelism의 개념은 하나의 GPU로부터 여러개 GPU로 쪼개서 동시에 학습을 진행하는 것.
Pytorch에서 어떻게 구축되어있는가?
1.
DataParallel
•
CPU 코어 하나만 사용해서 여러개의 GPU를 처리한다.
2.
DistributedDataParallel
•
하나의 process에 하나의 GPU가 연결되어 병렬처리가 가능함.
이 때, 학습 패러다임이 완전히 달라지게 된다.
DataParallel Workflow:
•
각 GPU에 데이터를 쪼개고, 모델을 복제하고, loss와 gradiant를 계산 후 gradiant를 accumulation 시켜서 weight를 업데이트한다.
•
이때, 매 iteration마다 모델을 복제한다.
◦
모델사이즈가 적으면 이 과정이 어렵지 않다.
◦
하지만 모델사이즈가 커지면 매우 부담이 되는 과정이다.
DistributedDataParallel Workflow:
•
모델을 복제하지 않고, 각 GPU에 모델을 가지고 있다.
•
이 때, 똑같은 모델을 업데이트하기 위해 gradient를 동기화시켜주는 작업이 필요하다.
•
DDP는 Backward 작업을 하면서 매번 gradient sync를 하게 된다.
•
이때, Pytorch는 이를 효율적으로 수행하기 위해 효율적인 로직을 가지고 있다.
•
예를 들면 AllReduce가 비효율적이기 때문에 이를 개선하는 알고리즘 등이 있다.
Model Parallelism
•
GPU메모리에 올라가지 않는 큰 모델을 쪼개서 학습을 시키는 기술
1.
Pipeline Parallel: 파이프라인을 쪼개는 것
2.
Tensor Parallel: 매트릭스를 쪼개는 것
Tensor Parallel
•
Communication Burdon이 크므로 하드웨어 제약을 생각해야 한다.
•
텐서를 너무 작게 분할하면 효과적인 학습이 안된다.
•
Intensity Metric을 고려하여 GPU리소스를 충분히 활용하는지 확인해야 한다.
•
두가지 종류가 있다. 하나는 가로로 쪼개고, 다른 하나는 세로로 쪼개는 것.
•
Transformers등에도 적용되어있는데, Communication burdon이 있다.
•
Input X와 Weight A가 있다면,
◦
forward 연산은 split으로 나누어준 후 마지막에 allgather 연산으로 합쳐준다.
◦
backward 연산은 identity와 allgather 연산을 해준다.
◦
이 두 연산은 communitive 하다.
•
이런 내용들이 LLM Model Framework 내부에서 자동적으로 적용되도록 잘 구축되어있다.
Pipeline Parallel
•
파이프라인을 n개로 나누어주면, 이 n개의 파이프라인은 sequential하게 연산이 된다.
•
이 경우, GPU가 쉬는 구간이 많아진다. (GPU idle time)
•
이를 해결하기 위해 micro batch로 나누어 GPU idle time을 최소화시킬 수 있다.
예를 들어보자.
첫번째 batch (1a)에 대한 Forward pass와 backward pass는 다음과 같이 나타낼 수 있다.
유휴시간을 줄이기 위해, 두번째 micro batch (2b)를 다음과 같이 연산한다.
n개의 micro batch에 대해서 다음과 같이 연산할 수 있다.
이런 방법들을 통해 bubble time을 줄이는 알고리즘이 내장되어있다.
Hybrid Parallelism
•
node와 rank를 그룹으로 나누어 데이터 및 모델을 병렬화한다.
Distributed Training
분산학습을 하기 위한 Parameters
•
--nproc_per_node: 노드당 GPU 개수
•
--nnodes: 전체 노드의 개수
•
--node_rank: 노드의 글로벌 랭크
•
—master_addr / —master_port: master address의 port정보가
분산학습을 위한 환경 변수
•
Global Rank와 Local Rank를 구분할 필요성이 있다.
예시
QnA
•
모델사이즈가 커서 batch size = 2~4로 작게 설정하는 경우, Model/Pipeline parallel을 사용하는 것이 좋을까?
◦
No. 하나의 GPU에 올라간다면 그냥 쓰는것이 가장 좋다.
◦
gradient accumulation을 활용하자.
•
pytorch lightning과 같은 wrapper를 사용하면 DDP시 성능이 저하될까?
◦
No. 성능저하 없다. 편하게 사용하자.