Skip to content

필사 모드: マルチGPU・マルチノード学習プラットフォーム総まとめ — フレームワークの地図からSlurm・Kubeflow実践ガイドまで

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — GPUが増えた瞬間、問題はソフトウェアになる

GPU 1枚での学習はフレームワークが面倒を見てくれます。GPU 8枚、ノード4台になった瞬間から、インフラの問題が始まります — プロセスをどう起動し、互いをどう見つけさせ、失敗したらどう再起動するのか。本記事はその地形の全体を扱います — どんなライブラリがあるのか(エコシステム地図)、モデルをどう分割するのか(並列化戦略)、そしてジョブをどこに投げるのか(Slurm vs Kubeflow vs Ray)。AIモデル開発ライフサイクルの「分散学習スタック」の節を実践レベルに拡張した記事です。

第1部 — AIライブラリ・フレームワークのエコシステム地図

まずは登場人物から。層で分けると地形がはっきりします。

層                      代表プレイヤー                 一言まとめ
──────────────────────  ────────────────────────────  ─────────────────────────────
基盤フレームワーク      PyTorch 2.x                   事実上の標準。torch.compileでコンパイル加速
                        JAX                           関数型+XLA。TPU・Google系研究の中心
モデル・データハブ      HuggingFace Transformers      モデル定義の共通語
                        Datasets / Tokenizers         データロード・トークナイズの標準
ファインチューニング層  PEFT (LoRA), TRL (SFT/DPO)    少ないリソースでチューニング・アラインメント
                        Accelerate                    単一↔分散のコードを同じにする抽象化
分散学習エンジン        PyTorch DDP/FSDP              フレームワーク内蔵の並列化
                        DeepSpeed (ZeRO)              メモリ最適化の代名詞
                        Megatron-LM                   TP/PP込み、超大規模事前学習の標準
オーケストレーション    Slurm                         HPCクラスタの王
                        Kubeflow / Ray                Kubernetes・Pythonネイティブ陣営
サービング(参考)      vLLM / SGLang / TensorRT-LLM  学習が終わったらこちら — サービング編を参照

選び方の感覚としては、研究・ファインチューニングはPyTorch + HFスタックTPUや大規模並列研究はJAX超大規模事前学習はMegatron系、そしてその中間のあらゆる場所にDeepSpeedとFSDPがあります。

第2部 — 並列化戦略:「何が載らないか」からまず問う

並列化の選択は「何がGPUに載らないか」で決まります。

  • DDP(Data Parallel) — モデルは載るが、もっと速く 学習させたい。モデルを各GPUに複製してバッチを分割し、逆伝播の後に勾配をall-reduceで同期します。最も単純でスケール効率も良いため、可能なら常にDDPが第一候補です。
  • ZeRO / FSDP(Fully Sharded Data Parallel) — モデル(正確にはパラメータ+勾配+オプティマイザ状態)が 載らない。その3つをGPU群にシャーディングしておき、必要な瞬間だけ集めて使います。DeepSpeed ZeROのステージ(1: オプティマイザ、2: +勾配、3: +パラメータ)とPyTorch FSDPは、同じアイデアの2つの実装です。7B〜70Bファインチューニングの主力です。
  • TP(Tensor Parallel)1層すら載らない、あるいはレイテンシが重要。行列積そのものをGPU群に分割します。通信が頻繁なため、ノード内(NVLink)での使用が原則です。
  • PP(Pipeline Parallel) — 層をGPUグループに分けて、組み立てラインのように流します。マイクロバッチでパイプラインのバブルを減らします。ノード境界をまたぐ分割に向いています。
  • 実際の超大規模学習ではこれらを 3D並列(DP × TP × PP)として組み合わせ、MoEモデルならEP(Expert Parallel)が加わります。

暗記用の公式:載るならDDP → 載らないならFSDP/ZeRO → それでも無理ならTP・PPを追加。そしてどの組み合わせでも、混合精度(bf16)と勾配チェックポインティングは標準装備です。

