メインコンテンツへスキップ
分散トレーニングの実験では、複数のマシンやクライアントを並列に使用してモデルをトレーニングします。W&B は、分散トレーニング実験のトラッキングをサポートします。ユースケースに合わせて、以下のいずれかのアプローチを使用して分散トレーニング実験をトラッキングしてください。
  • 単一プロセスのトラッキング: ランク 0 のプロセス(「リーダー」または「コーディネーター」とも呼ばれます)を W&B でトラッキングします。これは、PyTorch Distributed Data Parallel (DDP) クラスを使用して分散トレーニング実験をログ記録するための一般的なソリューションです。
  • 複数プロセスのトラッキング: 複数のプロセスの場合、以下のいずれかを選択できます:
    • プロセスごとに1つの run を使用して、各プロセスを個別にトラッキングする。オプションで、W&B App UI でこれらをグループ化できます。
    • すべてのプロセスを単一の run にトラッキングする。

単一プロセスのトラッキング

このセクションでは、ランク 0 プロセスで利用可能な値とメトリクスをトラッキングする方法について説明します。単一のプロセスからのみ取得可能なメトリクスをトラッキングする場合に、このアプローチを使用します。一般的なメトリクスには、GPU/CPU 使用率、共有検証セットでの振る舞い、勾配とパラメータ、代表的なデータ例での損失(loss)値などがあります。 ランク 0 プロセス内で、wandb.init() を使用して W&B run を初期化し、その run に実験をログ記録(wandb.log)します。 以下の サンプル Python スクリプト (log-ddp.py) は、PyTorch DDP を使用して単一マシンの 2 つの GPU でメトリクスをトラッキングする 1 つの方法を示しています。PyTorch DDP (torch.nnDistributedDataParallel) は、分散トレーニングで人気のあるライブラリです。基本的な原理はあらゆる分散トレーニングのセットアップに適用されますが、実装は異なる場合があります。 この Python スクリプトは以下のことを行います:
  1. torch.distributed.launch を使用して複数のプロセスを開始します。
  2. --local_rank コマンドライン引数でランクを確認します。
  3. ランクが 0 に設定されている場合、train() 関数内で条件付きで wandb ロギングをセットアップします。
if __name__ == "__main__":
    # 引数を取得
    args = parse_args()

    if args.local_rank == 0:  # メインプロセスのみ
        # wandb run を初期化
        run = wandb.init(
            entity=args.entity,
            project=args.project,
        )
        # DDP でモデルをトレーニング
        train(args, run)
    else:
        train(args)
単一プロセスからトラッキングされたメトリクスを表示するサンプルダッシュボード を確認してください。 ダッシュボードには、温度や使用率など、両方の GPU のシステムメトリクスが表示されます。
GPU metrics dashboard
ただし、エポックおよびバッチサイズごとの関数としての損失値は、単一の GPU からのみログ記録されています。
Loss function plots

複数プロセスのトラッキング

W&B で複数のプロセスをトラッキングするには、次のいずれかのアプローチを使用します:

各プロセスを個別にトラッキングする

このセクションでは、プロセスごとに run を作成して、各プロセスを個別にトラッキングする方法について説明します。各 run 内で、メトリクスやアーティファクトなどをそれぞれの run にログ記録します。トレーニングの最後に wandb.Run.finish() を呼び出して run が完了したことをマークし、すべてのプロセスが適切に終了するようにします。 複数の実験にわたって run を追跡するのが難しい場合があります。これを軽減するために、W&B を初期化する際に group パラメータに値を指定し(wandb.init(group='group-name'))、どの run が特定の実験に属しているかを把握できるようにします。実験におけるトレーニングと評価の W&B Runs を追跡する方法の詳細については、Group Runs を参照してください。
個々のプロセスからメトリクスをトラッキングしたい場合に、このアプローチを使用してください。典型的な例としては、各ノードでのデータや予測(データ分散のデバッグ用)、メインノード以外の個々のバッチのメトリクスなどがあります。すべてのノードからシステムメトリクスを取得したり、メインノードで利用可能なサマリー統計を取得したりするだけであれば、このアプローチは必要ありません。
以下の Python コードスニペットは、W&B を初期化する際に group パラメータを設定する方法を示しています:
if __name__ == "__main__":
    # 引数を取得
    args = parse_args()
    # run を初期化
    run = wandb.init(
        entity=args.entity,
        project=args.project,
        group="DDP",  # 実験のすべての run を 1 つのグループにまとめる
    )
    # DDP でモデルをトレーニング
    train(args, run)

    run.finish()  # run を終了としてマーク
