brunch

You can make anything
by writing

C.S.Lewis

by Chris송호연 Feb 14. 2020

GPU 분산 학습 기법: All-Reduce

All-Reduce

All-Reduce를 공부하는 중에 좋은 아티클이 있어서 번역해봤습니다. 제가 좋아하는 AutoML 라이브러리 optuna를 만든 일본 PFN의 인턴 분이 작성했던 글이네요.


https://tech.preferred.jp/en/blog/technologies-behind-distributed-deep-learning-allreduce/


안녕하세요, 우에노 유이치로입니다. 2017 년 PFN에서 여름 인턴쉽 프로그램에 참여했으며 현재 파트 타임 엔지니어로 일하고 있습니다. 저는 도쿄 공과 대학의 학부생이며 연구 주제는 고성능, 병렬 및 분산 컴퓨팅입니다.
이 블로그 게시물에서는 분산 딥 러닝에 사용되는 통신 작업 인 AllReduce 알고리즘에 대한 최근 연구를 설명합니다.


분산 딥 러닝이란 무엇입니까?


현재 딥 러닝의 중요한 과제 중 하나는 시간이 많이 걸리는 프로세스입니다. 딥 러닝 모델을 설계하려면 많은 하이퍼 파라미터의 설계 공간 탐색과 빅 데이터 처리가 필요합니다. 따라서 학습 과정을 가속화하는 것은 우리의 연구 개발에 매우 중요합니다. 분산 딥 러닝은 학습 시간을 단축하는 데 필수적인 기술 중 하나입니다.
연구 개발 프로세스를 가속화하기 위해 개인용 슈퍼 컴퓨터“MN-1”을 배포했습니다. 1024 NVIDIA Tesla P100 GPU와 Mellanox InfiniBand FDR 인터커넥트가 장착되어 있으며 일본 업계에서 가장 강력한 슈퍼 컴퓨터입니다. MN-1을 활용하여 15 분 안에 ImageNet 데이터 세트에 대한 ResNet-50 모델 학습을 완료했습니다.


GPU 간의 통신은 대규모 환경에서 분산 딥 러닝 모델을 학습시킬 때 많은 문제 중 하나입니다. 모든 GPU에서 그라디언트 교환 대기 시간은 데이터 병렬 동기화 분산 딥 러닝에서 심각한 병목 현상입니다.
의사 소통은 분산 딥 러닝에서 어떻게 수행됩니까? 또한 왜 통신에 시간이 많이 걸리는가?


분산 딥 러닝에서 AllReduce의 중요성


동기화 된 데이터 병렬 분산 딥 러닝에서 주요 계산 단계는 다음과 같습니다.  

각 GPU에서 미니 배치를 사용하여 손실 함수의 그래디언트를 계산합니다.

GPU 간 통신을 통해 그래디언트의 평균을 계산합니다.

모델을 업데이트합니다.


평균을 계산하기 위해 "AllReduce"라는 집단 통신 작업을 사용합니다.


현재 GPU 클러스터를위한 가장 빠른 집단 통신 라이브러리 중 하나는 NVIDIA 집단 통신 라이브러리 : NCCL [3]입니다. HPC 커뮤니티의 사실상 표준 통신 라이브러리 인 MPI보다 훨씬 우수한 통신 성능을 제공합니다. NCCL은 ChainerMN을 사용하여 분산 딥 러닝에서 고성능을 달성하는 데 반드시 필요합니다. 그것 없이는 ImageNet 15 분의 업적을 달성 할 수 없었습니다 [2].


우리 연구원과 엔지니어들은 NCCL의 탁월한 성능에 대해 궁금했습니다. NCCL은 오픈 소스 라이브러리가 아니기 때문에 실험적인 AllReduce 라이브러리를 개발하고 최적화하여 라이브러리의 고성능을 이해하려고했습니다.


AllReduce의 알고리즘


먼저 AllReduce 알고리즘을 살펴 보겠습니다. AllReduce는 모든 프로세스의 대상 배열을 단일 배열로 줄이고 결과 배열을 모든 프로세스로 반환하는 작업입니다. 이제 P를 총 프로세스 수로하자. 각 프로세스에는 길이 N의 배열 Ap.가 있습니다. 프로세스 배열의 p ( 1 ≤ p ≤ P ) i번째 요소는 Ap,i이다. 결과 배열 B는 다음과 같습니다.

  


