# DDP

[DistributedDataParallel (DDP)](https://docs.pytorch.org/tutorials/beginner/ddp_series_theory.html) は、各 GPU にモデルの完全なコピーを保持します。各 GPU は、重複しないデータのシャードをフォワードパスとバックワードパスで処理します。オプティマイザーステップの前に、all-reduce によって全 GPU 間で勾配を平均化し、すべてのモデルコピーが同一であることを保ちます。モデルが単一の GPU に収まる場合は、DDP を使用してください。

```text
                         ┌─────────────────┐
                         │  training data  │
                         └────────┬────────┘
               ┌──────────────────┼──────────────────┐
               │ shard 0          │ shard 1          │ shard 2
               ▼                  ▼                  ▼
        ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
        │   model     │    │   model     │    │   model     │
        │  (copy 0)   │    │  (copy 1)   │    │  (copy 2)   │
        │   GPU 0     │    │   GPU 1     │    │   GPU 2     │
        └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
               │ grads            │ grads            │ grads
               └──────────────────┼──────────────────┘
                               all-reduce
                          (average gradients)
               ┌──────────────────┼──────────────────┐
               ▼                  ▼                  ▼
        ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
        │  optimizer  │    │  optimizer  │    │  optimizer  │
        │    step     │    │    step     │    │    step     │
        └─────────────┘    └─────────────┘    └─────────────┘
          (identical)        (identical)        (identical)
```

[Accelerate](./accelerate) などのマルチプロセスランチャーで起動すると、DDP は自動的に有効になります。

```cli
# 4 GPUs on one machine
accelerate launch --num_processes 4 train.py
```

## DDPを設定する

DDPの動作を制御するために、これらの[TrainingArguments](/docs/transformers/main/ja/main_classes/trainer#transformers.TrainingArguments)を渡します。

- `gradient_accumulation_steps()` は、all-reduce を実行するタイミングを決定します。[Trainer](/docs/transformers/main/ja/main_classes/trainer#transformers.Trainer) は、中間の累積ステップでは all-reduce をスキップし、最終的なマイクロバッチでのみ実行します。例えば、`gradient_accumulation_steps=4` の場合、all-reduce は 4 回のバックワードパスごとに実行されます。
- `~TrainingArguments.ddp_find_unused_parameters` は、フォワードパスの終了時に、勾配を受けないパラメータについて autograd グラフを走査し、それらを ready としてマークすることで、all-reduce をブロックしないようにします。`~TrainingArguments.gradient_checkpointing` と併用しないでください。gradient checkpointing は中間アクティベーションを破棄し、必要に応じて再計算するためです。
- `~TrainingArguments.ddp_bucket_cap_mb` は、バックワードパス中に勾配を単一の all-reduce にバッチ処理するためのバケットサイズです。バケットが大きいほど、all-reduce の呼び出し回数が減り、起動オーバーヘッドが小さくなります。
- `~TrainingArguments.ddp_broadcast_buffers` は、各 forward pass の開始時に、モデルのバッファ（BatchNorm の実行統計など）を rank 0 から他のすべての rank に同期します。モデルが LayerNorm のみを使用している場合は無効にしてください。`~TrainingArguments.gradient_checkpointing` と併用しないでください。
- `~TrainingArguments.ddp_backend` は通信バックエンドを設定します。NVIDIA GPU には `"nccl"`（デフォルトで最速）、CPU での学習やデバッグには `"gloo"`、その他のハードウェアには `"xccl"`、`"hccl"`、または `"cncl"` を使用します。
- `ddp_timeout()` は、すべてのプロセスおよび操作（all-reduce、broadcast）が完了するまでの時間制限を設定します。大規模なモデルの読み込みが遅く、プロセスがハングするなどの場合、タイムアウトによりエラーが発生し、無限にブロックされることを防ぎます。

```py
from transformers import TrainingArguments

args = TrainingArguments(
    ...,
    gradient_accumulation_steps=4,
    ddp_backend="nccl",
    ddp_find_unused_parameters=False,
    ddp_bucket_cap_mb=25,
    ddp_broadcast_buffers=True,
    ddp_timeout=1800,
)
```

## 次のステップ

- 単一のGPUに収まらないほど大きなモデルの学習については、[FSDP](./fsdp)を参照してください。
- ZeROの最適化とオフロードについては、[DeepSpeed](./deepspeed)を参照してください。
- DDPの動作に関する詳細については、The Ultra-Scale Playbookの[Data Parallelism](https://nanotron-ultrascale-playbook.static.hf.space/index.html#data_parallelism)章をお読みください。