W&B App UI で、複数プロセスからトラッキングされたメトリクスの サンプルダッシュボード を確認してください。左側のサイドバーに 2 つの W&B Runs がグループ化されていることに注目してください。グループをクリックすると、その実験専用のグループページが表示されます。専用のグループページには、各プロセスからのメトリクスが個別に表示されます。
Grouped distributed runs
上の画像は W&B App UI ダッシュボードを示しています。サイドバーには 2 つの実験が表示されています。1 つは ‘null’ というラベルで、2 つ目(黄色い枠で囲まれているもの)は ‘DPP’ と呼ばれています。グループを展開する(Group ドロップダウンを選択する)と、その実験に関連付けられた W&B Runs が表示されます。

分散 run の整理

W&B を初期化する際に job_type パラメータを設定し(wandb.init(job_type='type-name'))、機能に基づいてノードをカテゴリ分けします。例えば、1 つのメインコーディネートノードと複数のレポート用ワーカーノードがある場合、メインコーディネートノードには job_typemain に、レポート用ワーカーノードには worker に設定できます。
# メインコーディネートノード
with wandb.init(project="<project>", job_type="main", group="experiment_1") as run:
     # トレーニングコード

# レポート用ワーカーノード
with wandb.init(project="<project>", job_type="worker", group="experiment_1") as run:
     # トレーニングコード
ノードの job_type を設定したら、Workspace で 保存済みビュー を作成して run を整理できます。右上の アクションメニューをクリックし、Save as new view をクリックします。 例えば、以下のような保存済みビューを作成できます:
  • デフォルトビュー: ノイズを減らすためにワーカーノードをフィルタリングして除外する
    • Filter をクリックし、Job Typeworker 以外に設定します。
    • レポート用ノードのみを表示します。
  • デバッグビュー: トラブルシューティングのためにワーカーノードに焦点を当てる
    • Filter をクリックし、Job Type == worker かつ StateIN crashed に設定します。
    • クラッシュした、またはエラー状態にあるワーカーノードのみを表示します。
  • 全ノードビュー: すべてをまとめて表示する
    • フィルタなし
    • 包括的なモニタリングに役立ちます。
保存済みビューを開くには、サイドバーの Workspaces をクリックし、メニューをクリックします。Workspace はリストの上部に表示され、保存済みビューは下部に表示されます。

すべてのプロセスを単一の run にトラッキングする

x_ で始まるパラメータ(x_label など)はパブリックプレビュー中です。フィードバックを提供するには、W&B リポジトリで GitHub issue を作成してください。
要件複数のプロセスを単一の run にトラッキングするには、以下が必要です:
  • W&B Python SDK バージョン v0.19.9 以降。
  • W&B Server v0.68 以降。
