DeepSpeed[[deepspeed]]
DeepSpeed๋ ๋ถ์ฐ ํ์ต ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํจ์จ์ ์ด๊ณ ๋น ๋ฅด๊ฒ ๋ง๋๋ PyTorch ์ต์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๊ทธ ํต์ฌ์ ๋๊ท๋ชจ ๋ชจ๋ธ์ ๊ท๋ชจ์ ๋ง๊ฒ ํ๋ จํ ์ ์๋ Zero Redundancy Optimizer(ZeRO)์ ๋๋ค. ZeRO๋ ์ฌ๋ฌ ๋จ๊ณ๋ก ์๋ํฉ๋๋ค:
- ZeRO-1, GPU ๊ฐ ์ต์ ํ ์ํ ๋ถํ
- ZeRO-2, GPU ๊ฐ ๊ทธ๋ ์ด๋์ธํธ ๋ถํ
- ZeRO-3, GPU ๊ฐ ๋งค๊ฐ๋ณ์ ๋ถํ
GPU๊ฐ ์ ํ๋ ํ๊ฒฝ์์ ZeRO๋ ์ต์ ํ ๋ฉ๋ชจ๋ฆฌ์ ๊ณ์ฐ์ GPU์์ CPU๋ก ์คํ๋ก๋ํ์ฌ ๋จ์ผ GPU์ ๋๊ท๋ชจ ๋ชจ๋ธ์ ์ฅ์ฐฉํ๊ณ ํ๋ จํ ์ ์์ต๋๋ค. DeepSpeed๋ ๋ชจ๋ ZeRO ๋จ๊ณ ๋ฐ ์คํ๋ก๋ฉ์ ์ํด Transformers [Trainer] ํด๋์ค์ ํตํฉ๋์ด ์์ต๋๋ค. ๊ตฌ์ฑ ํ์ผ์ ์ ๊ณตํ๊ฑฐ๋ ์ ๊ณต๋ ํ
ํ๋ฆฟ์ ์ฌ์ฉํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ถ๋ก ์ ๊ฒฝ์ฐ, Transformers๋ ๋์ฉ๋ ๋ชจ๋ธ์ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฏ๋ก ZeRO-3 ๋ฐ ์คํ๋ก๋ฉ์ ์ง์ํฉ๋๋ค.
์ด ๊ฐ์ด๋์์๋ DeepSpeed ํธ๋ ์ด๋์ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ, ํ์ฑํํ ์ ์๋ ๊ธฐ๋ฅ, ๋ค์ํ ZeRO ๋จ๊ณ์ ๋ํ ๊ตฌ์ฑ ํ์ผ ์ค์ ๋ฐฉ๋ฒ, ์คํ๋ก๋ฉ, ์ถ๋ก ๋ฐ [Trainer] ์์ด DeepSpeed๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ดํด ๋๋ฆฝ๋๋ค.
์ค์น[[installation]]
DeepSpeed๋ PyPI ๋๋ Transformers์์ ์ค์นํ ์ ์์ต๋๋ค(์์ธํ ์ค์น ์ต์ ์ DeepSpeed ์ค์น ์์ธ์ฌํญ ๋๋ GitHub README๋ฅผ ์ฐธ์กฐํ์ธ์).
DeepSpeed๋ฅผ ์ค์นํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ DeepSpeed CUDA ์ค์น ๊ฐ์ด๋๋ฅผ ํ์ธํ์ธ์. DeepSpeed์๋ pip ์ค์น ๊ฐ๋ฅํ PyPI ํจํค์ง๋ก ์ค์นํ ์ ์์ง๋ง, ํ๋์จ์ด์ ๊ฐ์ฅ ์ ๋ง๊ณ PyPI ๋ฐฐํฌํ์์๋ ์ ๊ณต๋์ง ์๋ 1๋นํธ Adam๊ณผ ๊ฐ์ ํน์ ๊ธฐ๋ฅ์ ์ง์ํ๋ ค๋ฉด ์์ค์์ ์ค์นํ๊ธฐ๋ฅผ ์ ๊ทน ๊ถ์ฅํฉ๋๋ค.
pip install deepspeed
pip install transformers[deepspeed]
๋ฉ๋ชจ๋ฆฌ ์๊ตฌ๋[[memory-requirements]]
์์ํ๊ธฐ ์ ์ ๋ชจ๋ธ์ ๋ง๋ ์ถฉ๋ถํ GPU ๋ฐ CPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋์ง ํ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. DeepSpeed๋ ํ์ํ CPU/GPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ถ์ ํ ์ ์๋ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋จ์ผ GPU์์ bigscience/T0_3B ๋ชจ๋ธ์ ๋ฉ๋ชจ๋ฆฌ ์๊ตฌ ์ฌํญ์ ์ถ์ ํ ์ ์์ต๋๋ค:
$ python -c 'from transformers import AutoModel; \
from deepspeed.runtime.zero.stage3 import estimate_zero3_model_states_mem_needs_all_live; \
model = AutoModel.from_pretrained("bigscience/T0_3B"); \
estimate_zero3_model_states_mem_needs_all_live(model, num_gpus_per_node=1, num_nodes=1)'
[...]
Estimated memory needed for params, optim states and gradients for a:
HW: Setup with 1 node, 1 GPU per node.
SW: Model with 2783M total params, 65M largest layer params.
per CPU | per GPU | Options
70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=1
70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu , zero_init=0
62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=1
62.23GB | 5.43GB | offload_param=none, offload_optimizer=cpu , zero_init=0
0.37GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=1
15.56GB | 46.91GB | offload_param=none, offload_optimizer=none, zero_init=0
์ฆ, CPU ์คํ๋ก๋๊ฐ ์๋ ๋จ์ผ 80GB GPU ๋๋ ์คํ๋ก๋ ํ 8GB GPU์ ์ต๋ 60GB CPU๊ฐ ํ์ํฉ๋๋ค (์ด๋ ๋งค๊ฐ๋ณ์, ์ต์ ํ ์ํ ๋ฐ ๊ทธ๋ ์ด๋์ธํธ์ ๋ํ ๋ฉ๋ชจ๋ฆฌ ์๊ตฌ ์ฌํญ์ผ ๋ฟ์ด๋ฉฐ CUDA ์ปค๋ ๋ฐ ํ์ฑํ์๋ ์กฐ๊ธ ๋ ํ์ํฉ๋๋ค). ๋ํ ๋ ์์ GPU๋ฅผ ๋์ฌํ๊ฑฐ๋ ๊ตฌ์ ํ๋ ๊ฒ์ด ๋ ์ ๋ ดํ์ง๋ง ๋ชจ๋ธ์ ํ๋ จํ๋ ๋ฐ ์๊ฐ์ด ๋ ์ค๋ ๊ฑธ๋ฆฌ๋ฏ๋ก ๋น์ฉ๊ณผ ์๋ ๊ฐ์ ๊ท ํ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ถฉ๋ถํ๋ค๋ฉด CPU/NVMe ์คํ๋ก๋๋ฅผ ๋นํ์ฑํํ์ฌ ๋ชจ๋ ์์ ์ ๋ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ธ์.
ZeRO ๋จ๊ณ ์ค์ ํ๊ธฐ[[select-a-zero-stage]]
DeepSpeed๋ฅผ ์ค์นํ๊ณ ๋ฉ๋ชจ๋ฆฌ ์๊ตฌ ์ฌํญ์ ๋ ์ ํ์ ํ๋ค๋ฉด ๋ค์ ๋จ๊ณ๋ ์ฌ์ฉํ ZeRO ์คํ ์ด์ง๋ฅผ ์ ํํ๋ ๊ฒ์ ๋๋ค. ๊ฐ์ฅ ๋น ๋ฅด๊ณ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด ๋์ ์์๋๋ก ์ ๋ ฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
| ์๋ | ๋ฉ๋ชจ๋ฆฌ ํจ์จ |
|---|---|
| ZeRO-1 | ZeRO-3 + offload |
| ZeRO-2 | ZeRO-3 |
| ZeRO-2 + offload | ZeRO-2 + offload |
| ZeRO-3 | ZeRO-2 |
| ZeRO-3 + offload | ZeRO-1 |
์์ ์๊ฒ ๊ฐ์ฅ ์ ํฉํ ๋ฐฉ๋ฒ์ ์ฐพ์ผ๋ ค๋ฉด ๊ฐ์ฅ ๋น ๋ฅธ ๋ฐฉ๋ฒ๋ถํฐ ์์ํ๊ณ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ๋ฉด ๋ ๋๋ฆฌ์ง๋ง ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด ๋์ ๋ค์ ๋จ๊ณ๋ฅผ ์๋ํ์ธ์. ์๋์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฌ์ด์ ์ ์ ํ ๊ท ํ์ ์ฐพ๊ธฐ ์ํด (๊ฐ์ฅ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ ์ด๊ฑฐ๋ ๊ฐ์ฅ ๋น ๋ฅธ ๊ฒ๋ถํฐ ์์ํ์ฌ) ์ํ๋ ๋ฐฉํฅ์ผ๋ก ์์ ๋กญ๊ฒ ์์ ํ์ธ์.
์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ํ๋ก์ธ์ค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค(๋ฐฐ์น ํฌ๊ธฐ 1๋ก ์์):
- ๊ทธ๋ ์ด๋์ธํธ ์ฒดํฌํฌ์ธํ ํ์ฑํ
- ZeRO-2 ์๋
- ZeRO-2์ ๋งค๊ฐ๋ณ์ ์คํ๋ก๋ ์๋
- ZeRO-3 ์๋
- ZeRO-3๊ณผ ๋งค๊ฐ๋ณ์ CPU ์คํ๋ก๋ ์๋
- ZeRO-3, ๋งค๊ฐ๋ณ์์ ์ตํฐ๋ง์ด์ CPU ์คํ๋ก๋ ์๋
- [
~GenerationMixin.generate] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ ์ข์ ๋น ์์น ๊ฒ์ ๋ฒ์์ ๊ฐ์ ๋ค์ํ ๊ธฐ๋ณธ๊ฐ์ ๋ฎ์ถฐ๋ณด๊ธฐ - ์ ์ฒด ์ ๋ฐ๋ ๊ฐ์ค์น๋ณด๋ค ๋ฐ์ ๋ฐ๋(๊ตฌํ GPU ๊ตฌ์กฐ์ ๊ฒฝ์ฐ fp16, ์ํ์ด ์ดํ GPU์ ๊ฒฝ์ฐ bf16)๋ฅผ ํผํฉํด๋ณด๊ธฐ
- ๊ฐ๋ฅํ๋ฉด ํ๋์จ์ด๋ฅผ ๋ ์ถ๊ฐํ๊ฑฐ๋ Infinity๊ฐ ๋งค๊ฐ๋ณ์์ ์ตํฐ๋ง์ด์ ๋ฅผ NVMe๋ก ์คํ๋ก๋ํ๋๋ก ํ์ฑํ
- ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ์ง ์์ผ๋ฉด ์ ํจ ์ฒ๋ฆฌ๋์ ์ธก์ ํ ๋ค์ ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ์ต๋ํ ํฌ๊ฒ ๋๋ ค GPU ํจ์จ์ฑ์ ๊ทน๋ํ
- ๋ง์ง๋ง์ผ๋ก ์ผ๋ถ ์คํ๋ก๋ ๊ธฐ๋ฅ์ ๋นํ์ฑํํ๊ฑฐ๋ ๋ ๋น ๋ฅธ ZeRO ์คํ ์ด์ง๋ฅผ ์ฌ์ฉํ๊ณ ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ๋๋ฆฌ๊ฑฐ๋ ์ค์ฌ ์๋์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ฐ์ ์ต์ ์ ๊ท ํ์ ์ฐพ์ ํธ๋ ์ด๋ ์ค์ ์ ์ต์ ํ
DeepSpeed ๊ตฌ์ฑ ํ์ผ[[deepspeed-configuration-file]]
DeepSpeed๋ ํธ๋ ์ด๋ ์คํ ๋ฐฉ๋ฒ์ ๊ตฌ์ฑํ๋ ๋ชจ๋ ๋งค๊ฐ๋ณ์๊ฐ ํฌํจ๋ ๊ตฌ์ฑ ํ์ผ์ ํตํด [Trainer] ํด๋์ค์ ํจ๊ป ์๋ํฉ๋๋ค. ํธ๋ ์ด๋ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ฉด DeepSpeed๋ [Trainer]๋ก๋ถํฐ ๋ฐ์ ๊ตฌ์ฑ์ ์ฝ์์ ๊ธฐ๋กํ๋ฏ๋ก ์ด๋ค ๊ตฌ์ฑ์ด ์ฌ์ฉ๋์๋์ง ์ ํํ ํ์ธํ ์ ์์ต๋๋ค.
DeepSpeed ๊ตฌ์ฑ ์ต์ ์ ์ ์ฒด ๋ชฉ๋ก์ DeepSpeed Configuration JSON์์ ํ์ธํ ์ ์์ต๋๋ค. ๋ํ DeepSpeedExamples ๋ฆฌํฌ์งํ ๋ฆฌ ๋๋ ๊ธฐ๋ณธ DeepSpeed ๋ฆฌํฌ์งํ ๋ฆฌ์์ ๋ค์ํ DeepSpeed ๊ตฌ์ฑ ์์ ์ ๋ํ ๋ณด๋ค ์ค์ฉ์ ์ธ ์์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๊ตฌ์ฒด์ ์ธ ์์ ๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ์ผ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์ธ์:
git clone https://github.com/deepspeedai/DeepSpeedExamples
cd DeepSpeedExamples
find . -name '*json'
# Lamb ์ตํฐ๋ง์ด์ ์ํ ์ฐพ๊ธฐ
grep -i Lamb $(find . -name '*json')
๋ช
๋ น์ค ์ธํฐํ์ด์ค์์ ํธ๋ ์ด๋ํ๋ ๊ฒฝ์ฐ DeepSpeed ๊ตฌ์ฑ ํ์ผ์ JSON ํ์ผ์ ๊ฒฝ๋ก๋ก ์ ๋ฌ๋๊ฑฐ๋ ๋
ธํธ๋ถ ์ค์ ์์ [Trainer]๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ค์ฒฉ๋ dict ๊ฐ์ฒด๋ก ์ ๋ฌ๋ฉ๋๋ค.
TrainingArguments(..., deepspeed="path/to/deepspeed_config.json")
ds_config_dict = dict(scheduler=scheduler_params, optimizer=optimizer_params)
args = TrainingArguments(..., deepspeed=ds_config_dict)
trainer = Trainer(model, args, ...)
DeepSpeed์ Trainer ๋งค๊ฐ๋ณ์[[deepspeed-and-trainer-parameters]]
๊ตฌ์ฑ ๋งค๊ฐ๋ณ์์๋ ์ธ ๊ฐ์ง ์ ํ์ด ์์ต๋๋ค:
์ผ๋ถ ๊ตฌ์ฑ ๋งค๊ฐ๋ณ์๋ [
Trainer]์ DeepSpeed๊ฐ ๊ณต์ ํ๋ฉฐ, ์ ์๊ฐ ์ถฉ๋ํ๋ ๊ฒฝ์ฐ ์ค๋ฅ๋ฅผ ์๋ณํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ณต์ ๊ตฌ์ฑ ๋งค๊ฐ๋ณ์๋ [Trainer] ๋ช ๋ น์ค ์ธ์์์ ์ฝ๊ฒ ์ค์ ํ ์ ์์ต๋๋ค.๋ชจ๋ธ ์ค์ ์์ ์๋์ผ๋ก ๋์ถ๋๋ ์ผ๋ถ ์ค์ ๋งค๊ฐ๋ณ์๋ ์๋์ผ๋ก ๊ฐ์ ์กฐ์ ํ ํ์๊ฐ ์์ต๋๋ค. [
Trainer]๋ ๊ตฌ์ฑ ๊ฐauto๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฅ ์ ํํ๊ฑฐ๋ ํจ์จ์ ์ธ ๊ฐ์ ์ค์ ํฉ๋๋ค. ์ง์ ๊ตฌ์ฑ ๋งค๊ฐ๋ณ์๋ฅผ ๋ช ์์ ์ผ๋ก ์ค์ ํ ์๋ ์์ง๋ง, [Trainer] ์ธ์์ DeepSpeed ์ค์ ๋งค๊ฐ๋ณ์๊ฐ ์ผ์นํ๋๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค. ์ผ์นํ์ง ์์ผ๋ฉด ๊ฐ์งํ๊ธฐ ๋งค์ฐ ์ด๋ ค์ด ๋ฐฉ์์ผ๋ก ํ๋ จ์ด ์คํจํ ์ ์์ต๋๋ค!๊ต์ก ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ์๋์ผ๋ก ์ค์ ํด์ผ ํ๋ ์ผ๋ถ ์ค์ ๋งค๊ฐ๋ณ์๋ DeepSpeed์๋ง ํด๋น๋ฉ๋๋ค.
DeepSpeed ๊ตฌ์ฑ์ ์์ ํ๊ณ [TrainingArguments]๋ฅผ ํธ์งํ ์๋ ์์ต๋๋ค:
- ๊ธฐ๋ณธ ๊ตฌ์ฑ์ผ๋ก ์ฌ์ฉํ DeepSpeed ๊ตฌ์ฑ ํ์ผ์ ์์ฑํ๊ฑฐ๋ ๋ก๋ํฉ๋๋ค.
- ๋ค์ DeepSpeed ๊ตฌ์ฑ์ ๊ธฐ๋ฐ์ผ๋ก [
TrainingArguments] ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
scheduler.params.total_num_steps์ ๊ฐ์ ์ผ๋ถ ๊ฐ์ ํธ๋ ์ด๋ ์ค [Trainer]์ ์ํด ๊ณ์ฐ๋ฉ๋๋ค.
ZeRO ๊ตฌ์ฑ[[zero-configuration]]
์ธ ๊ฐ์ง ๊ตฌ์ฑ์ด ์์ผ๋ฉฐ, ๊ฐ ๊ตฌ์ฑ์ ์๋ก ๋ค๋ฅธ ZeRO ๋จ๊ณ์ ํด๋นํฉ๋๋ค. 1๋จ๊ณ๋ ํ์ฅ์ฑ ์ธก๋ฉด์์ ๊ทธ๋ค์ง ๋์ฌ๊ฒจ๋ณผ๋งํ์ง ์์ผ๋ฏ๋ก ์ด ๊ฐ์ด๋์์๋ 2๋จ๊ณ์ 3๋จ๊ณ์ ์ค์ ์ ๋ก๋๋ค. zero_optimization ๊ตฌ์ฑ์๋ ํ์ฑํํ ํญ๋ชฉ๊ณผ ๊ตฌ์ฑ ๋ฐฉ๋ฒ์ ๋ํ ๋ชจ๋ ์ต์
์ด ํฌํจ๋์ด ์์ต๋๋ค. ๊ฐ ๋งค๊ฐ๋ณ์์ ๋ํ ์์ธํ ์ค๋ช
์ DeepSpeed ๊ตฌ์ฑ JSON ์ฐธ์กฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
[Trainer]๋ ๋๋ฑํ ๋ช
๋ น์ค ์ธ์๋ฅผ ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก ๋ค์ ๊ตฌ์ฑ์ DeepSpeed๋ก ์ค์ ํด์ผ ํฉ๋๋ค.
ZeRO-1์ ์ตํฐ๋ง์ด์ ์ํ๋ฅผ GPU์ ๋ถํ ํ์ฌ ์ฝ๊ฐ์ ์๋ ํฅ์์ ๊ธฐ๋ํ ์ ์์ต๋๋ค. ZeRO-1 ๊ตฌ์ฑ์ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ ์ ์์ต๋๋ค:
{
"zero_optimization": {
"stage": 1
}
}
ZeRO-2๋ GPU์์ ์ตํฐ๋ง์ด์ ์ ๊ทธ๋ ์ด๋์ธํธ๋ฅผ ๋ถํ ํฉ๋๋ค. ์ด ๋จ๊ณ๋ ์ถ๋ก ๊ณผ ๊ด๋ จ์ด ์๋ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ์ฃผ๋ก ํ๋ จ์ ์ฌ์ฉ๋ฉ๋๋ค. ๋ ๋์ ์ฑ๋ฅ์ ์ํด ๊ตฌ์ฑํด์ผ ํ ๋ช ๊ฐ์ง ์ค์ํ ๋งค๊ฐ๋ณ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- GPU ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๋ ค๋ฉด
offload_optimizer๋ฅผ ํ์ฑํํด์ผ ํฉ๋๋ค. true๋ก ์ค์ ๋ ๊ฒฝ์ฐoverlap_comm์ GPU ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฆ๊ฐ๋ฅผ ์์ํ์ฌ ์ง์ฐ ์๊ฐ์ ์ค์ ๋๋ค. ์ด ๊ธฐ๋ฅ์ 4.5๋ฐฐ์allgather_bucket_size๋ฐreduce_bucket_size๊ฐ์ ์ฌ์ฉํฉ๋๋ค. ์ด ์์์๋5e8๋ก ์ค์ ๋์ด ์์ผ๋ฏ๋ก 9GB์ GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ 8GB ์ดํ์ธ ๊ฒฝ์ฐ, ๋ฉ๋ชจ๋ฆฌ ์๊ตฌ๋์ ๋ฎ์ถ๊ณ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ(OOM) ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํดoverlap_comm์ ์ค์ฌ์ผ ํฉ๋๋ค.allgather_bucket_size์reduce_bucket_size๋ ์ฌ์ฉ ๊ฐ๋ฅํ GPU ๋ฉ๋ชจ๋ฆฌ์ ํต์ ์๋๋ฅผ ์ ์ถฉํฉ๋๋ค. ๊ฐ์ด ์์์๋ก ํต์ ์๋๊ฐ ๋๋ ค์ง๊ณ ๋ ๋ง์ GPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฐฐ์น ํฌ๊ธฐ๊ฐ ํฐ ๊ฒ์ด ์ฝ๊ฐ ๋๋ฆฐ ํ๋ จ ์๊ฐ๋ณด๋ค ๋ ์ค์ํ์ง ๊ท ํ์ ๋ง์ถ ์ ์์ต๋๋ค.- DeepSpeed 0.4.4์์๋ CPU ์คํ๋ก๋ฉ์ ์ํด
round_robin_gradients๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ธ๋ถํ๋ ๊ทธ๋ ์ด๋์ธํธ ํํฐ์ ๋์ ํตํด ๋ฑ๊ธ ๊ฐ ๊ทธ๋ ์ด๋์ธํธ ๋ณต์ฌ๋ฅผ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ๋ณ๋ ฌํํฉ๋๋ค. ์ฑ๋ฅ ์ด์ ์ ๊ทธ๋ ์ด๋์ธํธ ๋์ ๋จ๊ณ(์ต์ ํ ๋จ๊ณ ๊ฐ ๋ณต์ฌ ํ์ ์ฆ๊ฐ) ๋๋ GPU ์(๋ณ๋ ฌ ์ฒ๋ฆฌ ์ฆ๊ฐ)์ ๋ฐ๋ผ ์ฆ๊ฐํฉ๋๋ค.
{
"zero_optimization": {
"stage": 2,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"allgather_partitions": true,
"allgather_bucket_size": 5e8,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 5e8,
"contiguous_gradients": true
"round_robin_gradients": true
}
}
ZeRO-3๋ ์ตํฐ๋ง์ด์ , ๊ทธ๋๋์ธํธ, ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ๋ฌ GPU์ ๊ฑธ์ณ ๋ถํ ํฉ๋๋ค. ZeRO-2์ ๋ฌ๋ฆฌ ZeRO-3๋ ์ฌ๋ฌ GPU์ ๋๊ท๋ชจ ๋ชจ๋ธ์ ๊ฐ์ ธ์ฌ ์ ์๊ธฐ ๋๋ฌธ์ ํ๋ จ ์ธ์๋ ์ถ๋ก ์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ตฌ์ฑํด์ผ ํ ๋ช ๊ฐ์ง ์ค์ํ ๋งค๊ฐ๋ณ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
device: "cpu"๋ GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ๊ณ ์ฌ์ฉ ๊ฐ๋ฅํ CPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋ ๊ฒฝ์ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ชจ๋ธ ๋งค๊ฐ๋ณ์๋ฅผ CPU๋ก ์คํ๋ก๋ํ ์ ์์ต๋๋ค.pin_memory: true๋ ์ฒ๋ฆฌ๋์ ํฅ์์ํฌ ์ ์์ง๋ง, ํ ๋ฉ๋ชจ๋ฆฌ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ฒญํ ํน์ ํ๋ก์ธ์ค๋ฅผ ์ํด ์์ฝ๋์ด ์๊ณ ์ผ๋ฐ์ ์ผ๋ก ์ผ๋ฐ CPU ๋ฉ๋ชจ๋ฆฌ๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๊ฒ ์ก์ธ์ค๋๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํ๋ก์ธ์ค์์ ์ฌ์ฉํ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ค์ด๋ญ๋๋ค.stage3_max_live_parameters๋ ํน์ ์๊ฐ์ GPU์ ์ ์งํ๋ ค๋ ์ ์ฒด ๋งค๊ฐ๋ณ์์ ์ํ๊ฐ์ ๋๋ค. OOM ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ด ๊ฐ์ ์ค์ด์ธ์.stage3_max_reuse_distance๋ ํฅํ ๋งค๊ฐ๋ณ์๋ฅผ ๋ค์ ์ฌ์ฉํ ์๊ธฐ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฐ์ผ๋ก, ๋งค๊ฐ๋ณ์๋ฅผ ๋ฒ๋ฆด์ง ์ ์งํ ์ง ๊ฒฐ์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฌ์ฉํ ๊ฒฝ์ฐ(stage3_max_reuse_distance๋ณด๋ค ์์ ๊ฐ์ธ ๊ฒฝ์ฐ) ํต์ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ธฐ ์ํด ๋งค๊ฐ๋ณ์๋ฅผ ์ ์งํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ์ฑํ ์ฒดํฌํฌ์ธํ ์ด ํ์ฑํ๋์ด ์๊ณ ์ญ์ ํ ๊ณ์ฐ์๊น์ง ์์ ํ ์์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์งํ๋ ค๋ ๊ฒฝ์ฐ์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ OOM ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ด ๊ฐ์ ์ค์ด์ธ์.๋ชจ๋ธ ์ ์ฅ ์
stage3_gather_16bit_weights_on_model_save๋ fp16 ๊ฐ์ค์น๋ฅผ ํตํฉํฉ๋๋ค. ๋๊ท๋ชจ ๋ชจ๋ธ์ ํ์ตํ๊ฑฐ๋ ์ฌ๋ฌ GPU๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ์ธก๋ฉด์์ ๋น์ฉ์ด ๋ง์ด ๋ญ๋๋ค. ํ๋ จ์ ์ฌ๊ฐํ ๊ณํ์ด๋ผ๋ฉด ์ด ์ต์ ์ ํ์ฑํํด์ผ ํฉ๋๋ค.sub_group_size๋ ์ต์ ํ ๋จ๊ณ์์ ์ ๋ฐ์ดํธ๋๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ดํฉ๋๋ค. ๋งค๊ฐ๋ณ์๋sub_group_size์ ๋ฒํท์ผ๋ก ๊ทธ๋ฃนํ๋๋ฉฐ ๊ฐ ๋ฒํท์ ํ ๋ฒ์ ํ๋์ฉ ์ ๋ฐ์ดํธ๋ฉ๋๋ค. NVMe ์คํ๋ก๋์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐsub_group_size๋ ์ต์ ํ ๋จ๊ณ ์ค ๋ชจ๋ธ ์ํ๊ฐ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ์ด๋ํ๋ ์์ ์ ๊ฒฐ์ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋งค์ฐ ํฐ ๋ชจ๋ธ์ CPU ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. NVMe ์คํ๋ก๋๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐsub_group_size๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ ์ ์์ง๋ง, ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์ข์ต๋๋ค:- ์ตํฐ๋ง์ด์ ๋จ๊ณ์์ OOM ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ, ์์ ๋ฒํผ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๋ ค๋ฉด
sub_group_size๋ฅผ ์ค์ด์ธ์. - ์ตํฐ๋ง์ด์ ๋จ๊ณ์์ ์๊ฐ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฝ๋๋ค. ์ด ๊ฒฝ์ฐ ๋ฐ์ดํฐ ๋ฒํผ ์ฆ๊ฐ๋ก ์ธํ ๋์ญํญ ์ฌ์ฉ๋ฅ ์ ๊ฐ์ ํ๊ธฐ ์ํด
sub_group_size๋ฅผ ๋๋ฆฌ์ธ์.
- ์ตํฐ๋ง์ด์ ๋จ๊ณ์์ OOM ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ, ์์ ๋ฒํผ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๋ ค๋ฉด
reduce_bucket_size,stage3_prefetch_bucket_size,stage3_param_persistence_threshold๋ ๋ชจ๋ธ์ ์จ๊ฒจ์ง ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์ด ๊ฐ๋ค์auto์ผ๋ก ์ค์ ํ๊ณ [Trainer]๊ฐ ์๋์ผ๋ก ๊ฐ์ ํ ๋นํ๋๋ก ํ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
{
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
},
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
}
}
deepspeed.zero.Init ์ปจํ
์คํธ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ธ์ ๋ ๋น ๋ฅด๊ฒ ์ด๊ธฐํํ ์ ์์ต๋๋ค:
from transformers import T5ForConditionalGeneration, T5Config
import deepspeed
with deepspeed.zero.Init():
config = T5Config.from_pretrained("google-t5/t5-small")
model = T5ForConditionalGeneration(config)
์ฌ์ ํ์ต๋ ๋ชจ๋ธ์ ๊ฒฝ์ฐ, ๋ฅ์คํผ๋ ๊ตฌ์ฑ ํ์ผ์ is_deepspeed_zero3_enabled: true๊ฐ [TrainingArguments]์ ์ค์ ๋์ด ์์ด์ผ ํ๋ฉฐ, ZeRO ๊ตฌ์ฑ์ด ํ์ฑํ๋์ด ์์ด์ผ ํฉ๋๋ค. ํ๋ จ๋ ๋ชจ๋ธ [~PreTrainedModel.from_pretrained]์ ํธ์ถํ๊ธฐ ์ ์ [TrainingArguments] ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
from transformers import AutoModel, Trainer, TrainingArguments
training_args = TrainingArguments(..., deepspeed=ds_config)
model = AutoModel.from_pretrained("google-t5/t5-small")
trainer = Trainer(model=model, args=training_args, ...)
fp16 ๊ฐ์ค์น๊ฐ ๋จ์ผ GPU์ ๋ง์ง ์๋ ๊ฒฝ์ฐ ZeRO-3์ด ํ์ํฉ๋๋ค. fp16 ๊ฐ์ค์น๋ฅผ ๋ก๋ํ ์ ์๋ ๊ฒฝ์ฐ, [~PreTrainedModel.from_pretrained]์ torch_dtype=torch.float16์ ์ง์ ํด์ผ ํฉ๋๋ค.
ZeRO-3์ ๋ ๋ค๋ฅธ ๊ณ ๋ ค ์ฌํญ์ ์ฌ๋ฌ ๊ฐ์ GPU๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ์ฌ ์คํ ์ค์ธ ๋ ์ด์ด์ ๋งค๊ฐ๋ณ์๊ฐ ์๋ ํ ๋จ์ผ GPU์ ๋ชจ๋ ๋งค๊ฐ๋ณ์๊ฐ ์๋ค๋ ๊ฒ์
๋๋ค. ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ ๊ฐ์ค์น๋ฅผ [~PreTrainedModel.from_pretrained]์ ๋ก๋ํ๋ ๋ฑ ๋ชจ๋ ๋ ์ด์ด์ ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ํ ๋ฒ์ ์ก์ธ์คํ๋ ค๋ฉด ํ ๋ฒ์ ํ๋์ ๋ ์ด์ด๋ฅผ ๋ก๋ํ๊ณ ์ฆ์ ๋ชจ๋ GPU์ ํํฐ์
๋ํฉ๋๋ค. ์ด๋ ๋งค์ฐ ํฐ ๋ชจ๋ธ์ ๊ฒฝ์ฐ ๋ฉ๋ชจ๋ฆฌ ์ ํ์ผ๋ก ์ธํด ํ๋์ GPU์ ๊ฐ์ค์น๋ฅผ ๋ก๋ํ ๋ค์ ๋ค๋ฅธ GPU์ ๋ถ์ฐํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ๋ณด์ด๋ ๋ชจ๋ธ ๋งค๊ฐ๋ณ์ ๊ฐ์ค์น(์ฌ๊ธฐ์ tensor([1.])) ๋๋ ๋งค๊ฐ๋ณ์ ํฌ๊ธฐ๊ฐ ๋ ํฐ ๋ค์ฐจ์ ํํ ๋์ 1์ธ ๊ฒฝ์ฐ, ์ด๋ ๋งค๊ฐ๋ณ์๊ฐ ๋ถํ ๋์ด ์์ผ๋ฉฐ ์ด๊ฒ์ด ZeRO-3 ํ๋ ์ด์คํ๋์ธ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
tensor([1.0], device="cuda:0", dtype=torch.float16, requires_grad=True)
ZeRO-3๋ก ๋๊ท๋ชจ ๋ชจ๋ธ์ ์ด๊ธฐํํ๊ณ ๋งค๊ฐ๋ณ์์ ์ก์ธ์คํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ธํ ๋ด์ฉ์ Constructing Massive Models ๋ฐ Gathering Parameters ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
NVMe ์ค์ [[nvme-configuration]]
ZeRO-Infinity๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ธ ์ํ๋ฅผ CPU ๋ฐ/๋๋ NVMe๋ก ์คํ๋ก๋ํ์ฌ ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ ์ ์์ต๋๋ค. ์ค๋งํธ ํํฐ์ ๋ ๋ฐ ํ์ผ๋ง ์๊ณ ๋ฆฌ์ฆ์ ํตํด ๊ฐ GPU๋ ์คํ๋ก๋ฉ ์ค์ ๋งค์ฐ ์ ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์์ผ๋ฏ๋ก ์ต์ NVMe๋ ํ๋ จ ํ๋ก์ธ์ค์ ์ฌ์ฉํ ์ ์๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ํฐ ์ด ๋ฉ๋ชจ๋ฆฌ ํ์ ๋ง์ถ ์ ์์ต๋๋ค. ZeRO-Infinity์๋ ZeRO-3๊ฐ ํ์ํฉ๋๋ค.
์ฌ์ฉ ๊ฐ๋ฅํ CPU ๋ฐ/๋๋ NVMe ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ๋ผ ์ตํฐ๋ง์ด์ ์ ๋งค๊ฐ๋ณ์ ์ค ํ๋๋ง ์คํ๋ก๋ํ๊ฑฐ๋ ์๋ฌด๊ฒ๋ ์คํ๋ก๋ํ์ง ์์ ์ ์์ต๋๋ค. ๋ํ ์ผ๋ฐ ํ๋ ๋๋ผ์ด๋ธ๋ ์๋ฆฌ๋ ์คํ
์ดํธ ๋๋ผ์ด๋ธ์์๋ ์๋ํ์ง๋ง ์๋๊ฐ ํ์ ํ ๋๋ ค์ง๋ฏ๋ก nvme_path๊ฐ NVMe ์ฅ์น๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ์ต์ NVMe๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๊ธฐ ์์
์ ๊ฒฝ์ฐ ์ต๋ 3.5GB/s, ์ฐ๊ธฐ ์์
์ ๊ฒฝ์ฐ ์ต๋ 3GB/s์ ์ ์ก ์๋๋ฅผ ๊ธฐ๋ํ ์ ์์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก, ํธ๋ ์ด๋ ์ค์ ์์ ๋ฒค์น๋งํฌ ์คํํ๊ธฐ์ ํตํด ์ต์ ์ 'aio' ๊ตฌ์ฑ์ ๊ฒฐ์ ํฉ๋๋ค.
์๋ ์์ ZeRO-3/Infinity ๊ตฌ์ฑ ํ์ผ์ ๋๋ถ๋ถ์ ๋งค๊ฐ๋ณ์ ๊ฐ์ auto์ผ๋ก ์ค์ ํ๊ณ ์์ง๋ง, ์๋์ผ๋ก ๊ฐ์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
{
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "nvme",
"nvme_path": "/local_nvme",
"pin_memory": true,
"buffer_count": 4,
"fast_init": false
},
"offload_param": {
"device": "nvme",
"nvme_path": "/local_nvme",
"pin_memory": true,
"buffer_count": 5,
"buffer_size": 1e8,
"max_in_cpu": 1e9
},
"aio": {
"block_size": 262144,
"queue_depth": 32,
"thread_count": 1,
"single_submit": false,
"overlap_events": true
},
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"steps_per_print": 2000,
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"wall_clock_breakdown": false
}
DeepSpeed ๊ตฌ์ฑ[[deepspeed-features]]
์ด ์น์ ์์ ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ๋ ๋ช ๊ฐ์ง ์ค์ํ ๋งค๊ฐ๋ณ์๋ฅผ DeepSpeed ๊ตฌ์ฑ ํ์ผ์ ์ง์ ํ ์ ์์ต๋๋ค.
ํ์ฑํ/๊ทธ๋ ์ด๋์ธํธ ์ฒดํฌํฌ์ธํ [[activationgradient-checkpointing]]
ํ์ฑํ ๋ฐ ๊ทธ๋ ์ด๋์ธํธ ์ฒดํฌํฌ์ธํ ์ ์๋๋ฅผ ๋ ๋ง์ GPU ๋ฉ๋ชจ๋ฆฌ์ ๊ตํํ์ฌ GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ ์ํฉ์ ๊ทน๋ณตํ๊ฑฐ๋ ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ๋๋ ค ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ์ฑํํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์ธ์:
- ํ๊น
ํ์ด์ค ๋ชจ๋ธ์ ๊ฒฝ์ฐ, [
Trainer]์์model.gradient_checkpointing_enable()๋๋--gradient_checkpointing์ ์ค์ ํฉ๋๋ค. - ํ๊น
ํ์ด์ค๊ฐ ์๋ ๋ชจ๋ธ์ ๊ฒฝ์ฐ, ๋ฅ์คํผ๋ Activation Checkpointing API๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํธ๋์คํฌ๋จธ ๋ชจ๋ธ๋ง ์ฝ๋๋ฅผ ๋์ฒดํ๊ณ
torch.utils.checkpoint๋ฅผ DeepSpeed API๋ก ๋์ฒดํ ์๋ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์๋ฐฉํฅ ํ์ฑํ๋ฅผ ๋ค์ ๊ณ์ฐํ๋ ๋์ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ์คํ๋ก๋ํ ์ ์์ผ๋ฏ๋ก ๋ ์ ์ฐํฉ๋๋ค.
์ตํฐ๋ง์ด์ ์ ์ค์ผ์ค๋ฌ[[optimizer-and-scheduler]]
offload_optimizer๋ฅผ ํ์ฑํํ์ง ์๋ ํ DeepSpeed์ ํธ๋์คํฌ๋จธ ์ตํฐ๋ง์ด์ ๋ฐ ์ค์ผ์ค๋ฌ๋ฅผ ํผํฉํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค. offload_optimizer๋ฅผ ํ์ฑํํ๋ฉด CPU์ GPU ๊ตฌํ์ด ๋ชจ๋ ์๋ ๊ฒฝ์ฐ DeepSpeed๊ฐ ์๋ ์ต์ ํ๊ธฐ(LAMB ์ ์ธ)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ตฌ์ฑ ํ์ผ์ ์ต์ ํ ํ๋ก๊ทธ๋จ ๋ฐ ์ค์ผ์ค๋ฌ ๋งค๊ฐ๋ณ์๋ ๋ช
๋ น์ค์์ ์ค์ ํ ์ ์์ผ๋ฏ๋ก ์ค๋ฅ๋ฅผ ์ฐพ๊ธฐ ์ด๋ ต์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํ์ต ์๋๊ฐ ๋ค๋ฅธ ๊ณณ์์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ค์ ๋ ๊ฒฝ์ฐ ๋ช
๋ น์ค์์ ์ด๋ฅผ ์ฌ์ ์ํ ์ ์์ต๋๋ค. ์ต์ ํ ํ๋ก๊ทธ๋จ ๋ฐ ์ค์ผ์ค๋ฌ ๋งค๊ฐ๋ณ์ ์ธ์๋ [Trainer] ๋ช
๋ น์ค ์ธ์๊ฐ DeepSpeed ๊ตฌ์ฑ๊ณผ ์ผ์นํ๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
DeepSpeed๋ ์ฌ๋ฌ ์ตํฐ๋ง์ด์ ๋ฅผ ์ ๊ณตํ์ง๋ง(Adam, AdamW, OneBitAdam ๋ฐ LAMB) PyTorch์์ ๋ค๋ฅธ ์ตํฐ๋ง์ด์ ๋ฅผ ๊ฐ์ ธ์ฌ ์๋ ์์ต๋๋ค. ์ค์ ์์ ์ตํฐ๋ง์ด์ ๋ฅผ ๊ตฌ์ฑํ์ง ์์ผ๋ฉด [Trainer]๊ฐ ์๋์ผ๋ก AdamW๋ฅผ ์ ํํ๊ณ ๋ช
๋ น์ค์์ ์ ๊ณต๋ ๊ฐ ๋๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํฉ๋๋ค: lr, adam_beta1, adam_beta2, adam_epsilon, weight_decay.
๋งค๊ฐ๋ณ์๋ฅผ "auto"์ผ๋ก ์ค์ ํ๊ฑฐ๋ ์ํ๋ ๊ฐ์ ์ง์ ์๋์ผ๋ก ์
๋ ฅํ ์ ์์ต๋๋ค.
{
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
}
}
์ต์์ ๊ตฌ์ฑ์ ๋ค์์ ์ถ๊ฐํ์ฌ ์ง์๋์ง ์๋ ์ตํฐ๋ง์ด์ ๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
{
"zero_allow_untested_optimizer": true
}
DeepSpeed==0.8.3๋ถํฐ ์คํ๋ก๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์คํ๋ก๋๊ฐ DeepSpeed์ CPU Adam ์ตํฐ๋ง์ด์ ์์ ๊ฐ์ฅ ์ ์๋ํ๋ฏ๋ก ์ต์์ ์์ค ๊ตฌ์ฑ์ ๋ค์ ์ฌํญ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
{
"zero_force_ds_cpu_optimizer": false
}
DeepSpeed๋ LRRangeTest, OneCycle, WarmupLR ๋ฐ WarmupDecayLR learning rateschedulers๋ฅผ ์ง์ํฉ๋๋ค.
ํธ๋์คํฌ๋จธ์ DeepSpeed๋ ๋์ผํ ๋ ๊ฐ์ง ์ค์ผ์ค๋ฌ๋ฅผ ์ ๊ณตํฉ๋๋ค:
- WarmupLR์ Transformers์
--lr_scheduler_type constant_warmup๊ณผ ๋์ผํฉ๋๋ค. - WarmupDecayLR์ Transformers์
--lr_scheduler_type linear์ ๋์ผํฉ๋๋ค(Transformers์์ ์ฌ์ฉ๋๋ ๊ธฐ๋ณธ ์ค์ผ์ค๋ฌ์ ๋๋ค).
์ค์ ์์ ์ค์ผ์ค๋ฌ๋ฅผ ๊ตฌ์ฑํ์ง ์์ผ๋ฉด[Trainer]๋ ์๋์ผ๋ก WarmupDecayLR์ ์ ํํ๊ณ ๋ช
๋ น์ค์์ ์ ๊ณต๋ ๊ฐ ๋๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํฉ๋๋ค: warmup_min_lr, warmup_max_lr, warmup_num_steps, total_num_steps (max_steps๊ฐ ์ ๊ณต๋์ง ์์ผ๋ฉด ๋ฐํ์ ์ค์ ์๋์ผ๋ก ๊ณ์ฐ๋จ).
๋งค๊ฐ๋ณ์๋ฅผ "auto"์ผ๋ก ์ค์ ํ๊ฑฐ๋ ์ํ๋ ๊ฐ์ ์ง์ ์๋์ผ๋ก ์
๋ ฅํ ์ ์์ต๋๋ค.
{
"scheduler": {
"type": "WarmupDecayLR",
"params": {
"total_num_steps": "auto",
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
}
}
์ ๋ฐ๋[[precision]]
DeepSpeed๋ fp32, fp16 ๋ฐ bf16 ํผํฉ ์ ๋ฐ๋๋ฅผ ์ง์ํฉ๋๋ค.
๋ชจ๋ธ์ด ํผํฉ ์ ๋ฐ๋๋ก ์ฌ์ ํ์ต๋์ง ์์ ๊ฒฝ์ฐ์ ๊ฐ์ด ํผํฉ ์ ๋ฐ๋๋ก ์ ์๋ํ์ง ์๋ ๊ฒฝ์ฐ NaN ์์ค์ ์ ๋ฐํ ์ ์๋ ์ค๋ฒํ๋ก ๋๋ ์ธ๋ํ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ fp16 ๋ชจ๋๋ฅผ ๋ช ์์ ์ผ๋ก ๋นํ์ฑํํ์ฌ ์ ์ฒด fp32 ์ ๋ฐ๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
{
"fp16": {
"enabled": false
}
}
Ampere GPU ๋ฐ PyTorch 1.7 ์ด์์ ๊ฒฝ์ฐ ์ผ๋ถ ์ฐ์ฐ์ ๋ํด ๋ ํจ์จ์ ์ธ tf32 ํ์์ผ๋ก ์๋ ์ ํ๋์ง๋ง ๊ฒฐ๊ณผ๋ ์ฌ์ ํ fp32๋ก ํ์๋ฉ๋๋ค. [Trainer]์์ --tf32๋ฅผ ์ค์ ํ์ฌ ํ์ฑํํ๊ณ --tf32 0 ๋๋ --no_tf32๋ฅผ ๋นํ์ฑํํ๋ฉด ์ ์ดํ ์ ์์ต๋๋ค.
PyTorch AMP์ ๊ฐ์ fp16 ํผํฉ ์ ๋ฐ๋๋ฅผ ๊ตฌ์ฑํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ค์ด๋ค๊ณ ํ๋ จ ์๋๊ฐ ๋นจ๋ผ์ง๋๋ค.[Trainer]๋ args.fp16_backend ๊ฐ์ ๋ฐ๋ผ fp16์ ์๋์ผ๋ก ํ์ฑํ ๋๋ ๋นํ์ฑํํ๋ฉฐ, ๋๋จธ์ง ๊ตฌ์ฑ์ ์ฌ์ฉ์๊ฐ ์ค์ ํ ์ ์์ต๋๋ค. ๋ช
๋ น์ค์์ ๋ค์ ์ธ์๋ฅผ ์ ๋ฌํ๋ฉด fp16์ด ํ์ฑํ๋ฉ๋๋ค: fp16, --fp16_backend amp ๋๋ --fp16_full_eval.
{
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
}
}
์ถ๊ฐ ๋ฅ์คํผ๋ fp16 ํ๋ จ ์ต์ ์ fp16 ํ๋ จ ์ต์ ์ฐธ์กฐ๋ฅผ ์ฐธ์กฐํ์ธ์.
Apex์ ๊ฐ์ fp16 ํผํฉ ์ ๋ฐ๋๋ฅผ ๊ตฌ์ฑํ๋ ค๋ฉด ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด "auto" ๋๋ ์ง์ ๊ฐ์ ์ค์ ํฉ๋๋ค.[Trainer]๋ args.fp16_backend ๋ฐ args.fp16_opt_level์ ๊ฐ์ ๋ฐ๋ผ amp๋ฅผ ์๋์ผ๋ก ๊ตฌ์ฑํฉ๋๋ค. ๋ค์ ์ธ์๋ฅผ ์ ๋ฌํ๋ฉด ๋ช
๋ น์ค์์ ํ์ฑํํ ์๋ ์์ต๋๋ค: fp16, --fp16_backend apex ๋๋ --fp16_opt_level 01.
{
"amp": {
"enabled": "auto",
"opt_level": "auto"
}
}
bf16์ ์ฌ์ฉํ๋ ค๋ฉด DeepSpeed==0.6.0 ์ด์์ด ํ์ํฉ๋๋ค. bf16์ fp32์ ๋์ ๋ฒ์๊ฐ ๋์ผํ๋ฉฐ ์์ค ์ค์ผ์ผ๋ง์ด ํ์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ gradient accumulation์ bf16๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ด ํ์์ ๋ฎ์ ์ ๋ฐ๋๋ก ์ธํด ์์ค์ด ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ์ํ์ง ์๋ ๊ทธ๋ ์ด๋์ธํธ๊ฐ bf16์ ๋์ ๋ ์ ์์ต๋๋ค.
bf16์ ์ค์ ํ์ผ์์ ์ค์ ํ๊ฑฐ๋ ๋ค์ ์ธ์๋ฅผ ์ ๋ฌํ๋ฉด ๋ช
๋ น์ค์์ ํ์ฑํํ ์ ์์ต๋๋ค: --bf16 ๋๋ --bf16_full_eval.
{
"bf16": {
"enabled": "auto"
}
}
๋ฐฐ์น ํฌ๊ธฐ[[batch-size]]
๋ฐฐ์น ํฌ๊ธฐ๋ ์๋์ผ๋ก ๊ตฌ์ฑํ๊ฑฐ๋ ๋ช
์์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. "auto" ์ต์
์ ์ฌ์ฉํ๋๋ก ์ ํํ๋ฉด [Trainer]๋ train_micro_batch_size_per_gpu๋ฅผ args.per_device_train_batch_size์ ๊ฐ์ผ๋ก, train_batch_size๋ฅผ args.world_size * args.per_device_train_batch_size * args.gradient_accumulation_steps๋ก ์ค์ ํฉ๋๋ค.
{
"train_micro_batch_size_per_gpu": "auto",
"train_batch_size": "auto"
}
๊ทธ๋ ์ด๋์ธํธ ๋์ [[gradient-accumulation]]
๊ทธ๋ ์ด๋์ธํธ ๋์ ์ ์๋์ผ๋ก ๊ตฌ์ฑํ๊ฑฐ๋ ๋ช
์์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. "auto" ์ต์
์ ์ฌ์ฉํ๋๋ก ์ ํํ๋ฉด [Trainer]๊ฐ args.gradient_accumulation_steps์ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
{
"gradient_accumulation_steps": "auto"
}
๊ทธ๋ ์ด๋์ธํธ ํด๋ฆฌํ[[gradient-clipping]]
๊ทธ๋ ์ด๋์ธํธ ํด๋ฆฌํ์ ์๋์ผ๋ก ๊ตฌ์ฑํ๊ฑฐ๋ ๋ช
์์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. "auto" ์ต์
์ ์ฌ์ฉํ๋๋ก ์ ํํ๋ฉด [Trainer]๊ฐ args.max_grad_norm์ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
{
"gradient_clipping": "auto"
}
ํต์ ๋ฐ์ดํฐ ์ ํ(Communication data type)[[communication-data-type]]
์ถ์, ์์ง ๋ฐ ๋ถ์ฐ ์์ ๊ณผ ๊ฐ์ ํต์ ์งํฉ์ฒด์ ๊ฒฝ์ฐ ๋ณ๋์ ๋ฐ์ดํฐ ์ ํ์ด ์ฌ์ฉ๋ฉ๋๋ค.
๋ชจ๋ ์์ง ๋ฐ ๋ถ์ฐ ์์ ์ ๋ฐ์ดํฐ์ ๋์ผํ ๋ฐ์ดํฐ ์ ํ์ผ๋ก ์ํ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด bf16์ผ๋ก ํ๋ จํ๋ ๊ฒฝ์ฐ, ์์ง์ ๋น์์ค ์ฐ์ฐ์ด๋ฏ๋ก ๋ฐ์ดํฐ๋ bf16์ผ๋ก ์์ง๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด ๊ทธ๋ ์ด๋์ธํธ๊ฐ ์ฌ๋ฌ GPU์ ๊ฑธ์ณ ํ๊ท ํ๋๋ ๊ฒฝ์ฐ์ ๊ฐ์ด ๊ฐ์ ์ฐ์ฐ์ ์์ค์ด ๋ฐ์ํฉ๋๋ค. ํต์ ์ด fp16 ๋๋ bf16์ผ๋ก ์ํ๋๋ ๊ฒฝ์ฐ, ๋ฎ์ ์ ๋ฐ๋๋ก ์ฌ๋ฌ ์ซ์๋ฅผ ๋ํ๋ฉด ์ ํํ์ง ์๊ธฐ ๋๋ฌธ์ ์์ค์ด ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋ ๋์ต๋๋ค. ํนํ fp16๋ณด๋ค ์ ๋ฐ๋๊ฐ ๋ฎ์ bf16์ ๊ฒฝ์ฐ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ์ด๋ฌํ ์ด์ ๋ก ๊ธฐ์ธ๊ธฐ๋ฅผ ํ๊ท ํํ ๋ ์์ค์ด ์ต์ํ๋๋ฏ๋ก ๊ฐ์ ์ฐ์ฐ์๋ fp16์ด ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
ํต์ ๋ฐ์ดํฐ ์ ํ์ ์ค์ ํ์ผ์์ communication_data_type ๋งค๊ฐ๋ณ์๋ฅผ ์ค์ ํ์ฌ ์ ํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, fp32๋ฅผ ์ ํํ๋ฉด ์ฝ๊ฐ์ ์ค๋ฒํค๋๊ฐ ์ถ๊ฐ๋์ง๋ง ๊ฐ์ ์ฐ์ฐ์ด fp32์ ๋์ ๋๊ณ ์ค๋น๊ฐ ๋๋ฉด ํ๋ จ ์ค์ธ ๋ฐ์ ๋ฐ dtype์ผ๋ก ๋ค์ด์บ์คํธ๋ฉ๋๋ค.
{
"communication_data_type": "fp32"
}
๋ชจ๋ธ ๋ฐฐํฌ[[deployment]]
torchrun, deepspeed ๋ฐ์ฒ ๋๋ Accelerate ๋ฑ ๋ค์ํ ๋ฐ์ฒ๋ฅผ ํตํด DeepSpeed๋ฅผ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ๋ฐฐํฌํ๋ ค๋ฉด [Trainer] ๋ช
๋ น์ค์ --deepspeed ds_config.json์ ์ถ๊ฐํฉ๋๋ค. ํ์ํ ๋ช
๋ น์ค ์ธ์๋ฅผ ์ฝ๋์ ์ถ๊ฐํ๋ ค๋ฉด DeepSpeed์ add_config_arguments ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ ๋ค์ํ ํธ๋ ์ด๋ ์ค์ ์ ๋ํด deepspeed ๋ฐ์ฒ๋ก DeepSpeed๋ฅผ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฝ๋๋ค. ๋ณด๋ค ์ค์ฉ์ ์ธ ์ฌ์ฉ ์์ ๋ ์ด post์์ ํ์ธํ ์ ์์ต๋๋ค.
์ฌ๋ฌ GPU์ DeepSpeed๋ฅผ ๋ฐฐํฌํ๋ ค๋ฉด --num_gpus ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ์ธ์. ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ GPU๋ฅผ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ --num_gpus๋ฅผ ์ถ๊ฐํ ํ์๊ฐ ์์ต๋๋ค. ์๋ ์์ ์์๋ 2๊ฐ์ GPU๋ฅผ ์ฌ์ฉํฉ๋๋ค.
deepspeed --num_gpus=2 examples/pytorch/translation/run_translation.py \
--deepspeed tests/deepspeed/ds_config_zero3.json \
--model_name_or_path google-t5/t5-small --per_device_train_batch_size 1 \
--output_dir output_dir --overwrite_output_dir --fp16 \
--do_train --max_train_samples 500 --num_train_epochs 1 \
--dataset_name wmt16 --dataset_config "ro-en" \
--source_lang en --target_lang ro
๋จ์ผ GPU์ DeepSpeed๋ฅผ ๋ฐฐํฌํ๋ ค๋ฉด --num_gpus ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ์ธ์. GPU๊ฐ 1๊ฐ๋ง ์๋ ๊ฒฝ์ฐ ์ด ๊ฐ์ ๋ช
์์ ์ผ๋ก ์ค์ ํ ํ์๋ ์์ต๋๋ค. DeepSpeed๋ ์ง์ ๋ ๋
ธ๋์์ ๋ณผ ์ ์๋ ๋ชจ๋ GPU๋ฅผ ๋ฐฐํฌํ๋ฏ๋ก ์ด ๊ฐ์ ๋ช
์์ ์ผ๋ก ์ค์ ํ ํ์๋ ์์ต๋๋ค.
deepspeed --num_gpus=1 examples/pytorch/translation/run_translation.py \
--deepspeed tests/deepspeed/ds_config_zero2.json \
--model_name_or_path google-t5/t5-small --per_device_train_batch_size 1 \
--output_dir output_dir --overwrite_output_dir --fp16 \
--do_train --max_train_samples 500 --num_train_epochs 1 \
--dataset_name wmt16 --dataset_config "ro-en" \
--source_lang en --target_lang ro
DeepSpeed๋ ๋จ ํ๋์ GPU๋ก๋ ์ฌ์ ํ ์ ์ฉํฉ๋๋ค:
- ์ผ๋ถ ๊ณ์ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ CPU๋ก ์คํ๋ก๋ํ์ฌ ๋ ํฐ ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ง์ง ์๋ ๋งค์ฐ ํฐ ๋ชจ๋ธ์ ๋ง์ถ๊ธฐ ์ํด ๋ชจ๋ธ์ ๋ ๋ง์ GPU ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
- ์ค๋งํธ GPU ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์์คํ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์กฐ๊ฐํ๋ฅผ ์ต์ํํ์ฌ ๋ ํฐ ๋ชจ๋ธ๊ณผ ๋ฐ์ดํฐ ๋ฐฐ์น์ ๋ง์ถ ์ ์์ต๋๋ค.
๋จ์ผ GPU์์ ๋ ๋์ ์ฑ๋ฅ์ ์ป์ผ๋ ค๋ฉด ZeRO-2 ๊ตฌ์ฑ ํ์ผ์์ allgather_bucket_size ๋ฐ reduce_bucket_size ๊ฐ์ 2e8๋ก ์ค์ ํ์ธ์.
๋ค์ค ๋ ธ๋ ํ๊ฒฝ์์์ ๋ชจ๋ธ ๋ฐฐํฌ[[multi-node-deployment]]
๋
ธ๋๋ ์ํฌ๋ก๋๋ฅผ ์คํํ๊ธฐ ์ํ ํ๋ ์ด์์ GPU์
๋๋ค. ๋ ๊ฐ๋ ฅํ ์ค์ ์ ๋ฉํฐ ๋
ธ๋ ์ค์ ์ผ๋ก, deepspeed ๋ฐ์ฒ๋ก ์คํํ ์ ์์ต๋๋ค. ์ด ๊ฐ์ด๋์์๋ ๊ฐ๊ฐ 8๊ฐ์ GPU๊ฐ ์๋ ๋ ๊ฐ์ ๋
ธ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋
ธ๋๋ ssh hostname1๋ก, ๋ ๋ฒ์งธ ๋
ธ๋๋ ssh hostname2๋ก ์ ์ํ ์ ์์ต๋๋ค. ๋ ๋
ธ๋ ๋ชจ๋ ๋น๋ฐ๋ฒํธ ์์ด ssh๋ฅผ ํตํด ๋ก์ปฌ๋ก ์๋ก ํต์ ํ ์ ์์ด์ผ ํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก DeepSpeed๋ ๋ฉํฐ๋
ธ๋ ํ๊ฒฝ์์ ๊ณต์ ์ ์ฅ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ๊ทธ๋ ์ง ์๊ณ ๊ฐ ๋
ธ๋๊ฐ ๋ก์ปฌ ํ์ผ ์์คํ
๋ง ๋ณผ ์ ์๋ ๊ฒฝ์ฐ, ๊ณต์ ํ์ผ ์์คํ
์ ๋ํ ์ก์ธ์ค ์์ด ๋ก๋ฉํ ์ ์๋๋ก checkpoint๋ฅผ ํฌํจํ๋๋ก ๊ตฌ์ฑ ํ์ผ์ ์กฐ์ ํด์ผ ํฉ๋๋ค:
{
"checkpoint": {
"use_node_local_storage": true
}
}
[Trainer]์ ``--save_on_each_node์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ์์checkpoint`๋ฅผ ๊ตฌ์ฑ์ ์๋์ผ๋ก ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
torchrun์ ๊ฒฝ์ฐ, ๊ฐ ๋ ธ๋์ ssh๋ก ์ ์ํ ํ ๋ ๋ ธ๋ ๋ชจ๋์์ ๋ค์ ๋ช ๋ น์ ์คํํด์ผ ํฉ๋๋ค. ๋ฐ์ฒ๋ ๋ ๋ ธ๋๊ฐ ๋๊ธฐํ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ํธ๋ ์ด๋์ ์์ํฉ๋๋ค.
torchrun --nproc_per_node=8 --nnode=2 --node_rank=0 --master_addr=hostname1 \
--master_port=9901 your_program.py <normal cl args> --deepspeed ds_config.json
deepspeed ๋ฐ์ฒ์ ๊ฒฝ์ฐ, ๋จผ์ hostfile์ ์์ฑํฉ๋๋ค.
hostname1 slots=8
hostname2 slots=8
๊ทธ๋ฐ ๋ค์ ๋ค์ ๋ช
๋ น์ด๋ก ํธ๋ ์ด๋์ ์์ํ ์ ์์ต๋๋ค. deepspeed ๋ฐ์ฒ๋ ๋ ๋
ธ๋์์ ๋์์ ๋ช
๋ น์ ์๋์ผ๋ก ์คํํฉ๋๋ค.
deepspeed --num_gpus 8 --num_nodes 2 --hostfile hostfile --master_addr hostname1 --master_port=9901 \
your_program.py <normal cl args> --deepspeed ds_config.json
๋ค์ค ๋ ธ๋ ์ปดํจํ ๋ฆฌ์์ค ๊ตฌ์ฑ์ ๋ํ ์์ธํ ๋ด์ฉ์ Resource Configuration (multi-node) ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
SLURM[[slurm]]
SLURM ํ๊ฒฝ์์๋ ํน์ SLURM ํ๊ฒฝ์ ๋ง๊ฒ SLURM ์คํฌ๋ฆฝํธ๋ฅผ ์กฐ์ ํด์ผ ํฉ๋๋ค.SLURM ์คํฌ๋ฆฝํธ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
#SBATCH --job-name=test-nodes # ์์
์ด๋ฆ
#SBATCH --nodes=2 # ๋
ธ๋ ์
#SBATCH --ntasks-per-node=1 # ์ค์ - ๋
ธ๋๋น ๋ถ์ฐ ์์
1๊ฐ!
#SBATCH --cpus-per-task=10 # ์์
๋น CPU ์ฝ์ด ์
#SBATCH --gres=gpu:8 # gpu ์
#SBATCH --time 20:00:00 # ์ต๋ ์คํ ์๊ฐ (HH:MM:SS)
#SBATCH --output=%x-%j.out # ์ถ๋ ฅ ํ์ผ ์ด๋ฆ
export GPUS_PER_NODE=8
export MASTER_ADDR=$(scontrol show hostnames $SLURM_JOB_NODELIST | head -n 1)
export MASTER_PORT=9901
srun --jobid $SLURM_JOBID bash -c 'python -m torch.distributed.run \
--nproc_per_node $GPUS_PER_NODE --nnodes $SLURM_NNODES --node_rank $SLURM_PROCID \
--master_addr $MASTER_ADDR --master_port $MASTER_PORT \
your_program.py <normal cl args> --deepspeed ds_config.json'
๊ทธ๋ฐ ๋ค์ ๋ชจ๋ ๋ ธ๋์์ ๋์์ ํ์ต์ ์์ํ๋ ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋ค์ค ๋ ธ๋ ๋ฐฐํฌ๋ฅผ ์์ฝํ ์ ์์ต๋๋ค.
sbatch launch.slurm
๋ ธํธ๋ถ[[notebook]]
deepspeed ๋ฐ์ฒ๋ ๋
ธํธ๋ถ์์์ ๋ฐฐํฌ๋ฅผ ์ง์ํ์ง ์์ผ๋ฏ๋ก ๋ถ์ฐ ํ๊ฒฝ์ ์๋ฎฌ๋ ์ด์
ํด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ด๋ 1๊ฐ์ GPU์์๋ง ์๋ํฉ๋๋ค. 1๊ฐ ์ด์์ GPU๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ฅ์คํผ๋๊ฐ ์๋ํ ์ ์๋ ๋ค์ค ํ๋ก์ธ์ค ํ๊ฒฝ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ฆ, ์ฌ๊ธฐ์ ํ์๋ ๊ฒ์ฒ๋ผ ์๋ฎฌ๋ ์ด์
ํ ์ ์๋ deepspeed ๋ฐ์ฒ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
# DeepSpeed๋ ๋จ์ผ ํ๋ก์ธ์ค๋ง ์ฌ์ฉํ๋๋ผ๋ ๋ถ์ฐ ํ๊ฒฝ์ ํ์๋ก ํฉ๋๋ค.
# ์ด ์ฝ๋๋ก ๋ถ์ฐ ํ๊ฒฝ์ ๋ชจ๋ฐฉํฉ๋๋ค.
import os
os.environ["MASTER_ADDR"] = "localhost"
os.environ["MASTER_PORT"] = "9994" # RuntimeError: Address already in use ์ค๋ฅ ๋ฐ์ ์ ์์
os.environ["RANK"] = "0"
os.environ["LOCAL_RANK"] = "0"
os.environ["WORLD_SIZE"] = "1"
# ์ด์ ํ์์ ๊ฐ์ด ์งํํ๋, DeepSpeed ์ค์ ํ์ผ์ ์ ๋ฌํฉ๋๋ค.
training_args = TrainingArguments(..., deepspeed="ds_config_zero3.json")
trainer = Trainer(...)
trainer.train()
ํ์ฌ ๋๋ ํฐ๋ฆฌ์ ๋ ธํธ๋ถ์ ๊ตฌ์ฑ ํ์ผ์ ์ฆ์์์ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ์ ์ฉ ์ ์ ๋ง๋ค ์ ์์ต๋๋ค.
%%bash
cat <<'EOT' > ds_config_zero3.json
{
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
},
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"steps_per_print": 2000,
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"wall_clock_breakdown": false
}
EOT
ํธ๋ ์ด๋ ์คํฌ๋ฆฝํธ๊ฐ ๋
ธํธ๋ถ ์
์ด ์๋ ํ์ผ์ ์๋ ๊ฒฝ์ฐ, ๋
ธํธ๋ถ ์
์ ์
ธ์์ deepspeed๋ฅผ ์ ์์ ์ผ๋ก ์คํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด run_translation.py๋ฅผ ์์ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์ธ์.:
!git clone https://github.com/huggingface/transformers
!cd transformers; deepspeed examples/pytorch/translation/run_translation.py ...
๋ํ %%bash ๋งค์ง์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ค์ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ์
ธ ํ๋ก๊ทธ๋จ์ ์คํํ ์๋ ์์ง๋ง ๊ต์ก์ด ์๋ฃ๋ ๋๊น์ง ๋ก๊ทธ๋ฅผ ๋ณผ ์ ์์ต๋๋ค. %%bash ๋งค์ง์ผ๋ก ๋ถ์ฐ ํ๊ฒฝ์ ์๋ฎฌ๋ ์ด์
ํ ํ์๋ ์์ต๋๋ค.
%%bash
git clone https://github.com/huggingface/transformers
cd transformers
deepspeed examples/pytorch/translation/run_translation.py ...
๋ชจ๋ธ ๊ฐ์ค์น ์ ์ฅํ๊ธฐ[[save-model-weights]]
๋ฅ์คํผ๋๋ ๊ธฐ๋ณธ ๊ณ ์ ๋ฐ fp32 ๊ฐ์ค์น๋ฅผ ์ฌ์ฉ์ ์ง์ ์ฒดํฌํฌ์ธํธ ์ต์ ํ ํ์ผ(glob ํจํด์ global_step*/*optim_states.pt์ฒ๋ผ ๋ณด์
๋๋ค)์ ์ ์ฅํ๊ณ ์ผ๋ฐ ์ฒดํฌํฌ์ธํธ ์๋์ ์ ์ฅํฉ๋๋ค.
ZeRO-2๋ก ํ๋ จ๋ ๋ชจ๋ธ์ pytorch_model.bin ๊ฐ์ค์น๋ฅผ fp16์ ์ ์ฅํฉ๋๋ค. ZeRO-3์ผ๋ก ํ๋ จ๋ ๋ชจ๋ธ์ ๋ชจ๋ธ ๊ฐ์ค์น๋ฅผ fp16์ ์ ์ฅํ๋ ค๋ฉด ๋ชจ๋ธ ๊ฐ์ค์น๊ฐ ์ฌ๋ฌ GPU์ ๋ถํ ๋์ด ์์ผ๋ฏ๋ก โstage3_gather_16bit_weights_on_model_saveโ: true๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด [Trainer]๊ฐ ๊ฐ์ค์น๋ฅผ fp16์ ์ ์ฅํ์ง ์๊ณ pytorch_model.bin ํ์ผ์ ์์ฑํ์ง ์์ต๋๋ค. ์ด๋ DeepSpeed์ state_dict์ ์ค์ ๊ฐ์ค์น ๋์ ํ๋ ์ด์คํ๋๊ฐ ํฌํจ๋์ด ์์ด ์ด๋ฅผ ๋ก๋ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
{
"zero_optimization": {
"stage3_gather_16bit_weights_on_model_save": true
}
}
์ ์ฒด ์ ๋ฐ ๊ฐ์ค์น๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ ์ ์์ผ๋ฏ๋ก ํธ๋ ์ด๋ ์ค์ ์ ์ฅํด์๋ ์ ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํ๋ จ์ด ์๋ฃ๋ ํ ์คํ๋ผ์ธ์ผ๋ก fp32 ๊ฐ์ค์น๋ฅผ ์ ์ฅํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ CPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ง์ ๊ฒฝ์ฐ ํ๋ จ ์ค์ fp32 ๊ฐ์ค์น๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค. ์ด ์น์ ์์๋ ์จ๋ผ์ธ๊ณผ ์คํ๋ผ์ธ ๋ฐฉ์์ ๋ชจ๋ ๋ค๋ฃน๋๋ค.
์จ๋ผ์ธ ํ๊ฒฝ[[online]]
๋ค์๊ณผ ๊ฐ์ด ์ต์ ์ฒดํฌํฌ์ธํธ๋ฅผ ๋ก๋ํ๋ ค๋ฉด ์ฒดํฌํฌ์ธํธ๋ฅผ ํ๋ ์ด์ ์ ์ฅํด์ผ ํฉ๋๋ค:
from transformers.trainer_utils import get_last_checkpoint
from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
checkpoint_dir = get_last_checkpoint(trainer.args.output_dir)
fp32_model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
--load_best_model_at_end ๋งค๊ฐ๋ณ์๋ฅผ ํ์ฑํํ์ฌ [TrainingArguments]์์ ์ต์ ์ ์ฒดํฌํฌ์ธํธ๋ฅผ ์ถ์ ํ๋ ๊ฒฝ์ฐ, ๋จผ์ ํ์ต์ ์๋ฃํ๊ณ ์ต์ข
๋ชจ๋ธ์ ๋ช
์์ ์ผ๋ก ์ ์ฅํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์๋์ ๊ฐ์ด ๋ค์ ๋ก๋ํ ์ ์์ต๋๋ค:
from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
checkpoint_dir = os.path.join(trainer.args.output_dir, "checkpoint-final")
trainer.deepspeed.save_checkpoint(checkpoint_dir)
fp32_model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
load_state_dict_from_zero_checkpoint๊ฐ ์คํ๋๋ฉด ๋์ผํ ์ ํ๋ฆฌ์ผ์ด์
์ ์ปจํ
์คํธ์์ ๋ชจ๋ธ์ ๋ ์ด์ DeepSpeed์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. model.load_state_dict(state_dict)๋ ๋ชจ๋ ๋ฅ์คํผ๋ ๋ง๋ฒ์ ์ ๊ฑฐํ๋ฏ๋ก ๋ฅ์คํผ๋ ์์ง์ ๋ค์ ์ด๊ธฐํํด์ผ ํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ๋ จ์ด ๋๋ ๋๋ง ์ฌ์ฉํ์ธ์.
fp32 ๊ฐ์ค์น์ state_dict๋ฅผ ์ถ์ถํ์ฌ ๋ก๋ํ ์๋ ์์ต๋๋ค:
from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir) # cpu์ ์ด๋ฏธ ์กด์ฌํจ
model = model.cpu()
model.load_state_dict(state_dict)
์คํ๋ผ์ธ ํ๊ฒฝ[[offline]]
DeepSpeed๋ ์ธ์ ๋ ์ง ๊ฐ์ค์น๋ฅผ ์ถ์ถํ ์ ์๋๋ก ์ฒดํฌํฌ์ธํธ ํด๋์ ์ต์์ ๋ ๋ฒจ์ zero_to_fp32.py ์คํฌ๋ฆฝํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ ๋
๋ฆฝํ ์คํฌ๋ฆฝํธ๋ก ๊ตฌ์ฑ ํ์ผ์ด๋ [Trainer]๊ฐ ํ์ํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฒดํฌํฌ์ธํธ ํด๋๊ฐ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ๋๋ค:
$ ls -l output_dir/checkpoint-1/
-rw-rw-r-- 1 stas stas 1.4K Mar 27 20:42 config.json
drwxrwxr-x 2 stas stas 4.0K Mar 25 19:52 global_step1/
-rw-rw-r-- 1 stas stas 12 Mar 27 13:16 latest
-rw-rw-r-- 1 stas stas 827K Mar 27 20:42 optimizer.pt
-rw-rw-r-- 1 stas stas 231M Mar 27 20:42 pytorch_model.bin
-rw-rw-r-- 1 stas stas 623 Mar 27 20:42 scheduler.pt
-rw-rw-r-- 1 stas stas 1.8K Mar 27 20:42 special_tokens_map.json
-rw-rw-r-- 1 stas stas 774K Mar 27 20:42 spiece.model
-rw-rw-r-- 1 stas stas 1.9K Mar 27 20:42 tokenizer_config.json
-rw-rw-r-- 1 stas stas 339 Mar 27 20:42 trainer_state.json
-rw-rw-r-- 1 stas stas 2.3K Mar 27 20:42 training_args.bin
-rwxrw-r-- 1 stas stas 5.5K Mar 27 13:16 zero_to_fp32.py*
๋ฅ์คํผ๋ ์ฒดํฌํฌ์ธํธ(ZeRO-2 ๋๋ ZeRO-3) ํ์ ํด๋ global_step1์์ fp32 ๊ฐ์ค์น๋ฅผ ์ฌ๊ตฌ์ฑํ๋ ค๋ฉด ๋ค์ ๋ช
๋ น์ ์คํํ์ฌ ์ฌ๋ฌ GPU์ ์ ์ฒด fp32 ๊ฐ์ค์น๋ฅผ ๋จ์ผ pytorch_model.bin ํ์ผ๋ก ์์ฑํ๊ณ ํตํฉํฉ๋๋ค. ์คํฌ๋ฆฝํธ๋ ์๋์ผ๋ก ์ฒดํฌํฌ์ธํธ๊ฐ ํฌํจ๋ ํ์ ํด๋๋ฅผ ์ฐพ์ต๋๋ค.
python zero_to_fp32.py . pytorch_model.bin
์์ธํ ์ฌ์ฉ๋ฒ์ python zero_to_fp32.py -h๋ฅผ ์คํํ์ธ์. ์ด ์คํฌ๋ฆฝํธ์๋ ์ต์ข
fp32 ๊ฐ์ค์น์ 2๋ฐฐ์ ์ผ๋ฐ RAM์ด ํ์ํฉ๋๋ค.
ZeRO Inference[[zero-inference]]
ZeRO Inference๋ ๋ชจ๋ธ ๊ฐ์ค์น๋ฅผ CPU ๋๋ NVMe ๋ฉ๋ชจ๋ฆฌ์ ๋ฐฐ์นํ์ฌ GPU์ ๋ถ๋ด์ ์ฃผ์ง ์์ผ๋ฏ๋ก GPU์์ ๋๊ท๋ชจ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์ถ๋ก ์ ์คํํ ์ ์์ต๋๋ค. ์ถ๋ก ์ ์ต์ ํ ์ํ ๋ฐ ๊ทธ๋ ์ด๋์ธํธ์ ๋ง์ ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ถ๊ฐ๋ก ํ์๋ก ํ์ง ์์ผ๋ฏ๋ก ๋์ผํ ํ๋์จ์ด์ ํจ์ฌ ๋ ํฐ ๋ฐฐ์น ๋ฐ/๋๋ ์ํ์ค ๊ธธ์ด๋ฅผ ๋ง์ถ ์ ์์ต๋๋ค.
ZeRO Inference๋ ZeRO-3์ ๋์ผํ ๊ตฌ์ฑ ํ์ผ์ ๊ณต์ ํ๋ฉฐ, ZeRO-2 ๋ฐ ZeRO-1 ๊ตฌ์ฑ์ ์ถ๋ก ์ ์๋ฌด๋ฐ ์ด์ ์ ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก ์๋ํ์ง ์์ต๋๋ค.
ZeRO Inference๋ฅผ ์คํํ๋ ค๋ฉด ์ผ๋ฐ์ ์ธ ํ๋ จ ์ธ์๋ฅผ [TrainingArguments] ํด๋์ค์ ์ ๋ฌํ๊ณ --do_eval ์ธ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
deepspeed --num_gpus=2 your_program.py <normal cl args> --do_eval --deepspeed ds_config.json
Trainer ์์ด DeepSpeed ์ฌ์ฉํ๊ธฐ[[non-trainer-deepspeed-integration]]
DeepSpeed๋ [Trainer] ํด๋์ค๊ฐ ์๋ ํธ๋์คํฌ๋จธ์์๋ ์๋ํฉ๋๋ค. ์ด๋ [~PreTrainedModel.from_pretrained]๋ฅผ ํธ์ถํ ๋ ZeRO-3 ๋งค๊ฐ๋ณ์๋ฅผ ์์งํ๊ณ ๋ชจ๋ธ์ ์ฌ๋ฌ GPU์ ๋ถํ ํ๋ ์์
๋ง ์ฒ๋ฆฌํ๋ [HfDeepSpeedConfig]๊ฐ ์ฒ๋ฆฌํฉ๋๋ค.
๋ชจ๋ ๊ฒ์ด ์๋์ผ๋ก ์ฒ๋ฆฌ๋๊ธฐ๋ฅผ ์ํ๋ค๋ฉด, [Trainer]์ ํจ๊ป DeepSpeed๋ฅผ ์ฌ์ฉํด ๋ณด์ธ์! DeepSpeed ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ฌ ์ค์ ํ์ผ์์ ๋งค๊ฐ๋ณ์ ๊ฐ์ ์๋์ผ๋ก ๊ตฌ์ฑํด์ผ ํฉ๋๋ค("auto" ๊ฐ์ ์ฌ์ฉํ ์ ์์).
ZeRO-3๋ฅผ ํจ์จ์ ์ผ๋ก ๋ฐฐํฌํ๋ ค๋ฉด ๋ชจ๋ธ ์์ [HfDeepSpeedConfig] ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํํ๊ณ ํด๋น ๊ฐ์ฒด๋ฅผ ์ ์งํด์ผ ํฉ๋๋ค:
from transformers.integrations import HfDeepSpeedConfig
from transformers import AutoModel
import deepspeed
ds_config = {...} # deepspeed ์ค์ ๊ฐ์ฒด ๋๋ ํ์ผ ๊ฒฝ๋ก
# Zero 3๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด ๋ชจ๋ธ์ ์ธ์คํด์คํํ๊ธฐ ์ ์ ๋ฐ๋์ ์คํํด์ผ ํฉ๋๋ค
dschf = HfDeepSpeedConfig(ds_config) # ์ด ๊ฐ์ฒด๋ฅผ ์ ์งํ์ธ์.
model = AutoModel.from_pretrained("openai-community/gpt2")
engine = deepspeed.initialize(model=model, config_params=ds_config, ...)
[HfDeepSpeedConfig] is not required for ZeRO-1 or ZeRO-2.
from transformers.integrations import HfDeepSpeedConfig
from transformers import AutoModel, AutoConfig
import deepspeed
ds_config = {...} # deepspeed ์ค์ ๊ฐ์ฒด ๋๋ ํ์ผ ๊ฒฝ๋ก
# Zero 3๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด ๋ชจ๋ธ์ ์ธ์คํด์คํํ๊ธฐ ์ ์ ๋ฐ๋์ ์คํํด์ผ ํฉ๋๋ค
dschf = HfDeepSpeedConfig(ds_config) # ์ด ๊ฐ์ฒด๋ฅผ ์ ์งํ์ธ์.
config = AutoConfig.from_pretrained("openai-community/gpt2")
model = AutoModel.from_config(config)
engine = deepspeed.initialize(model=model, config_params=ds_config, ...)
Trainer ์์ด ZeRO Inference ์ฌ์ฉํ๊ธฐ[[non-trainer-zero-inference]]
๋จ์ผ GPU์ ๋ชจ๋ธ์ ๋ง์ถ ์ ์๋ ๊ฒฝ์ฐ [Trainer]์์ด ZeRO ์ถ๋ก ์ ์คํํ๋ ค๋ฉด ์ถ๊ฐ GPU๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ์คํ๋ก๋๋ฅผ ์๋ํ์ธ์. ์ฌ๊ธฐ์ ์ดํดํด์ผ ํ ์ค์ํ ๋์์ค๋ ZeRO๊ฐ ์ค๊ณ๋ ๋ฐฉ์์ ๋ฐ๋ผ ์๋ก ๋ค๋ฅธ GPU์์ ์๋ก ๋ค๋ฅธ ์
๋ ฅ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๋ฐ๋์ ํ์ธํ์ธ์:
- GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ถฉ๋ถํ ๊ฒฝ์ฐ CPU ์คํ๋ก๋๋ฅผ ๋นํ์ฑํํฉ๋๋ค(์๋๊ฐ ๋๋ ค์ง๋ฏ๋ก).
- Ampere ์ด์์ GPU๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ bf16์ ํ์ฑํํ๋ฉด ์๋๊ฐ ๋นจ๋ผ์ง๋๋ค. ์ด๋ฌํ GPU๊ฐ ์๋ ๊ฒฝ์ฐ ์ค๋ฒํ๋ก ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก bf16์ผ๋ก ์ฌ์ ํ์ต๋ ๋ชจ๋ธ(T5 ๋ชจ๋ธ)์ ์ฌ์ฉํ์ง ์๋ ํ fp16์ ํ์ฑํํ ์ ์์ต๋๋ค.
๋จ์ผ GPU์ ๋ง์ง ์๋ ๋ชจ๋ธ์์ [Trainer] ์์ด ZeRO ์ถ๋ก ์ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ ๋์ ์์ด๋์ด๋ฅผ ์ป์ผ๋ ค๋ฉด ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ์ดํด๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
#!/usr/bin/env python
# ์ด ์คํฌ๋ฆฝํธ๋ ๋จ์ผ GPU์ ๋ชจ๋ธ์ ๋ง์ถ ์ ์์ ๋ ์ถ๋ก ๋ชจ๋์์ Deepspeed ZeRO๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
#
# 1. CPU ์คํ๋ก๋์ ํจ๊ป 1๊ฐ์ GPU ์ฌ์ฉ
# 2. ๋๋ ์ฌ๋ฌ GPU ์ฌ์ฉ
#
# ๋จผ์ deepspeed๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค: pip install deepspeed
#
# ์ฌ๊ธฐ์๋ ์ฝ 15GB์ GPU RAM์ด ํ์ํ 3B "bigscience/T0_3B" ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค - ๋ฐ๋ผ์ 1๊ฐ์ ํฐ GPU๋ 2๊ฐ์
# ์์ GPU๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๋๋ 1๊ฐ์ ์์ GPU์ ๋ง์ CPU ๋ฉ๋ชจ๋ฆฌ๋ก๋ ๊ฐ๋ฅํฉ๋๋ค.
#
# ์ฝ 50GB๊ฐ ํ์ํ "bigscience/T0"์ ๊ฐ์ ๋ ํฐ ๋ชจ๋ธ์ ์ฌ์ฉํ๋ ค๋ฉด, 80GB GPU๊ฐ ์๋ ํ
# 2-4๊ฐ์ GPU๊ฐ ํ์ํ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ์
๋ ฅ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด
# ์คํฌ๋ฆฝํธ๋ฅผ ์์ ํ์ฌ ๋ ๋ง์ GPU๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
#
# ์ ๊ณต๋ deepspeed ์ค์ ์ CPU ๋ฉ๋ชจ๋ฆฌ ์คํ๋ก๋ฉ๋ ํ์ฑํํ๋ฏ๋ก, ์ฌ์ฉ ๊ฐ๋ฅํ CPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ง๊ณ
# ์๋ ์ ํ๋ฅผ ๊ฐ์ํ ์ ์๋ค๋ฉด ์ผ๋ฐ์ ์ผ๋ก ๋จ์ผ GPU์ ๋ง์ง ์๋ ๋ชจ๋ธ์ ๋ก๋ํ ์ ์์ ๊ฒ์
๋๋ค.
# GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ถฉ๋ถํ๋ค๋ฉด CPU๋ก์ ์คํ๋ก๋๋ฅผ ์ํ์ง ์์ ๋ ํ๋ก๊ทธ๋จ์ด ๋ ๋น ๋ฅด๊ฒ ์คํ๋ ๊ฒ์
๋๋ค - ๊ทธ๋ด ๋๋ ํด๋น ์น์
์ ๋นํ์ฑํํ์ธ์.
#
# 1๊ฐ์ GPU์ ๋ฐฐํฌํ๋ ค๋ฉด:
#
# deepspeed --num_gpus 1 t0.py
# ๋๋:
# python -m torch.distributed.run --nproc_per_node=1 t0.py
#
# 2๊ฐ์ GPU์ ๋ฐฐํฌํ๋ ค๋ฉด:
#
# deepspeed --num_gpus 2 t0.py
# ๋๋:
# python -m torch.distributed.run --nproc_per_node=2 t0.py
from transformers import AutoTokenizer, AutoConfig, AutoModelForSeq2SeqLM
from transformers.integrations import HfDeepSpeedConfig
import deepspeed
import os
import torch
os.environ["TOKENIZERS_PARALLELISM"] = "false" # ํ ํฌ๋์ด์ ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ์ ๊ดํ ๊ฒฝ๊ณ ๋ฅผ ํผํ๊ธฐ ์ํจ์
๋๋ค.
# ๋ถ์ฐ ํ๊ฒฝ ์ค์
local_rank = int(os.getenv("LOCAL_RANK", "0"))
world_size = int(os.getenv("WORLD_SIZE", "1"))
torch.cuda.set_device(local_rank)
deepspeed.init_distributed()
model_name = "bigscience/T0_3B"
config = AutoConfig.from_pretrained(model_name)
model_hidden_size = config.d_model
# ๋ฐฐ์น ํฌ๊ธฐ๋ world_size๋ก ๋๋์ด ๋จ์ด์ ธ์ผ ํ์ง๋ง, world_size๋ณด๋ค ํด ์ ์์ต๋๋ค
train_batch_size = 1 * world_size
# ds_config ์ฐธ๊ณ ์ฌํญ
#
# - Ampere ์ด์์ GPU๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ bf16์ ํ์ฑํํ์ธ์ - ์ด๋ ํผํฉ ์ ๋ฐ๋๋ก ์คํ๋์ด
# ๋ ๋น ๋ฅผ ๊ฒ์
๋๋ค.
#
# - ์ค๋๋ GPU์ ๊ฒฝ์ฐ fp16์ ํ์ฑํํ ์ ์์ง๋ง, bf16์ผ๋ก ์ฌ์ ํ๋ จ๋์ง ์์ ๋ชจ๋ธ์์๋ง ์๋ํฉ๋๋ค - ์๋ฅผ ๋ค์ด
# ๋ชจ๋ ๊ณต์ t5 ๋ชจ๋ธ์ bf16์ผ๋ก ์ฌ์ ํ๋ จ๋์์ต๋๋ค
#
# - CPU ์คํ๋ก๋๋ฅผ ์ํ์ง ์๋๋ค๋ฉด offload_param.device๋ฅผ "none"์ผ๋ก ์ค์ ํ๊ฑฐ๋ `offload_param` ์น์
์
# ์์ ํ ์ ๊ฑฐํ์ธ์
#
# - `offload_param`์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, stage3_param_persistence_threshold๋ฅผ ์๋์ผ๋ก ๋ฏธ์ธ ์กฐ์ ํ์ฌ
# ์ด๋ค ๋งค๊ฐ๋ณ์๊ฐ GPU์ ๋จ์์์ด์ผ ํ๋์ง ์ ์ดํ ์ ์์ต๋๋ค - ๊ฐ์ด ํด์๋ก ์คํ๋ก๋ ํฌ๊ธฐ๊ฐ ์์์ง๋๋ค
#
# Deepspeed ์ค์ ์ ๋ํ ์์ธํ ์ ๋ณด๋ ๋ค์์ ์ฐธ์กฐํ์ธ์
# https://huggingface.co/docs/transformers/main/main_classes/deepspeed
# ์ผ๊ด์ฑ์ ์ํด json๊ณผ ๋์ผํ ํ์์ ์ ์งํ๋, true/false์๋ ์๋ฌธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค
# fmt: off
ds_config = {
"fp16": {
"enabled": False
},
"bf16": {
"enabled": False
},
"zero_optimization": {
"stage": 3,
"offload_param": {
"device": "cpu",
"pin_memory": True
},
"overlap_comm": True,
"contiguous_gradients": True,
"reduce_bucket_size": model_hidden_size * model_hidden_size,
"stage3_prefetch_bucket_size": 0.9 * model_hidden_size * model_hidden_size,
"stage3_param_persistence_threshold": 10 * model_hidden_size
},
"steps_per_print": 2000,
"train_batch_size": train_batch_size,
"train_micro_batch_size_per_gpu": 1,
"wall_clock_breakdown": False
}
# fmt: on
# ๋ค์ ์ค์ ๋ชจ๋ธ์ `from_pretrained` ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋
# deepspeed.zero.Init๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ์ฌ๋ฌ GPU์ ์ง์ ๋ถํ ํ๋๋ก transformers์ ์ง์ํฉ๋๋ค.
#
# **์ด๋ AutoModelForSeq2SeqLM.from_pretrained(model_name)๋ก ๋ชจ๋ธ์ ๋ก๋ํ๊ธฐ ์ ์ ์คํ๋์ด์ผ ํฉ๋๋ค**
#
# ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ชจ๋ธ์ด ๋จผ์ ์ ์์ ์ผ๋ก ๋ก๋๋ ํ ํฌ์๋ ์์๋ง ๋ถํ ๋๋๋ฐ, ์ด๋
# ๋ ํจ์จ์ ์ด๋ฉฐ CPU RAM์ด ๋ถ์กฑํ ๊ฒฝ์ฐ ์คํจํ ์ ์์ต๋๋ค
dschf = HfDeepSpeedConfig(ds_config) # ์ด ๊ฐ์ฒด๋ฅผ ์ ์งํ์ธ์
# ์ด์ ๋ชจ๋ธ์ ๋ก๋ํ ์ ์์ต๋๋ค.
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
# Deepspeed ZeRO๋ฅผ ์ด๊ธฐํํ๊ณ ์์ง ๊ฐ์ฒด๋ง ์ ์ฅ
ds_engine = deepspeed.initialize(model=model, config_params=ds_config)[0]
ds_engine.module.eval() # inference
# Deepspeed ZeRO๋ ๊ฐ GPU์์ ์๋ก ๊ด๋ จ ์๋ ์
๋ ฅ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ 2๊ฐ์ GPU๋ฅผ ์ฌ์ฉํ๋ฉด ํ ๋ฒ์ 2๊ฐ์ ์
๋ ฅ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
# GPU๋ฅผ ๋ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๊ทธ์ ๋ง๊ฒ ์กฐ์ ํ์ธ์.
# ๋ฌผ๋ก ์ฒ๋ฆฌํ ์
๋ ฅ์ด ํ๋๋ฟ์ด๋ผ๋ฉด ๋ GPU์ ๋์ผํ ๋ฌธ์์ด์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
# GPU๋ฅผ ํ๋๋ง ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ rank 0๋ง ๊ฐ๊ฒ ๋ฉ๋๋ค.
rank = torch.distributed.get_rank()
if rank == 0:
text_in = "Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy"
elif rank == 1:
text_in = "Is this review positive or negative? Review: this is the worst restaurant ever"
tokenizer = AutoTokenizer.from_pretrained(model_name)
inputs = tokenizer.encode(text_in, return_tensors="pt").to(device=local_rank)
with torch.no_grad():
outputs = ds_engine.module.generate(inputs, synced_gpus=True)
text_out = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"rank{rank}:\n in={text_in}\n out={text_out}")
์คํฌ๋ฆฝํธ๋ฅผ t0.py๋ก ์ ์ฅํ๊ณ ์คํํฉ๋๋ค:
$ deepspeed --num_gpus 2 t0.py
rank0:
in=Is this review positive or negative? Review: this is the best cast iron skillet you will ever buy
out=Positive
rank1:
in=Is this review positive or negative? Review: this is the worst restaurant ever
out=negative
์ด๊ฒ์ ๋งค์ฐ ๊ธฐ๋ณธ์ ์ธ ์์์ด๋ฏ๋ก ์ฌ์ฉ ์ฌ๋ก์ ๋ง๊ฒ ์กฐ์ ํ ์ ์์ต๋๋ค.
์์ฑ[[generate]]
์์ฑ์ ZeRO-3์ ํจ๊ป ์ฌ๋ฌ ๊ฐ์ GPU๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด [~GenerationMixin.generate] ๋ฉ์๋์์ synced_gpus=True๋ฅผ ์ค์ ํ์ฌ GPU๋ฅผ ๋๊ธฐํํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ํ GPU๊ฐ ๋ค๋ฅธ GPU๋ณด๋ค ๋จผ์ ์์ฑ์ ์๋ฃํ๋ฉด ๋๋จธ์ง GPU๊ฐ ๋จผ์ ์๋ฃํ GPU๋ก๋ถํฐ ๊ฐ์ค์น ์ค๋๋ฅผ ๋ฐ์ง ๋ชปํ์ฌ ์ ์ฒด ์์คํ
์ด ์ค๋จ๋ฉ๋๋ค.
ํธ๋์คํฌ๋จธ>=4.28์ ๊ฒฝ์ฐ, ์์ฑ ์ค์ ์ฌ๋ฌ ๊ฐ์ GPU๊ฐ ๊ฐ์ง๋๋ฉด synced_gpus๊ฐ ์๋์ผ๋ก True๋ก ์ค์ ๋ฉ๋๋ค.
ํธ๋ฌ๋ธ์ํ [[troubleshoot]]
๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด DeepSpeed๊ฐ ๋ฌธ์ ์ ์์ธ์ด ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ฏ๋ก(์์ฃผ ๋ช ๋ฐฑํ๊ณ ์์ธ์ ์ผ๋ก DeepSpeed ๋ชจ๋์ ๋ณผ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด) DeepSpeed๊ฐ ๋ฌธ์ ์ ์์ธ์ธ์ง ๊ณ ๋ คํด์ผ ํฉ๋๋ค! ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ DeepSpeed ์์ด ์ค์ ์ ๋ค์ ์๋ํ๊ณ ๋ฌธ์ ๊ฐ ์ง์๋๋ฉด ๋ฌธ์ ๋ฅผ ์ ๊ณ ํ๋ ๊ฒ์ ๋๋ค. ๋ฌธ์ ๊ฐ ํต์ฌ์ ์ธ DeepSpeed ๋ฌธ์ ์ด๊ณ transformers์ ๊ด๋ จ์ด ์๋ ๊ฒฝ์ฐ, DeepSpeed ๋ฆฌํฌ์งํ ๋ฆฌ์์ ์ด์๋ฅผ ๊ฐ์คํ์ธ์.
transformers์ ๊ด๋ จ๋ ์ด์๋ฅผ ๊ฐ์คํ ๋์๋ ๋ค์ ์ ๋ณด๋ฅผ ์ ๊ณตํด ์ฃผ์ธ์:
- ์ ์ฒด DeepSpeed ๊ตฌ์ฑ ํ์ผ
*[Trainer]์ ๋ช
๋ น์ค ์ธ์, ๋๋[Trainer] ์ค์ ์ ์ง์ ์์ฑํ๋ ๊ฒฝ์ฐ[TrainingArguments] ์ธ์(๊ด๋ จ ์๋ ํญ๋ชฉ์ด ์์ญ ๊ฐ ์๋ [TrainingArguments]๋ ๋คํํ์ง ๋ง์ธ์).
- ๋ค์ ์ฝ๋์ ์ถ๋ ฅ ๊ฒฐ๊ณผ:
python -c 'import torch; print(f"torch: {torch.__version__}")'
python -c 'import transformers; print(f"transformers: {transformers.__version__}")'
python -c 'import deepspeed; print(f"deepspeed: {deepspeed.__version__}")'
๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์๋ Google Colab ๋ ธํธ๋ถ ๋งํฌ
๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๊ธฐ์กด ์์ ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์๋ ํ์ค ๋ฐ ์ฌ์ฉ์ ์ง์ ์ด ์๋ ๋ฐ์ดํฐ ์งํฉ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค์ ์น์ ์์๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ ๊ฐ์ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
DeepSpeed ํ๋ก์ธ์ค๊ฐ ์์ ๋จ๊ณ์์ ์ข ๋ฃ๋์์ ๊ฒฝ์ฐ[[deepspeed-process-killed-at-startup]]
์คํ ์ค์ ํธ๋ ์ด์ค๋ฐฑ ์์ด DeepSpeed ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋๋ฉด ์ผ๋ฐ์ ์ผ๋ก ํ๋ก๊ทธ๋จ์ด ์์คํ
๋ณด๋ค ๋ง์ CPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ ค๊ณ ์๋ํ๊ฑฐ๋ ํ๋ก์ธ์ค๊ฐ ํ์ฉ๋ ๊ฒ๋ณด๋ค ๋ง์ CPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ ค๊ณ ์๋ํ์ฌ OS ์ปค๋์ด ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃํ์์ ์๋ฏธํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ๊ตฌ์ฑ ํ์ผ์ offload_optimizer, offload_param ๋๋ ๋ ๋ค CPU๋ก ์คํ๋ก๋ํ๋๋ก ๊ตฌ์ฑ๋์ด ์๋์ง ํ์ธํ์ธ์.
NVMe ๋ฐ ZeRO-3๋ฅผ ์ค์ ํ ๊ฒฝ์ฐ NVMe๋ก ์คํ๋ก๋๋ฅผ ์คํํด ๋ณด์ธ์(๋ชจ๋ธ์ ๋ฉ๋ชจ๋ฆฌ ์๊ตฌ ์ฌํญ์ ํ์ธํ์ธ์).
NaN ์์ค[[nan-loss]]
๋ชจ๋ธ์ bf16์ผ๋ก ์ฌ์ ํ๋ จํ ๋ค์ fp16์ผ๋ก ์ฌ์ฉํ๋ ค๊ณ ํ ๋ NaN ์์ค์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค(ํนํ TPU ํ๋ จ ๋ชจ๋ธ์ ํด๋น). ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ํ๋์จ์ด๊ฐ ์ด๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ(TPU, Ampere GPU ์ด์) fp32 ๋๋ bf16์ ์ฌ์ฉํ์ธ์.
๋ค๋ฅธ ๋ฌธ์ ๋ fp16 ์ฌ์ฉ๊ณผ ๊ด๋ จ์ด ์์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ด๊ฒ์ด fp16 ๊ตฌ์ฑ์ธ ๊ฒฝ์ฐ์ ๋๋ค:
{
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
}
}
๋ก๊ทธ์ ๋ค์๊ณผ ๊ฐ์ OVERFLOW! ๋ฉ์์ง๊ฐ ํ์๋ ์ ์์ต๋๋ค:
0%| | 0/189 [00:00<?, ?it/s]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 262144
1%|โ | 1/189 [00:00<01:26, 2.17it/s]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 131072.0
1%|โโ
[...]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
14%|โโโโโโโโโโโโโโโโโ | 27/189 [00:14<01:13, 2.21it/s]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
15%|โโโโโโโโโโโโโโโโโโ | 28/189 [00:14<01:13, 2.18it/s]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
15%|โโโโโโโโโโโโโโโโโโ | 29/189 [00:15<01:13, 2.18it/s]
[deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
[...]
์ด๋ DeepSpeed ์์ค ์ค์ผ์ผ๋ฌ๊ฐ ์์ค ์ค๋ฒํ๋ก๋ฅผ ๊ทน๋ณตํ ์ ์๋ ์ค์ผ์ผ๋ง ๊ณ์๋ฅผ ์ฐพ์ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด initial_scale_power ๊ฐ์ ๋ ๋๊ฒ ์ค์ ํ์ธ์(์ผ๋ฐ์ ์ผ๋ก 32๊ฐ ์ ์ ํฉ๋๋ค).
๋ฆฌ์์ค[[resources]]
DeepSpeed ZeRO๋ ์ ํ๋ GPU ๋ฆฌ์์ค๋ก ์ถ๋ก ์ ์ํด ๋งค์ฐ ํฐ ๋ชจ๋ธ์ ํ๋ จํ๊ณ ๋ก๋ํ๋ ๊ฐ๋ ฅํ ๊ธฐ์ ๋ก, ๋๊ตฌ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. DeepSpeed์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ธ๋ก๊ทธ ํฌ์คํธ, ๊ณต์ ๋ฌธ์, ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ค์ ๋ฌธ์๋ ZeRO์ ๋ํด ์์ธํ ์์๋ณผ ์ ์๋ ํ๋ฅญํ ์๋ฃ์ ๋๋ค: