大規模モデルの分散化トレーニングにおける最適化: FSDP と `optim_state_dict_to_load()` 関数


torch.distributed.fsdp.FullyShardedDataParallel.optim_state_dict_to_load() は、"Fully Sharded Data Parallel" (FSDP) トレーニングで使用される関数です。この関数は、分散化された最適化器の状態辞書をロードするために使用されます。FSDP は、大規模なモデルを複数の GPU に分散してトレーニングするための手法です。

引数

  • is_named_optimizer: 名前付きの最適化器かどうかを指定するフラグ
  • full_state_dict: 完全な状態辞書かどうかを指定するフラグ
  • optim: 最適化器
  • optim_input: 最適化器に入力されるデータ
  • model: FSDP ラッパーでラップされたモデル
  • optim_state_dict: ロードする最適化器の状態辞書

戻り値

この関数は、ロードされた最適化器の状態辞書を返します。

内部処理

この関数は、以下の処理を実行します。

  1. ロードされた最適化器の状態辞書を検証します。
  2. FSDP ラッパーでラップされたモデルのパラメーターと、ロードされた最適化器の状態辞書のパラメーターを照合します。
  3. 照合されたパラメーターに対して、ロードされた最適化器の状態辞書から対応する値を抽出します。
  4. 抽出した値を、FSDP ラッパーでラップされたモデルのパラメーターに対応する最適化器の状態に設定します。
import torch
from torch.distributed import FSDP

model = torch.nn.Linear(10, 1)
fsdp_model = FSDP(model)
optimizer = torch.optim.Adam(fsdp_model.parameters())

# ... トレーニングを実行 ...

checkpoint = torch.load('checkpoint.pth')
optim_state_dict = checkpoint['optimizer_state_dict']

loaded_optim_state_dict = fsdp_model.optim_state_dict_to_load(optim_state_dict)

optimizer.load_state_dict(loaded_optim_state_dict)
  • この関数は、PyTorch 1.8 以降で使用できます。
  • torch.distributed.fsdp.FullyShardedDataParallel.optim_state_dict_to_load() 関数は、FSDP トレーニングでロードされた最適化器の状態辞書をロードする場合にのみ使用できます。


import torch
from torch.distributed import FSDP

# モデルを定義
model = torch.nn.Linear(10, 1)

# FSDP ラッパーでラップ
fsdp_model = FSDP(model)

# 最適化器を作成
optimizer = torch.optim.Adam(fsdp_model.parameters())

# ... トレーニングを実行 ...

# チェックポイントを保存
checkpoint = {
    'model_state_dict': fsdp_model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
}
torch.save(checkpoint, 'checkpoint.pth')

# チェックポイントからモデルと最適化器の状態辞書をロード
checkpoint = torch.load('checkpoint.pth')
model_state_dict = checkpoint['model_state_dict']
optim_state_dict = checkpoint['optimizer_state_dict']

# FSDP ラッパーでラップされた新しいモデルを作成
new_fsdp_model = FSDP(torch.nn.Linear(10, 1))

# ロードされたモデルの状態辞書を新しい FSDP ラッパーでラップされたモデルにロード
new_fsdp_model.load_state_dict(model_state_dict)

# ロードされた最適化器の状態辞書を FSDP トレーニングで使用できるように変換
loaded_optim_state_dict = new_fsdp_model.optim_state_dict_to_load(optim_state_dict)

# 新しい FSDP ラッパーでラップされたモデルにロードされた最適化器の状態辞書をロード
new_optimizer = torch.optim.Adam(new_fsdp_model.parameters())
new_optimizer.load_state_dict(loaded_optim_state_dict)

# 新しい FSDP ラッパーでラップされたモデルを使用して推論を実行
# ...

説明

このコードは、以下の手順を実行します。

  1. torch.nn.Linear モデルを定義します。
  2. モデルを FSDP ラッパーでラップします。
  3. torch.optim.Adam を使用して、FSDP ラッパーでラップされたモデルのパラメーターに対する最適化器を作成します。
  4. ... トレーニングを実行 ...
  5. トレーニング済みのモデルと最適化器の状態辞書を保存します。
  6. チェックポイントからモデルと最適化器の状態辞書をロードします。
  7. 新しい FSDP ラッパーでラップされたモデルを作成します。
  8. ロードされたモデルの状態辞書を新しい FSDP ラッパーでラップされたモデルにロードします。
  9. ロードされた最適化器の状態辞書を FSDP トレーニングで使用できるように変換します。
  10. 新しい FSDP ラッパーでラップされたモデルにロードされた最適化器の状態辞書をロードします。
  11. 新しい FSDP ラッパーでラップされたモデルを使用して推論を実行します。
  • このコードは、PyTorch 1.8 以降で使用できます。
  • このコードは、説明目的のみで使用されています。実際の使用状況では、モデル、最適化器、トレーニング設定を適切に変更する必要があります。


torch.optim.load_state_dict() を直接使用する

最も簡単な代替方法は、torch.optim.load_state_dict() 関数を使用して、ロードされた最適化器の状態辞書を直接 FSDP ラッパーでラップされたモデルの最適化器にロードすることです。

import torch
from torch.distributed import FSDP

# モデルを定義
model = torch.nn.Linear(10, 1)

# FSDP ラッパーでラップ
fsdp_model = FSDP(model)

# 最適化器を作成
optimizer = torch.optim.Adam(fsdp_model.parameters())

# ... トレーニングを実行 ...

# チェックポイントを保存
checkpoint = {
    'model_state_dict': fsdp_model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
}
torch.save(checkpoint, 'checkpoint.pth')

# チェックポイントからモデルと最適化器の状態辞書をロード
checkpoint = torch.load('checkpoint.pth')
model_state_dict = checkpoint['model_state_dict']
optim_state_dict = checkpoint['optimizer_state_dict']

# 新しい FSDP ラッパーでラップされたモデルを作成
new_fsdp_model = FSDP(torch.nn.Linear(10, 1))

# ロードされたモデルの状態辞書を新しい FSDP ラッパーでラップされたモデルにロード
new_fsdp_model.load_state_dict(model_state_dict)

# ロードされた最適化器の状態辞書を FSDP トレーニングで使用できるように変換する必要はありません
# 新しい FSDP ラッパーでラップされたモデルにロードされた最適化器の状態辞書を直接ロード
new_optimizer = torch.optim.Adam(new_fsdp_model.parameters())
new_optimizer.load_state_dict(optim_state_dict)

# 新しい FSDP ラッパーでラップされたモデルを使用して推論を実行
# ...

カスタムの変換ロジックを実装する

torch.distributed.fsdp.FullyShardedDataParallel.optim_state_dict_to_load() 関数の内部処理を理解している場合は、カスタムの変換ロジックを実装して、FSDP トレーニングで使用できるようにロードされた最適化器の状態辞書を変換することができます。

別の分散化トレーニングライブラリを使用する

FSDP以外にも、大規模なモデルを分散してトレーニングするためのライブラリはいくつかあります。

これらのライブラリには、独自の最適化器の状態辞書ロードロジックが含まれている場合があります。

  • 別の分散化トレーニングライブラリを使用する場合は、ライブラリのドキュメントを参照して、最適化器の状態辞書をロードする方法を確認する必要があります。
  • カスタムの変換ロジックを実装する場合は、FSDP トレーニングで使用できるようにロードされた最適化器の状態辞書を正しく変換していることを確認する必要があります。
  • 実際の使用状況では、モデル、最適化器、トレーニング設定を適切に変更する必要があります。
  • 上記の代替方法は、すべて FSDP トレーニングで使用される特定の状況でのみ役立ちます。