DeepSpeed와 Accelerate를 활용한 놀라운 속도의 BLOOM 추론
요약
Hugging Face는 8×80 GB A100 GPU에서 DeepSpeed‑Inference 텐서 병렬화와 Accelerate 파이프라인 병렬화를 사용하여 176B 파라미터 BLOOM 모델이 토큰당 1밀리초 미만의 속도로 생성될 수 있음을 보여줍니다.
하드웨어 요구사항 및 설정
- 최적 구성: 8 × 80 GB A100 GPU (352 GB bf16 가중치). 대안으로는 2 × 8 × 40 GB A100, 2 × 8 × 48 GB A6000, 또는 24 × 32 GB V100이 있습니다.
- 단일 노드 장점: 노드 내부 GPU 인터커넥트가 노드 간 링크보다 빠르며, 일반적으로 더 높은 처리량을 제공합니다.
- 저사양 옵션: CPU 또는 NVMe 오프로드를 사용하면 작은 GPU에서도 BLOOM을 실행할 수 있지만, 생성 지연 시간이 크게 증가합니다.
- 양자화 추론: BitsAndBytes를 통한 8‑bit 모델은 GPU 메모리를 대략 절반만 사용하지만, 약간의 처리량 감소가 있습니다.
벤치마크 환경
- 노드: Jean Zay HPC, 8 × 80 GB A100, 512 GB CPU RAM, GPFS 스토리지 (~3 GB/s 읽기 속도).
- 작업: 짧은 프롬프트와 KV‑캐시를 활성화한 상태에서 100 토큰을 탐욕적으로 생성 (
max_length=100, do_sample=False). - 측정 지표: 모델 로딩 시간(초) 및 토큰당 처리량(ms per token = 전체 시간 ÷ (배치 × 토큰)).
모델 로딩 시간
| 솔루션 | 로드 시간 (초) |
|---|---|
| Accelerate | 121 |
| DeepSpeed‑Inference (shard‑int8) | 61 |
| DeepSpeed‑Inference (shard‑fp16) | 60 |
| DeepSpeed‑Inference (unsharded) | 662 |
| DeepSpeed‑ZeRO | 462 |
Pre‑sharded DeepSpeed 체크포인트는 ~1 분에 로드되며, 비분할 체크포인트는 10 분 이상 걸릴 수 있습니다.
토큰 생성 처리량 (8 × 80 GB A100)
| 솔루션 (dtype) | Batch 1 | Batch 8 | Batch 16 | Batch 32 | Batch 64 | Batch 128 | Batch 256 | Batch 512 |
|---|---|---|---|---|---|---|---|---|
| Accelerate bf16 | 230.38 ms | 31.78 ms | 17.84 ms | 10.89 ms | OOM | – | – | – |
| Accelerate int8 | 286.56 ms | 40.92 ms | 22.65 ms | 13.27 ms | OOM | – | – | – |
| DeepSpeed‑Inference fp16 | 44.02 ms | 5.70 ms | 3.01 ms | 1.68 ms | 1.00 ms | 0.69 ms | OOM | – |
| DeepSpeed‑Inference int8 | 89.09 ms | 11.44 ms | 5.88 ms | 3.09 ms | 1.71 ms | 1.02 ms | 0.71 ms | OOM |
| DeepSpeed‑ZeRO bf16 | 283 ms | 34.88 ms | OOM | – | – | – | – | – |
핵심 관찰
- DeepSpeed‑Inference는 텐서 병렬화(TP)와 맞춤형 융합 CUDA 커널 덕분에 배치 128에서 토큰당 1 ms 미만을 달성합니다.
- Accelerate는 단순 파이프라인 병렬화(PP)를 사용하여 배치 32에서 토큰당 약 10 ms에 도달하지만, 배치 64를 넘어서는 GPU 메모리 한계에 부딪힙니다.
- 양자화된 int8 실행은 메모리 사용량을 절반으로 줄이며, DeepSpeed‑Inference int8은 배치 128에서도 토큰당 약 1 ms를 유지하지만 Accelerate int8은 더 일찍 메모리 부족이 발생합니다.
양자화된 8‑bit 처리량 (4 × 80 GB A100)
| 솔루션 | Batch 1 | Batch 8 | Batch 16 | Batch 32 | Batch 64 | Batch 128 |
|---|---|---|---|---|---|---|
| Accelerate int8 | 284.15 ms | 40.14 ms | 21.97 ms | OOM | – | – |
| DeepSpeed‑Inference int8 | 156.51 ms | 20.11 ms | 10.38 ms | 5.50 ms | 2.96 ms | OOM |
솔루션 상세
HuggingFace Accelerate
- 접근 방식: 레이어 크기와 사용 가능한 메모리에 따라 모델 가중치를 지연 로드하며, 각 레이어당 하나의 GPU만 활성화되는 단순 파이프라인 병렬화를 사용합니다.
- 장점: 어떤 하드웨어 구성에서도 바로 작동하며, GPU 메모리가 부족할 경우 CPU나 디스크로 오프로드할 수 있습니다.
- 단점: 대부분의 순전파 과정에서 GPU가 유휴 상태가 되어 최고 처리량이 제한되고, 배치 크기가 커지면 빠르게 OOM에 도달합니다.
- 사용법:
pip install transformers>=4.21.3 accelerate>=0.12.0 python bloom-inference-scripts/bloom-accelerate-inference.py \ --name bigscience/bloom --batch_size 1 --benchmark # 8‑bit 양자화 실행 pip install bitsandbytes python bloom-inference-scripts/bloom-accelerate-inference.py \ --name bigscience/bloom --dtype int8 --batch_size 1 --benchmark
DeepSpeed‑Inference
- 접근 방식: 텐서 병렬화는 각 레이어를 GPU에 분할하고, 맞춤형 융합 커널은 메모리 복사와 커널 호출을 감소시킵니다.
- 성능 요인:
- TP vs PP – 모든 GPU가 동시에 계산하여 활용도를 높입니다.
- 융합 커널 – 메모리 오버헤드가 낮고 커널 호출이 적습니다.
- 사전 분할된 체크포인트 (
microsoft/bloom-deepspeed-inference-fp16)는 약 1분에 로드되며, 비분할 체크포인트는 10‑20분에 로드되지만 로드 후 동일한 속도로 실행됩니다. - 양자화된 int8 (
microsoft/bloom-deepspeed-inference-int8)은 메모리 요구량을 절반으로 줄이며 8 × 80 GB A100에서 배치 128 시 토큰당 1 ms 미만을 유지하거나 4 × 80 GB A100에서도 동작합니다. - 사용법:
pip install deepspeed>=0.7.3 # 빠른 TP‑사전분할 fp16 deepspeed --num_gpus 8 bloom-inference-scripts/bloom-ds-inference.py \ --name microsoft/bloom-deepspeed-inference-fp16 # 원본 체크포인트 (로드 느림) deepspeed --num_gpus 8 bloom-inference-scripts/bloom-ds-inference.py \ --name bigscience/bloom # 8‑bit 버전 (메모리 절반) deepspeed --num_gpus 8 bloom-inference-scripts/bloom-ds-inference.py \ --name microsoft/bloom-deepspeed-inference-int8 --dtype int8
DeepSpeed‑ZeRO Inference
- 접근 방식: 모델 상태를 GPU에 분할(ZeRO‑3 스타일)하고, 여러 독립적인 생성 스트림을 병렬로 실행하여 GPU 수에 비례하는 실질적인 속도 향상을 제공합니다.
- 제한 사항: 제공된 스크립트는 모든 GPU에서 동일한 입력을 실행합니다; 이론적인 8배 또는 16배 속도 향상을 얻으려면 GPU별 맞춤 스트림이 필요합니다.
- 오프로드 옵션: CPU 오프로드 또는 NVMe 오프로드를 통해 단일 GPU에서 추론이 가능하지만 큰 지연이 발생합니다.
- 사용법:
pip install deepspeed # 다중‑GPU ZeRO 추론 deepspeed --num_gpus 8 bloom-inference-scripts/bloom-ds-zero-inference.py \ --name bigscience/bloom --batch_size 1 --benchmark # CPU 오프로드 (단일 GPU) deepspeed --num_gpus 1 bloom-inference-scripts/bloom-ds-zero-inference.py \ --name bigscience/bloom --batch_size 8 --cpu_offload --benchmark # NVMe 오프로드 (단일 GPU) deepspeed --num_gpus 1 bloom-inference-scripts/bloom-ds-zero-inference.py \ --name bigscience/bloom --batch_size 8 \ --nvme_offload_path=/path/to/nvme_offload --benchmark
커뮤니티 서버 및 클라이언트 확장
- 서버 구현:
- Mayank Mishra는 데모 스크립트를 바로 실행 가능한 웹 서버로 패키징했습니다.
- Nicolas Patry는 고성능 Rust 기반 서버를 만들었습니다.
- 클라이언트‑측 프로젝트:
- Thomas Wang은 맞춤형 CUDA 커널 가속 BLOOM 모델을 개발 중입니다.
- HuggingFace JAX 팀은 BLOOM을 위한 JAX 추론 백엔드를 공개했습니다.
- 업데이트 유지:
transformers-bloom-inference저장소는 최신 스크립트와 서버 구현을 모아놓았습니다.
실용적인 시사점
- 단일 노드에서 최대 원시 처리량을 원한다면 사전 분할된 fp16 체크포인트와 함께 DeepSpeed‑Inference를 사용하세요; 배치 128에서 토큰당 1 ms 미만을 기대할 수 있습니다.
- GPU 메모리가 제한적일 때는 BitsAndBytes(DeepSpeed 또는 Accelerate)를 통한 8‑bit 양자화로 전환하여 메모리 요구량을 절반으로 줄이고 약간의 속도 손실을 감수합니다.
- Accelerate는 이기종 하드웨어에 가장 유연한 솔루션이지만, 파이프라인 병렬화는 DeepSpeed의 텐서 병렬화보다 높은 지연을 초래합니다.
- ZeRO 추론은 다수의 GPU로 확장하거나 오프로드를 통해 단일 GPU에서 실행할 수 있는 경로를 제공하며, 대규모 GPU 클러스터가 없을 때 유용합니다.
“이 경우 OOM 없이 실행할 수 있었던 최대 배치 크기는 128이었습니다.” – Hugging Face 블로그, 8 × 80 GB A100에서 DeepSpeed‑Inference int8을 설명하면서.
이 게시물은 2022년 9월 기준 BLOOM 추론 성능 상태를 반영합니다. 최신 최적화에 대해서는 transformers-bloom-inference GitHub 저장소를 참고하세요.