第3部 — torchrun:すべての共通分母

SlurmであれKubeflowであれ、足元では多くの場合 torchrun(PyTorchの分散ランチャー)が動いています。概念は3つだけです — 全体のプロセス数(world size)、自分の順番(rank)、待ち合わせ場所(rendezvous)。

# 単一ノード 8 GPU
torchrun --nproc_per_node=8 train.py

# マルチノード(例:2ノード × 8GPU = world size 16)
# すべてのノードで同じコマンドを実行し、node_rankだけ変える
torchrun \
  --nnodes=2 --nproc_per_node=8 --node_rank=0 \
  --rdzv_backend=c10d --rdzv_endpoint=10.0.0.1:29500 \
  train.py

学習コードは torch.distributed.init_process_group() を呼んだ後、LOCAL_RANK 環境変数で自分のGPUを掴めば十分です。HF AccelerateやLightningを使えば、この配線はライブラリが肩代わりしてくれます。マルチノードの性能の前提条件を1つ — ノード間はEthernetではなく RDMA(InfiniBand/RoCE)でなければall-reduceがボトルネックになります。NCCLはその上で通信を担当します。

第4部 — Slurm使い方ガイド:HPCの王

Slurm は、数十年のHPCの歴史の中で磨かれてきたバッチスケジューラで、GPUクラスタ学習の事実上の標準です。バージョンは 年.月 方式(24.11、25.05 …)で、SchedMDが管理しています。概念は4つで十分です:ノード(機械) — パーティション(ノードの束、キュー) — ジョブ(リソース要求+スクリプト) — GRES(GPUのような汎用リソース)。

# クラスタの状態をざっと見る
sinfo                      # パーティション・ノードの状態
squeue --me                # 自分のジョブキュー
scontrol show node node01  # ノードの詳細

# ジョブ投入の3兄弟
sbatch job.sh              # バッチ投入(標準)
srun --pty bash            # インタラクティブシェル(デバッグ用)
salloc --gres=gpu:2        # リソースを先取りして手動実行

マルチノード学習の核心はsbatchスクリプトです。2ノード × 8GPUのtorchrun例:

#!/bin/bash
#SBATCH --job-name=llm-train
#SBATCH --partition=gpu
#SBATCH --nodes=2                  # ノード2台
#SBATCH --ntasks-per-node=1        # ノードあたりtorchrun 1つ(プロセスはtorchrunが8つ生成)
#SBATCH --gres=gpu:8               # ノードあたりGPU 8枚
#SBATCH --cpus-per-task=64
#SBATCH --time=48:00:00
#SBATCH --output=logs/%x-%j.out    # %x=ジョブ名 %j=ジョブID

# ランデブーのアドレス = 最初のノード
export MASTER_ADDR=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | head -n 1)
export MASTER_PORT=29500

# 各ノードでtorchrunを実行 — SLURM変数で配線を自動化
srun torchrun \
  --nnodes=$SLURM_JOB_NUM_NODES \
  --nproc_per_node=8 \
  --node_rank=$SLURM_NODEID \
  --rdzv_backend=c10d \
  --rdzv_endpoint=$MASTER_ADDR:$MASTER_PORT \
  train.py --config config.yaml

読み方:srun がジョブに割り当てられた 各ノードで1回ずつ torchrunを実行し、SLURM_NODEID がノードの順番を、scontrol show hostnames がマスターのアドレスを自動で埋めてくれます。このパターン1つがSlurmマルチノード学習の80%を占めます。残りの20%は運用のコツです — チェックポイントは --time 制限より頻繁に書く(プリエンプション・タイムアウト対策)、--signal=SIGUSR1@120 で終了2分前にシグナルを受け取って最後のチェックポイントを残す、アレイジョブ(--array)でハイパーパラメータスイープを回す、といったところです。

第5部 — Kubeflow使い方ガイド:Kubernetes陣営の答え

