Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

分散バッチジョブを作成する

このページでは PFCP クラスタ上で分散バッチ処理を実行するための ParallelJob の作成方法を説明します。

Note

実験的機能のため、将来 API スキーマが変更される可能性があります。

概要

ParallelJob は、複数のノード間で協調して動作する分散バッチジョブを簡単にデプロイ・管理するための Kubernetes カスタムリソースです。ParallelJob には以下の特徴があります。

  • 複数のフレームワークに対応: MPI などの分散処理フレームワークをサポート。
  • Gang Scheduling: 分散バッチジョブ内の全 Pod が同時にスケジューリングされることを保証。
  • ジョブ失敗時の再実行: 1 つのジョブが失敗した場合の ParallelJob 全体の自動再実行。

ParallelJob がサポートしているランタイム

Info

今後、複数のランタイムをサポートする予定ですが、現時点では Open MPI ランタイムのみ利用可能です。

Open MPI

Message Passing Interface(MPI)実装の 1 つである Open MPI を使用した並列計算をサポートします。Open MPI ジョブでは、1 つの launcher Pod が複数の worker Pod に SSH 経由で接続し、MPI を用いた並列計算を実行します。launcher Pod は rank=0 の worker としても使用されます。

以下は、MPI ランタイムを使用する ParallelJob の設定例です。

apiVersion: preferred.jp/v1alpha1
kind: ParallelJob
metadata:
  name: mpi-sample-job
spec:
  # 利用するMPIランタイムを指定
  runtimeRef:
    name: mpi-openmpi

  # LauncherとWorkerを含むPodの数です。
  # MPIランタイムではLauncherは1つで、残りがWorkerとなります。
  numPods: 3
  # PodあたりのMPIプロセス数で、MPIのhostfileのslotsに設定されます。
  # アクセラレータを用いた計算の場合は Pod あたりの アクセラレータ数、flat MPI の場合は CPU コア 数、ハイブリッド並列の場合は 1 を指定するケースが多いです。
  numProcPerPod: 2

  # Launcher用PodのTemplateの設定です。PodTemplateSpec形式で記述します。
  # `main` コンテナが含まれない場合、ParallelJobの作成に失敗します。
  launcher:
    spec:
      containers:
      - name: main # MPIを実行するコンテナは `main` としてください。
        image: ghcr.io/pfnet/parallel-controller/openmpi:v0.1.0
        command:
        - sh
        - -c
        - |
          cat > hello_mpi.c << 'EOF'
          #include <mpi.h>
          #include <stdio.h>

          int main(int argc, char *argv[]) {
              MPI_Init(&argc, &argv);
              int rank, world_size;
              MPI_Comm_rank(MPI_COMM_WORLD, &rank);
              MPI_Comm_size(MPI_COMM_WORLD, &world_size);
              printf("Hello from MPI process %d rank in %d processes\n", rank, world_size);
              MPI_Finalize();
              return 0;
          }
          EOF
          mpicc -o hello_mpi hello_mpi.c
          mpirun --allow-run-as-root ./hello_mpi

  # (Optional) Worker用PodのTemplateの設定です。PodTemplateSpec形式で記述します。
  # Workerの設定はLauncherから継承され、Launcherと通信する用のコンテナは `main` という名前で自動生成されます。
  # worker: nil

独自のコンテナイメージを使用する

Open MPI ランタイムで独自のコンテナイメージを使用する場合は下記のソフトウェアが含まれている必要があります。

  • Open MPI
  • ssh (SSH クライアント)
  • sshd (SSH サーバー)

シーン別設定例

以下に、実際の利用シーンでよく使用される設定例を示します。

失敗時のリトライ設定

デフォルトでは、ParallelJob 内のいずれかのジョブが失敗した場合、ParallelJob 全体が最大 3 回まで再実行されます。リトライ回数を変更するには、.spec.failurePolicy.maxRestarts フィールドを設定します。以下は、リトライ回数を 1 回に設定する例です。

apiVersion: preferred.jp/v1alpha1
kind: ParallelJob
metadata:
  name: mpi-sample-job
spec:
  failurePolicy:
    # ジョブ失敗時にParallelJob全体を再実行する最大回数です。(デフォルト: 3)
    maxRestarts: 1
...

Note

Preemption や Eviction によるジョブ中断はリトライ回数にカウントされません。

GPU/RDMAリソースの指定

分散ジョブで GPU や RDMA リソースを使用する場合、Pod テンプレートで該当リソース要求を指定します。 NCCL や UCX の設定ファイルは自動生成されますが、読み込みは明示的に行う必要があります。以下は、launcher Pod に GPU と RDMA デバイスを要求し、NCCL と UCX の設定ファイルを読み込む例です(今後のアップデートで自動化予定です)。

apiVersion: preferred.jp/v1alpha1
kind: ParallelJob
metadata:
  name: sample-job
spec:
  launcher:
    spec:
      containers:
      - name: main
        command: ["/bin/sh", "-c"]
        args:
        # Note: NCCLやUCX用の設定ファイルは自動生成されますが、読み込みは明示的に行う必要があります。
        - |
          [ -f "$RDMA_NCCL_CONF" ] && . "$RDMA_NCCL_CONF"
          [ -f "$RDMA_UCX_CONF" ] && . "$RDMA_UCX_CONF"

          mpirun --allow-run-as-root something-using-gpu-rdma
        resources:
          limits:
            nvidia.com/gpu: "2"
            preferred.jp/rdma: "1"
...

Note

RDMA リソースは次のクラスタでのみ利用可能です。

  • IK1-01
  • YH1-01

トラブルシューティング

分散ジョブの実行中に問題が発生した場合、以下の手順でトラブルシューティングを行います。

ジョブの状態確認

ParallelJob の状態を確認するには、以下のコマンドを実行します。

# ParallelJob の状態を確認
kubectl get paralleljobs sample-job

# イベントを含めた詳細情報を確認
kubectl describe paralleljobs sample-job

関連する Job / Pod の状態を確認するには、以下のコマンドを実行します。

# ParallelJob に紐づく JobSet 名を変数に設定
jobset_name=$(kubectl get paralleljobs sample-job -o jsonpath={".status.jobGroupName"})

# 関連する Job / Pod の状態を確認
kubectl get jobs,pods -l jobset.sigs.k8s.io/jobset-name=${jobset_name}

Podのログ確認

rank=0 の Pod のログを取得するには、以下のコマンドを実行します。

# ParallelJob に紐づく JobSet 名を変数に設定
jobset_name=$(kubectl get paralleljobs sample-job -o jsonpath={".status.jobGroupName"})

# ログの表示
kubectl logs -f $(kubectl get pod -l jobset.sigs.k8s.io/jobset-name=${jobset_name},jobset.sigs.k8s.io/job-global-index=0 -o name)

Note

ログは、Pod が存在する場合のみ確認できます。正常終了の場合はすべての Pod が残り、エラー終了の場合はエラーとなった Pod のみが残ります。また、ParallelJob を削除すると、関連する Pod もすべて削除されます。