分散深層学習、特にMegatron-LMのようなフレームワークを使用する際には、各パラメータが独立しているわけではなく、互いに関係し合い、いくつかの制約条件を満たす必要があります。主要なパラメータ間の関係性の制約を以下に列挙します。
**1. GPU数と並列度の関係:**
* **`world_size = tensor_parallel_size * pipeline_parallel_size * data_parallel_size`**
* `world_size`: 学習に使用するGPUの総数。
* `tensor_parallel_size` (TP): テンソル並列の分割数。
* `pipeline_parallel_size` (PP): パイプライン並列のステージ数。
* `data_parallel_size` (DP): データ並列の分割数。
* **制約**: GPUの総数は、TP、PP、DPの各並列度の積と完全に一致しなければなりません。これは最も基本的な制約です。
* **含意**: TP次数とPP次数を決めると、残りのGPUがデータ並列 (DP) に割り当てられます (`data_parallel_size = world_size / (tensor_parallel_size * pipeline_parallel_size)`)。したがって、`world_size` は `tensor_parallel_size * pipeline_parallel_size` で割り切れなければなりません。
**2. バッチサイズの関係:**
* **`global_batch_size = micro_batch_size * data_parallel_size * gradient_accumulation_steps`**
* `global_batch_size`: 1回のパラメータ更新(Optimizerステップ)で考慮される実効的な総バッチサイズ。学習のハイパーパラメータとして重要です。
* `micro_batch_size`: 1つのGPU(またはTP/PPで構成される論理的なGPUグループ)が1回のForward/Backwardパスで処理する最小単位のバッチサイズ。GPUメモリ使用量(特にアクティベーション)に直接影響します。
* `gradient_accumulation_steps`: 何回マイクロバッチのForward/Backwardを実行してから勾配を平均化し、1回のOptimizerステップを実行するかを示す数。
* **制約**: これらのパラメータはこの等式を満たすように設定する必要があります。
* **含意**: `global_batch_size` を固定したい場合、`micro_batch_size` や `gradient_accumulation_steps` を変更すると、他のパラメータ(特に `data_parallel_size` がTP/PP/world\_sizeによって決まるため、`micro_batch_size` か `gradient_accumulation_steps`)も調整する必要があります。例えば、メモリ制約から `micro_batch_size` を小さくした場合、同じ `global_batch_size` を維持するには `gradient_accumulation_steps` を増やす必要があります。
**3. テンソル並列 (TP) の制約:**
* **`hidden_size` は `tensor_parallel_size` で割り切れなければならない。**
* TransformerのLinear層などは、隠れ層次元 (`hidden_size`) で分割されるため、均等に分割できる必要があります。
* **`num_attention_heads` は `tensor_parallel_size` で割り切れなければならない。**
* Multi-Head Attentionのヘッドは、TPランク間で分割されるため、均等に分割できる必要があります。
* **(推奨) `tensor_parallel_size` は通常、1ノード内のGPU数以下に設定される。**
* TPは高頻度・低レイテンシの通信(All-Reduceなど)を必要とするため、高速なNVLink/NVSwitchで接続されたノード内で完結させるのが一般的です。ノードを跨ぐTPは、InfiniBand/Ethernet経由となりパフォーマンスが大幅に低下します。
**4. パイプライン並列 (PP) の制約:**
* **(推奨) `num_layers` (モデルの総レイヤー数) は `pipeline_parallel_size` で割り切れることが望ましい。**
* 各パイプラインステージに割り当てられるレイヤー数を均等にするためです。完全に割り切れなくても動作はしますが、ステージ間の計算負荷が不均衡になり、「最も遅いステージ」が全体のボトルネックとなりやすくなります(パイプラインバブル以外の非効率性を生む)。
* **`virtual_pipeline_stage` を使用する場合、その値は `pipeline_parallel_size` の倍数であることが一般的。**
* これは物理的なPPステージをさらに細かくスケジューリングするためのもので、負荷分散を改善する目的で使われます。
**5. シーケンス並列 (SP) の制約:**
* **SPは通常、TPと組み合わせて使用される。** (`tensor_parallel_size > 1` が必要)。
* Transformerのレイヤー内でシーケンス次元に沿って分割と通信を行うため、TPの通信機構と連携します。
**6. メモリ関連の制約 (間接的な制約):**
* **GPUメモリ容量 >= (パラメータ + Optimizer状態 + アクティベーション) のメモリ使用量**
* これは直接的なパラメータ間の等式ではありませんが、パラメータ選択における最も重要な**物理的制約**です。
* 各メモリ要素は、TP次数、PP次数、DP次数(ZeRO利用時)、`micro_batch_size`、Activation Checkpointingの有無/方法、混合精度の使用などに依存して変化します。これらのパラメータを調整することで、モデルをGPUメモリに収める必要があります。
これらの制約を理解し、パラメータを設定する際に確認することが、分散学習ジョブを正しく起動し、期待通りのパフォーマンスを得るための第一歩となります。特に、GPU数、並列度、バッチサイズの間の関係は基本であり、間違いやすいポイントです。
> AssertionError: world size is not divisible by tensor parallel size (784) times pipeline parallel size (16)
data_parallel_size = 784 / (8 * 4) =