メインコンテンツへスキップ
分散トレーニング実験では、複数のマシンまたはクライアントを並列に使用してモデルをトレーニングします。W&Bは、分散トレーニング実験のトラッキングに役立ちます。ユースケースに応じて、次のいずれかの方法で分散トレーニング実験をトラッキングします。
  • 単一のプロセスをトラッキングする: rank 0 のプロセス (“leader” または “coordinator” とも呼ばれます) をW&Bでトラッキングします。これは、PyTorch Distributed Data Parallel (DDP) Class を使用した分散トレーニング実験のログで一般的な方法です。
  • 複数のプロセスをトラッキングする: 複数のプロセスをトラッキングする場合は、次のいずれかの方法を使用できます。
    • 各プロセスを、プロセスごとに1つの run を使って個別にトラッキングします。必要に応じて、W&B App UI でまとめてグループ化することもできます。
    • すべてのプロセスを単一の run にトラッキングします。
同時接続同時接続ごとに、コンピュート、メモリ、ネットワークのリソースが必要になります。メトリクスを定期的にログしない空のクライアント接続でもシステムメトリクスの更新は送信されるため、チャートの読み込み時のパフォーマンス低下につながります。W&Bでは、ワークロードに応じて同時クライアント接続の最大数を適切に制限し、時間の経過に伴うリソース使用量を監視することを推奨しています。W&Bは、専用クラウド で同時クライアント接続数 300 のハード制限までテストしています。Multi-tenant Cloud の組織では、分散トレーニング用のクライアント接続には、通常のトレーニング run と同じ rate limits が適用されます。Teams and Enterprise plans のUsersは、Free プランのUsersよりも高い rate limits を利用できます。

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

このセクションでは、rank 0 プロセスで利用可能な値やメトリクスをトラッキングする方法について説明します。このアプローチは、単一のプロセスからしか取得できないメトリクスをトラッキングする場合に使用します。代表的なメトリクスには、GPU/CPU 使用率、共有の検証セットでの挙動、勾配やパラメーター、代表的なデータサンプルに対する損失値などがあります。 rank 0 プロセス内で、wandb.init() を使用して W&B run を初期化し、その run に実験データをログします (wandb.Run.log()) 。 次の Python サンプルスクリプト (log-ddp.py) は、PyTorch DDP を使用して 1 台のマシン上の 2 つの GPU でメトリクスをトラッキングする方法の一例を示しています。PyTorch DDP (torch.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)
単一プロセスでトラッキングされたメトリクスを示すダッシュボードの例を確認してください。 このダッシュボードには、温度や利用率など、2基のGPUそれぞれのシステムメトリクスが表示されます。
GPUメトリクスのダッシュボード
ただし、エポックとバッチサイズに対する損失値は、1基のGPUからのみログされていました。
損失関数のプロット

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

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

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

このセクションでは、各プロセスごとに run を作成して、各プロセスを個別にトラッキングする方法を説明します。各 run では、それぞれの run にメトリクスや Artifacts などをログします。すべてのプロセスが正常に終了するよう、トレーニングの最後に 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",  # 実験のすべての runs を 1 つのグループにまとめる
    )
    # DDP でモデルをトレーニングする
    train(args, run)

    run.finish()  # run を完了としてマークする
W&B App UI で、複数のプロセスからトラッキングされたメトリクスのダッシュボード例を確認してください。左サイドバーでは、2 つの W&B Runs が 1 つのグループにまとめられていることに注目してください。グループをクリックすると、その実験専用のグループページを表示できます。専用のグループページでは、各プロセスのメトリクスが個別に表示されます。
グループ化された分散 runs
上の画像は、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 を設定したら、Workspace で 保存済みビュー を作成して runs を整理できます。右上の action () メニューをクリックし、Save as new view をクリックします。 たとえば、次のような保存済みビューを作成できます。
  • Default view: worker ノードを除外してノイズを減らす
    • フィルター をクリックし、Job Typeworker に設定します。
    • レポート用ノードのみが表示されます
    • Debug view: トラブルシューティングのために worker ノードに絞り込む
      • フィルター をクリックし、Job Type== worker に設定し、StateIN crashed に設定します。
      • クラッシュした worker ノード、またはエラー状態の worker ノードのみが表示されます
    • All nodes view: すべてをまとめて表示する
      • フィルターなし
      • 全体を監視する際に便利です
保存済みビューを開くには、プロジェクトのサイドバーで Workspaces をクリックし、次にメニューをクリックします。Workspaces はリストの上部に、保存済みビューは下部に表示されます。

すべてのプロセスを単一の 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 は、プライマリノードとワーカーノードを区別するための設定です。設定ファイルやテレメトリーなど、ノード間で共有されるファイルを upload できるのはプライマリノードだけです。ワーカーノードはこれらのファイルを upload しません。
各ワーカーノードでは、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 とプロジェクトを使用してください。これにより、正しい 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 report を参照してください。
run がログを送信する project で、マルチノードプロセスのコンソールログを表示するには、次の手順に従います。
  1. run を含む project にアクセスします。
  2. プロジェクトのサイドバーで Runs タブをクリックします。
  3. 表示したい run をクリックします。
  4. プロジェクトのサイドバーで Logs タブをクリックします。
コンソールログページ上部にある UI の検索バーでは、x_label に指定したラベルに基づいてコンソールログをフィルターできます。たとえば、次の画像は、rank0rank1rank2rank3rank4rank5rank6 の各値を x_label に指定した場合に、コンソールログのフィルターに使用できるオプションを示しています。`
マルチノードのコンソールログ
詳細は Console logs を参照してください。 W&B はすべてのノードのシステムメトリクスを集約し、W&B App UI に表示します。たとえば、次の画像は、複数ノードのシステムメトリクスを含むサンプルダッシュボードを示しています。各ノードには、x_label パラメーターで指定する一意のラベル (rank_0rank_1rank_2) があります。
マルチノードのシステムメトリクス
ラインプロットパネルをカスタマイズする方法については、Line plots を参照してください。

使用例

以下のコードスニペットは、高度な分散処理の利用でよくあるシナリオを示しています。

プロセスの生成

spawn されたプロセスで run を開始する場合は、メイン関数内で wandb.setup() method を使用します。
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() method を使用し、文字列 "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" に設定します。