メインコンテンツへスキップ
分散学習 Experiment では、複数のマシンまたはクライアントを並列に使ってモデルを学習します。W&B を使うと、分散学習 Experiments を追跡できます。ユースケースに応じて、次のいずれかの方法で分散学習 Experiments を追跡します:
  • 単一プロセスを追跡する: W&B を使って、rank 0 プロセス(「leader」や「coordinator」とも呼ばれます)を追跡します。これは、PyTorch Distributed Data Parallel (DDP) クラスを使う分散学習 Experiments をログに記録する際の一般的な方法です。
  • 複数プロセスを追跡する: 複数プロセスの場合、次のいずれかを行います:
    • プロセスごとに 1 つの run を用いて、それぞれのプロセスを個別に追跡します。必要に応じて、W&B App UI でそれらをグループ化できます。
    • すべてのプロセスを 1 つの run に対して追跡します。
同時接続各同時接続は、計算リソース、メモリ、およびネットワークリソースを消費します。メトリクスを定期的にログに記録しないクライアント接続であっても、システムメトリクスの更新をプッシュするため、チャートの読み込み時のパフォーマンス低下につながります。W&B では、ワークロードに応じて同時クライアント接続の最大数を制限し、時間の経過に伴うリソース使用状況を監視することを推奨します。W&B は Dedicated Cloud において、最大 300 の同時クライアント接続というハードリミットでテストを実施しています。Multi-tenant Cloud の組織では、分散学習向けのクライアント接続は、通常の学習 run と同じ レート制限の対象になります。Teams および Enterprise プランのユーザーは、Free プランのユーザーよりも高いレート制限が適用されます。

単一プロセスをトラッキングする

このセクションでは、ランク 0 のプロセスで利用可能な値やメトリクスのトラッキング方法について説明します。この方法は、単一プロセスから取得できるメトリクスのみをトラッキングしたい場合に使用します。典型的なメトリクスには、GPU/CPU 使用率、共通の検証セットでの挙動、勾配とパラメータ、代表的なデータ例における損失値などが含まれます。 ランク 0 のプロセス内で、wandb.init() を使って W&B の run を初期化し、その run に対して実験をログ(wandb.log)に記録します。 次の サンプル Python スクリプト(log-ddp.py は、PyTorch DDP を使用して単一マシン上の 2 つの GPU でメトリクスをトラッキングする 1 つの方法を示しています。PyTorch DDPtorch.nnDistributedDataParallel)は、分散学習用の一般的なライブラリです。基本原則はあらゆる分散学習セットアップに適用できますが、実装は異なる場合があります。 この Python スクリプトは次のことを行います:
  1. torch.distributed.launch で複数のプロセスを起動します。
  2. コマンドライン引数 --local_rank を使って rank を確認します。
  3. rank が 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 メトリクスダッシュボード
しかし、エポックとバッチサイズに対する loss の値は、単一の GPU からのものだけがログとして記録されています。
損失関数のプロット

複数プロセスをトラッキングする

複数のプロセスを W&B でトラッキングするには、次のいずれかの方法を使用できます。

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

このセクションでは、各プロセスごとに run を作成して個別にトラッキングする方法を説明します。各 run の中で、その run に対応するメトリクスやアーティファクトなどをそれぞれの run にログします。学習の最後に wandb.Run.finish() を呼び出して run の完了をマークし、すべてのプロセスが正しく終了するようにします。 複数の実験にまたがる run を管理し続けるのが難しくなる場合があります。その対策として、W&B を初期化する際に group パラメータに値を指定してください(wandb.init(group='group-name'))。これにより、どの run がどの実験に属しているかを整理できます。Experiments 内での学習および評価用の 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 がグループ化されていることに注意してください。グループをクリックすると、その実験専用のグループページが表示されます。専用のグループページでは、各プロセスごとのメトリクスが個別に表示されます。
グループ化された分散 run
上の画像は、W&B App の UI におけるダッシュボードを示しています。サイドバーには 2 つの実験が表示されています。1 つは「null」とラベル付けされたもの、もう 1 つは(黄色の枠で囲まれた)「DPP」という名前のものです。グループを展開(Group ドロップダウンを選択)すると、その実験に関連付けられている W&B Runs が表示されます。

分散実行の run を整理する

ノードをその役割に応じて分類するには、W&B を初期化するときに job_type パラメータを設定します(wandb.init(job_type='type-name'))。たとえば、メインの調整用ノードと、いくつかのレポート用ワーカーノードがあるとします。メインの調整用ノードには 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 を設定したら、ワークスペース内で保存済みビューを作成して run を整理できます。右上の アクションメニューをクリックし、Save as new view をクリックします。 たとえば、次のような保存済みビューを作成できます。
  • Default view: ワーカーノードをフィルターしてノイズを減らす
    • Filter をクリックし、Job Typeworker に設定します。
    • レポート用ノードのみを表示します。
    • Debug view: トラブルシューティングのためにワーカーノードに集中する
      • Filter をクリックし、Job Type== worker に設定し、StateIN crashed に設定します。
      • クラッシュした、またはエラー状態にあるワーカーノードのみを表示します。
    • All nodes view: すべてをまとめて確認する
      • フィルターなし
      • 包括的な監視に便利です。
保存済みビューを開くには、プロジェクトのサイドバーで Workspaces をクリックし、メニューをクリックします。Workspaces はリストの上部に、保存済みビューは下部に表示されます。

複数のプロセスを 1 つの run にトラッキングする

x_label のような x_ で始まるパラメータはパブリックプレビューです。フィードバックは、W&B リポジトリの GitHub issue を作成してお寄せください。
要件複数のプロセスを 1 つの 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.init(settings=wandb.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. 次の内容を含む wandb.Settings オブジェクトを 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 を設定する環境変数を定義することを検討してください。
次のサンプルコードは、複数のプロセスを 1 つの 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, # プライマリノードと同じエンティティを使用する
    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, # プライマリノードと同じエンティティを使用する
    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 という値を指定した場合に、どのオプションでコンソールログをフィルタリングできるかを示しています。
マルチノードのコンソールログ
詳細については、Console logs を参照してください。 W&B はすべてのノードからシステムメトリクスを集約し、W&B App UI に表示します。たとえば、次の画像は複数ノードのシステムメトリクスを示すダッシュボードの一例です。各ノードには、x_label パラメータで指定する一意のラベル(rank_0rank_1rank_2)が付与されます。
マルチノードのシステムメトリクス
折れ線プロットパネルのカスタマイズ方法については、Line plots を参照してください。

使用例

次のコードスニペットは、高度な分散処理における一般的なシナリオを示します。

プロセスの生成

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 を呼び出して、run が完了したことを W&B に通知してください。wandb.Run.finish() API はデータのアップロードを完了し、W&B を終了させます。 W&B は、分散ジョブの信頼性を向上させるために wandb service コマンドの使用を推奨しています。上記 2 つの問題は、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" に設定してください。