여기서 Op는 이진 연산자입니다. SUM, MAX 및 MIN이 자주 사용됩니다. 분산 딥 러닝에서 SUM 연산은 그래디언트 평균을 계산하는 데 사용됩니다. 이 블로그 게시물의 나머지 부분에서는 축소 작업이 SUM이라고 가정합니다. 그림 1은 P = 4 및 N = 4의 예를 사용하여 AllReduce 작업의 작동 방식을 보여줍니다.


그림 1 AllReduce 작업

 
작업을 구현하기위한 몇 가지 알고리즘이 있습니다. 예를 들어, 하나의 프로세스를 마스터로 선택하고 모든 어레이를 마스터로 모으고 마스터에서 로컬로 축소 작업을 수행 한 다음 결과 어레이를 나머지 프로세스에 배포하는 것이 간단합니다. 이 알고리즘은 간단하고 구현하기 쉽지만 확장 할 수는 없습니다. 마스터 프로세스는 총 프로세스 수에 비례하여 통신 및 감소 비용이 증가하기 때문에 성능 병목 현상입니다.


더 빠르고 확장 가능한 알고리즘이 제안되었습니다. 참가자 프로세스에 계산 및 통신을 신중하게 분배하여 병목 현상을 제거합니다.


이러한 알고리즘에는 Ring-AllReduce 및 Rabenseifner 알고리즘 [4]이 포함됩니다.
이 블로그 게시물에서 Ring-AllReduce 알고리즘에 중점을 둘 것입니다. 이 알고리즘은 NCCL [5] 및 baidu-allreduce [6]에서도 사용됩니다.


Ring-AllReduce

P는 프로세스의 총 수이며 각 프로세스는 1과 P 사이의 숫자로 고유하게 식별된다고 가정합시다. 그림 2에 표시된 것처럼 프로세스는 단일 링을 구성합니다.

그림 2 프로세스 링의 예

 
먼저, 각 프로세스는 자체 배열을 P 하위 배열로 나눕니다.이를 "청크"라고합니다. 

chunk [p]는 p 번째 청크입니다.


다음으로 프로세스 [p]에 집중해봅시다. 이 프로세스는 다음 프로세스로 chunk [p]를 보내고, 이전 프로세스에서 chunk [p-1]을 동시에받습니다 (그림 3).

그림 3 각 프로세스는 청크 [p]를 다음 프로세스 [p + 1]로 보냅니다.

 
그 후, 프로세스 p는 수신 된 청크 [p-1] 및 그 자신의 청크 [p-1]에 대한 reduce 동작을 수행하고, reduce 된 청크를 다음 프로세스 p + 1에 전송합니다 (도 4).

그림 4 각 프로세스는 감소 된 청크를 다음 프로세스로 보냅니다.

 
수신-감소-송신 단계 P-1을 반복함으로써, 각 프로세스는 결과 어레이의 다른 부분을 얻는다 (도 5).

그림 5 P-1 단계 후 각 프로세스는 감소 된 하위 배열을 갖습니다.

 
즉, 각 프로세스는 로컬 청크를 수신 된 청크에 추가하여 다음 프로세스로 보냅니다. 다시 말해, 모든 청크는 링 주위를 여행하며 각 프로세스에서 청크를 축적합니다. 모든 프로세스를 한 번 방문한 후에는 최종 결과 배열의 일부가되고 마지막으로 방문한 프로세스가 청크를 보유합니다.


마지막으로 모든 프로세스는 분산 된 부분 결과를 공유함으로써 완전한 어레이를 얻을 수 있습니다. 이는 감소 단계없이 순환 단계를 다시 수행함으로써, 즉 수신 된 청크를 단지 각 프로세스에서 대응하는 로컬 청크에 덮어 쓰기함으로써 달성된다. 모든 프로세스가 최종 배열의 모든 부분을 확보하면 AllReduce 작업이 완료됩니다.
Ring-AllReduce의 통신량을 위에서 언급 한 간단한 알고리즘의 통신량과 비교해 봅시다.


간단한 알고리즘에서 마스터 프로세스는 다른 모든 프로세스에서 모든 배열을 수신합니다. 즉, 수신 된 총 데이터 양이 ( P– 1 ) × N. 축소 작업 후에는 배열을 모든 프로세스로 다시 보냅니다.( P– 1 ) × N데이터. 따라서 마스터 프로세스의 통신량은 P에 비례합니다.