GPUクラスタがすでにKubernetesなら(GPU Operator でセットアップしたあのクラスタなら)、学習ジョブもKubernetesリソースとして投げるのが自然です。Kubeflow はその陣営の総合プラットフォームです。

コンポーネントの地図 — すべてを使う必要はありません:

コンポーネント     役割                                       必須か?
─────────────────  ─────────────────────────────────────────  ────────────────────────
Training Operator  分散学習ジョブのCRD(核心!)              ★ これだけで始められる
Pipelines          MLワークフローのDAGオーケストレーション    パイプライン化の段階で
Katib              ハイパーパラメータチューニング・AutoML     必要になったら
Notebooks          クラスタ内のJupyter環境                    便利機能
KServe             モデルサービング(別プロジェクト化)       サービング段階で

核心は Training Operator です。PyTorchJob CRD 1つで、マルチノード学習が宣言できます:

apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
  name: llm-train
spec:
  nprocPerNode: "8"                # ノード(Pod)あたりのプロセス数 = GPU枚数
  pytorchReplicaSpecs:
    Master:
      replicas: 1
      template:
        spec:
          containers:
            - name: pytorch
              image: my-registry/train:latest
              command: ["torchrun", "train.py"]
              resources:
                limits:
                  nvidia.com/gpu: 8
    Worker:
      replicas: 3                  # マスター1 + ワーカー3 = 4ノード
      template:
        spec:
          containers:
            - name: pytorch
              image: my-registry/train:latest
              command: ["torchrun", "train.py"]
              resources:
                limits:
                  nvidia.com/gpu: 8

Training Operatorがポッドを作り、MASTER_ADDRWORLD_SIZERANK 環境変数を 自動注入 してくれるので、Slurmで手作業だった配線が消えます。ジョブの状態は kubectl get pytorchjobs で確認します。なお、次世代の Kubeflow Trainer(v2) は、フレームワークごとのCRDを1つのTrainJobへ統合する方向に進化中です — 新規導入なら、ドキュメントでv2のサポート状況を確認してから始めてください。ギャングスケジューリング(全ノードが同時に確保されて初めて開始する方式)は、Volcano/Kueueのようなスケジューラを組み合わせて解決します。

第6部 — 選択基準:Slurm vs Kubeflow vs Ray

状況                                        おすすめ
──────────────────────────────────────────  ─────────────────────────
HPCの伝統がある組織、ベアメタルGPUファーム  Slurm
すでにKubernetesですべてを運用              Kubeflow (Training Operator)
Pythonコード内で柔軟に分散・サービング統合  Ray (Train/Serve)
研究室の小規模、ノード2〜4台                素のtorchrun + pdsh/tmuxで十分
クラウドマネージド志向                      SageMaker/Vertexなど(概念は同じ)

本質を1つだけ残すなら — どのプラットフォームでも足元は同じ です:torchrun(またはその等価物)がプロセスを起動し、NCCLがGPU間の通信を担い、チェックポイントが障害に耐えます。プラットフォームの違いは「誰がノードを貸してくれて、誰が環境変数を埋めてくれるか」だけです。だから、1つのプラットフォームでマルチノードをきちんと理解すれば、残りは翻訳の問題になります。

おわりに

GPUが1枚から複数枚・複数ノードへと増えるときに直面する決定を順に並べると:並列化戦略(載るならDDP、載らないならFSDP/ZeRO、それでも無理ならTP・PP)→ ランチャー(torchrun)→ オーケストレーター(SlurmまたはKubeflow)→ 運用(チェックポイント・RDMA・ギャングスケジューリング)。このスタックの上で学習が回り始めたら、次のボトルネックはデータです — その話は LLM学習データ前処理編 に続きます。

参考資料

현재 단락 (1/105)

GPU 1枚での学習はフレームワークが面倒を見てくれます。GPU 8枚、ノード4台になった瞬間から、インフラの問題が始まります — **プロセスをどう起動し、互いをどう見つけさせ、失敗したらどう再起動...

작성 글자: 0원문 글자: 6,723작성 단락: 0/105