このアプローチでは、プライマリノードと 1 つ以上のワーカーノードを使用します。プライマリノード内で W&B run を初期化します。各ワーカーノードについては、プライマリノードで使用されている run ID を使用して run を初期化します。トレーニング中、各ワーカーノードはプライマリノードと同じ run ID にログを記録します。W&B はすべてのノードからのメトリクスを集約し、W&B App UI に表示します。 プライマリノード内で、wandb.init() を使用して W&B run を初期化します。settings パラメータに wandb.Settings オブジェクト(wandb.init(settings=wandb.Settings())を渡し、以下を設定します:
  1. 共有モードを有効にするために、mode パラメータを "shared" に設定します。
  2. x_label に一意のラベルを指定します。x_label に指定した値を使用して、W&B App UI のログやシステムメトリクスでデータがどのノードから来ているかを識別します。指定しない場合、W&B はホスト名とランダムなハッシュを使用してラベルを自動作成します。
  3. x_primary パラメータを True に設定して、これがプライマリノードであることを示します。
  4. オプションで、W&B がメトリクスをトラッキングする GPU を指定するために、GPU インデックスのリスト([0,1,2])を x_stats_gpu_device_ids に提供します。リストを提供しない場合、W&B はマシン上のすべての GPU のメトリクスをトラッキングします。
プライマリノードの run ID を控えておいてください。各ワーカーノードにはプライマリノードの run ID が必要です。
x_primary=True は、プライマリノードをワーカーノードと区別します。プライマリノードは、設定ファイルやテレメトリなど、ノード間で共有されるファイルをアップロードする唯一のノードです。ワーカーノードはこれらのファイルをアップロードしません。
各ワーカーノードで、wandb.init() を使用して W&B run を初期化し、以下を提供します:
  1. settings パラメータに wandb.Settings オブジェクト(wandb.init(settings=wandb.Settings())を渡し、以下を設定:
    • 共有モードを有効にするために、mode パラメータを "shared" に設定。
    • x_label に一意のラベルを指定。x_label に指定した値を使用して、W&B App UI のログやシステムメトリクスでデータがどのノードから来ているかを識別します。指定しない場合、W&B はホスト名とランダムなハッシュを使用してラベルを自動作成します。
    • x_primary パラメータを False に設定して、これがワーカーノードであることを示す。
  2. プライマリノードで使用されている run ID を id パラメータに渡す。
  3. オプションで x_update_finish_stateFalse に設定します。これにより、プライマリ以外のノードが run の状態 を途中で finished に更新するのを防ぎ、run の状態が一貫してプライマリノードによって管理されるようになります。
  • すべてのノードで同じ Entity と Project を使用してください。これにより、正しい run ID が見つかるようになります。
  • 各ワーカーノードで、プライマリノードの run ID を設定するための環境変数を定義することを検討してください。
以下のサンプルコードは、複数のプロセスを単一の run にトラッキングするためのハイレベルな要件を示しています:
import wandb

entity = "<team_entity>"
project = "<project_name>"

# プライマリノードで run を初期化
run = wandb.init(
    entity=entity,
    project=project,
	settings=wandb.Settings(
        x_label="rank_0", 
        mode="shared", 
        x_primary=True,
        x_stats_gpu_device_ids=[0, 1],  # (オプション) GPU 0 と 1 のメトリクスのみをトラッキング
        )
)

# プライマリノードの run ID を取得。
# 各ワーカーノードにこの run ID が必要。
run_id = run.id

# プライマリノードの run ID を使用して、ワーカーノードで run を初期化
run = wandb.init(
    entity=entity, # プライマリノードと同じ entity を使用
    project=project, # プライマリノードと同じ project を使用
	settings=wandb.Settings(x_label="rank_1", mode="shared", x_primary=False),
	id=run_id,
)

# プライマリノードの run ID を使用して、別のワーカーノードで run を初期化
run = wandb.init(
    entity=entity, # プライマリノードと同じ entity を使用
    project=project, # プライマリノードと同じ project を使用
	settings=wandb.Settings(x_label="rank_2", mode="shared", x_primary=False),
	id=run_id,
)
実際の例では、各ワーカーノードは別々のマシン上にある可能性があります。
GKE 上のマルチノード・マルチ GPU Kubernetes クラスターでモデルをトレーニングする方法のエンドツーエンドの例については、Distributed Training with Shared Mode レポートを参照してください。
run がログを記録しているプロジェクトで、マルチノードプロセスからのコンソールログを表示します:
  1. run が含まれているプロジェクトに移動します。
  2. 左側のサイドバーにある Runs タブをクリックします。
  3. 表示したい run をクリックします。
  4. 左側のサイドバーにある Logs タブをクリックします。
コンソールログページの最上部にある UI 検索バーで、x_label に指定したラベルに基づいてコンソールログをフィルタリングできます。例えば、次の画像は、x_labelrank0rank1rank2rank3rank4rank5rank6 が指定されている場合に、コンソールログをフィルタリングするために利用可能なオプションを示しています。
Multi-node console logs
詳細については、Console logs を参照してください。 W&B はすべてのノードからのシステムメトリクスを集約し、W&B App UI に表示します。例えば、次の画像は、複数のノードからのシステムメトリクスを含むサンプルダッシュボードを示しています。各ノードは、x_label パラメータで指定した一意のラベル(rank_0rank_1rank_2)を持っています。
Multi-node system metrics
折れ線グラフパネルのカスタマイズ方法については、Line plots を参照してください。

ユースケースの例

以下のコードスニペットは、高度な分散ユースケースの一般的なシナリオを示しています。

プロセスの spawn

spawn されたプロセスで run を開始する場合は、メイン関数内で wandb.setup() メソッドを使用します:
import multiprocessing as mp

def do_work(n):
    with wandb.init(config=dict(n=n)) as run:
        run.log(dict(this=n * n))

def main():
    wandb.setup()
    pool = mp.Pool(processes=4)
    pool.map(do_work, range(4))


if __name__ == "__main__":
    main()

run の共有

プロセス間で run を共有するには、run オブジェクトを引数として渡します:
def do_work(run):
    with wandb.init() as run:
        run.log(dict(this=1))

def main():
    run = wandb.init()
    p = mp.Process(target=do_work, kwargs=dict(run=run))
    p.start()
    p.join()
    run.finish()  # run を終了としてマーク


if __name__ == "__main__":
    main()
W&B はログの順序を保証できません。同期はスクリプトの作成者が行う必要があります。

トラブルシューティング

W&B と分散トレーニングを使用する際に遭遇する可能性のある 2 つの一般的な問題があります:
  1. トレーニング開始時にハングする - wandb のマルチプロセッシングが分散トレーニングのマルチプロセッシングと干渉すると、wandb プロセスがハングすることがあります。
  2. トレーニング終了時にハングする - wandb プロセスがいつ終了すべきかを認識していない場合、トレーニングジョブがハングすることがあります。Python スクリプトの最後で wandb.Run.finish() API を呼び出し、W&B に run が終了したことを伝えてください。wandb.Run.finish() API はデータのアップロードを完了させ、W&B を終了させます。 W&B は、分散ジョブの信頼性を向上させるために wandb service コマンドの使用を推奨しています。上記のトレーニングの問題は両方とも、wandb service が利用できない古いバージョンの W&B SDK でよく見られます。

W&B Service の有効化

W&B SDK のバージョンによっては、すでにデフォルトで W&B Service が有効になっている場合があります。

W&B SDK 0.13.0 以上

W&B SDK バージョン 0.13.0 以上では、W&B Service がデフォルトで有効になっています。

W&B SDK 0.12.5 以上

W&B SDK バージョン 0.12.5 以上で W&B Service を有効にするには、Python スクリプトを変更します。メイン関数内で wandb.require メソッドを使用し、文字列 "service" を渡します:
if __name__ == "__main__":
    main()


def main():
    wandb.require("service")
    # スクリプトの残りの処理をここに記述
最適なエクスペリエンスのために、最新バージョンへのアップグレードをお勧めします。 W&B SDK 0.12.4 以下 W&B SDK バージョン 0.12.4 以下を使用している場合は、WANDB_START_METHOD 環境変数を "thread" に設定して、代わりにマルチスレッディングを使用するようにしてください。