Ring-AllReduce 알고리즘에서는 다음과 같은 방법으로 각 프로세스의 통신량을 계산할 수 있습니다. 알고리즘의 초반부에서 각 프로세스는 크기가 다음과 같은 배열을 보냅니다.N/ P, P-1타임스. 다음으로, 각 프로세스는 다시 같은 크기 P-1 번의 배열을 보냅니다. 각 프로세스가 알고리즘을 통해 전송하는 총 데이터 양은2 N( P− 1 ) / P, P.의 실질적으로 독립적인 것이 균등 참가 프로세스 동안 계산 및 통신을 분산시켜 병목 공정을 제거하기 때문에 이와 같이, 링 Allreduce 알고리즘은 간단한 알고리즘보다 더욱 효율적이다. 많은 AllReduce 구현은 Ring-AllReduce를 채택하며 분산 딥 러닝 워크로드에도 적합합니다.


구현 및 최적화

기본 송신 및 수신 루틴이 제공되는 경우 Ring-AllReduce 알고리즘은 구현이 간단합니다. baidu-allreduce [6]는 MPI_Send 및 MPI_Recv를 사용하여 MPI 위에 구축됩니다.


그러나 MPI 대신 InfiniBand Verbs API를 사용하여 추가 최적화를 시도했습니다. 하드웨어 리소스를 완전히 활용하기 위해이 알고리즘에는 메모리 등록 (피닝), cuda-memcpy, 보내기, 축소, 받기 및 메모리 등록 취소와 같은 여러 단계가 있으며 소프트웨어 파이프 라인에서 처리됩니다. 여기서, "registration" 및 "deregistration"는 DMA 데이터 전송을위한 전처리 및 후 처리 단계입니다. 이러한 낮은 수준의 작업은 MPI 보내기 / 받기 루틴에서 추상화되며 파이프 라인 단계로 나눌 수 없습니다. 통신 및 계산의 세분성을 높이기 위해 청크를 더 작은 하위 청크로 나눕니다. 또한 메모리 할당 오버 헤드를 숨기는 메모리 풀을 소개합니다.


성능 평가

성능 평가를 위해 프로토 타입 (PFN-Proto)을 부록에 표시된 여러 AllReduce 구현과 비교했습니다.
프로토 타입 구현은 현재 노드 간 통신에 중점을 둡니다. 공유 메모리 또는 GPU-GPU DMA 데이터 전송을 사용하는 노드 내 통신에 최적화되지 않았습니다. 노드 구성 당 하나의 프로세스로 구현을 평가했습니다. Open MPI [7]의 경우, 가장 최신 시리즈에는 GPUDirect와 관련하여 사소한 문제가 있으므로 최신 버전 3.x 시리즈를 아직 소개하지 않았습니다. 따라서 대신 버전 2.1.3을 사용했습니다.


아래“실험 환경”에 표시된 것처럼이 실험에는 개인용 슈퍼 컴퓨터 MN-1을 사용했습니다. 하나의 프로세스가 하나의 컴퓨팅 노드에서 실행되는 8 개의 프로세스가 실행되었습니다. 대상 데이터 크기는 256MB입니다.


그림 6 AllReduce 실행 시간

 
평가 결과는 그림 6과 같습니다. 각 막대는 10 회 중앙값을 나타냅니다. 오차 막대는 신뢰 구간을 나타냅니다. 각 라이브러리의 세부 사항은 아래 "소프트웨어 버전"에 나와 있습니다.


먼저 중앙값을 봅시다. 우리의 실험적 구현 인 PFN-Proto는 가장 빠른 시간을 보였으며, 이는 NCCL의 바이 피, ompi-cuda, ompi-cuda보다 각각 약 82 %, 286 %, 28 %, 1.6 % 더 낫습니다. 그래프에없는 언급 할 가치가있는 것은 Baidu가 5 개의 라이브러리 중에서 가장 빠른 단일 실행 시간 0.097 [s]를 달성했다는 것입니다.


다음으로 성능의 분산에 중점을 둡니다. PFN-Proto 및 NCCL의 최대 및 최소 런타임은 각각 +/- 3 % 및 +/- 6 %입니다. 반대로 Baidu의 최대 값은 첫 실행에 시간이 오래 걸리기 때문에 중앙값의 7.5 배입니다. 첫 번째 실행을 제외한 최대 런타임은 중앙값보다 + 9.6 %이며 이는 여전히 NCCL 및 PFN-Proto보다 중요합니다.


우리의 가설은 MPI 및 MPI 기반 루틴의 성능 차이가 메모리 작업과 관련된 MPI의 내부 동작에 기인한다는 것입니다. MPI의 프로그래밍 인터페이스는 InfiniBand 통신을위한 메모리 할당 및 등록 작업을 숨 깁니다. 이러한 작업의 타이밍은 AllReduce 구현에서 제어 할 수 없습니다.


요약

분산 심층 학습에 매우 중요한 AllReduce 통신 패턴을 설명했습니다. 특히 실험 커뮤니케이션 라이브러리에서 Ring-AllReduce 알고리즘을 구현했으며 NVIDIA에서 출시 한 NCCL 라이브러리와 비슷한 성능을 달성했습니다. 이 구현은 InfiniBand Verbs API 및 소프트웨어 파이프 라이닝 사용과 같은 고급 최적화를 통해 사용 가능한 하드웨어 리소스를 효율적으로 활용합니다. 우리는 분산 딥 러닝 가속화에 대한 연구 개발을 계속합니다.
주의 사항 : 구현은 실험적이며 사내 클러스터의 성능 만 시연했습니다. NCCL은 광범위한 IB 연결 NVIDIA GPU 클러스터에서의 성능 적합성 및 가용성 덕분에 매우 실용적이고 유용한 라이브러리입니다.


감사의 말

친절한 지원과 피드백에 대해 멘토와 팀에게 감사의 말씀을 전합니다. 작년에 인턴쉽을 시작한 이래로 풍부한 계산 리소스를 이용할 수 있었으며 환상적인 경험이었습니다.


멘토의 피드백

이 프로젝트는 다음과 같은 질문으로 시작되었습니다.“NCCL이 어떻게 그렇게 높고 안정적인 성능을 달성합니까?”이것은 진보적이고 실험적인 주제이지만 Ueno는 높은 동기 부여와 기술력으로 놀라운 결과를 얻었습니다.


PFN은 딥 러닝 / 머신 러닝 분야뿐만 아니라 하드웨어에서 소프트웨어에 이르기까지 모든 기술 분야에서 인재를 찾고 있습니다. 자세한 내용은 https://www.preferred-networks.jp/en/jobs를 방문하십시오.
고성능 컴퓨팅 및 기타 기술에 관심이있는 학생들을 위해 PFN은 국제 인턴십 기회와 일본 학생들을위한 국내 프로그램을 제공합니다. 응모 기간은 올해 끝났지 만 다음 기회에 대비하십시오!


References

[1] Preferred Networks officially released ChainerMN version 1.0.0
[2] Akiba, et al., “Extremely Large Minibatch SGD: Training ResNet-50 on ImageNet in 15 Minutes”
[3] NVIDIA Collective Communications Library
[4] Rabenseifner, “Optimization of Collective Reduction Operations”, ICCS 2004
[5] Jeaugey, “Optimized Inter-GPU Collective Operations with NCCL”, GTC 2017
[6] baidu-allreduce
[7] Open MPI
[8] New ChainerMN functions for improved performance in cloud environments and performance testing results on AWS
[9] Tsuzuku, et al., “Variance-based Gradient Compression for Efficient Distributed Deep Learning”, In Proceedings of ICLR 2018 (Workshop Track)


Appendix

소프트웨어 버전      

      이행      버전      노트    

MPI (ompi) / MPI 2.1.3 열기 / CPU 메모리에서 CPU 메모리로의 Trasnfer (GPU 관련 없음)

CUDA 인식 MPI / MPI 2.1.3 / GPU 메모리에서 GPU 메모리로

바이두 allreduce (바이두) / 커밋 ID 73c7b7f를 기반으로 한 baidu-allreduce의 사용자 정의 버전 / https://github.com/keisukefukuda/baidu-allreduce

NCCL 2.2.13


실험 환경  

인텔 ® 제온 ® CPU E5-2667 * 2

Mellanox ConnectX-3 InfiniBand FDR (56Gbps) x2

NVIDIA Pascal P100 GPU (NVIDIA 드라이버 버전 375.20 포함)


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari