[GPU編]AWS ParallelCluster SlurmにGPU系ジョブを投げるとクラスターがどうスケールするか試してみた

ジョブスケジューラーにSlurmを利用したAWS ParallelClusterではコンピューティングノードがAutoScaling Groupと連動してスケーリングします。 GPU系ジョブを投げて、どのようにスケールするか試してみました。
2020.08.27

AWS ParallelClusterのジョブスケジューラーに伝統的なスケジューラーを利用すると、コンピュートフリートはAmazon EC2 Auto Scaling Group(ASG)で管理され、ASGの機能を用いてスケールします。

ジョブスケジューラーのSlurmGPUベースのジョブを投げ、ジョブがどのようにノードに割り振られ、フリートがスケールするのか、主に ユーザー↔ジョブスケジューラー(Slurm)間のジョブ操作の観点から試してみました。

CPU 編はこちら

環境

  • AWS ParallelCluster : 2.7
  • ジョブスケジューラー : Slurm Workload Manager (Slurm)
  • Intel ハイパースレッディング : 無効
  • コンピュートノード : g4dn.xlarge(1 GPU)とg4dn.12xlarge(4 GPU)を利用
  • ノードの台数 : 最大4(max_queue_size=4)

やり方

必要なGPU数を指定したジョブを投げ、利用可能なGPU数によってジョブスケジューラーがどのようにジョブを割り振り、フリートをスケールさせるのか確認します。

実行に5分かかるスクリプトを用意します。

my.script

#!/bin/sh
srun -l /bin/hostname
sleep 300

このスクリプトを元に、GPU数を指定してジョブを投げます。

ジョブに必要なGPU数を指定するには sbatch--gpus=N 引数を渡します。

$ sbatch --gpus=2 --job-name job_name my.script

GPU 数を指定する方法としては、--gpus-per-node, --gpus-per-task など、複数有ります。詳細はマニュアルを参照ください。

sinfo コマンドを利用すると、ノードのGPU数(GRES)とGPUの利用状況(GRES_Used)を確認できます。

$ sinfo --Node --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-101      gpu:tesla:1         gpu:tesla:0(IDX:N/A)
ip-10-1-21-199      gpu:tesla:4         gpu:tesla:4(IDX:0-3)
  • GRES 列 は gpu:tesla:利用可能なGPUの個数
  • GRES_USED 列は gpu:tesla:利用中のGPU数(IDX:利用中のGPUのインデックス番号)

を表します。

シナリオ1:シングルGPUインスタンスを利用

コンピュートフリートには GPU を1基だけ搭載した g4dn.xlarge インスタンスを利用します。

$ sinfo --Node --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-101      gpu:tesla:1         gpu:tesla:0(IDX:N/A)
ip-10-1-21-212      gpu:tesla:1         gpu:tesla:0(IDX:N/A)

$ sinfo --long
Tue Aug 11 15:01:19 2020
PARTITION AVAIL  TIMELIMIT   JOB_SIZE ROOT OVERSUBS     GROUPS  NODES       STATE NODELIST
compute*     up   infinite 1-infinite   no       NO        all      2        idle ip-10-1-21-[101,212]

2 GPU必要なジョブを投げます。

$ sbatch --gpus=2 --job-name j1 my.script
Submitted batch job 2

各ノードは1GPUしか無いため、2ノードで処理します。

$ sinfo --Node --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-101      gpu:tesla:1         gpu:tesla:1(IDX:0)
ip-10-1-21-212      gpu:tesla:1         gpu:tesla:1(IDX:0)

$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 3   compute       j1   centos  R       0:44      2 ip-10-1-21-[101,212]

追加で2GPU必要なジョブを投げます。

$ sbatch --gpus=2 --job-name j2 my.script
Submitted batch job 4

GPU数が足りないので、job 4 に対するリソースの追加要求が発生し、4ノードになります。

$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 4   compute       j2   centos PD       0:00      2 (Resources)
                 3   compute       j1   centos  R       0:44      2 ip-10-1-21-[101,212]

既存のジョブが完了し、割当済みノードが idle になった、あるいは、新規ノードがジョブを受け付けるようになると、job 4 分も実行されます。

次に、4GPU(1GPU/ノード * 4ノード)が idle になるまで待ちます。

$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      4   idle ip-10-1-21-[101,146,175,212]

この状態で、2GPU必要なジョブを2つ投げます。

$ sbatch --gpus=2 --job-name j1 my.script
Submitted batch job 5
$ sbatch --gpus=2 --job-name j2 my.script
Submitted batch job 6

4 ノードにまたがる 4 GPU をフル活用してジョブを処理します。

$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      4    mix ip-10-1-21-[101,146,175,212]

$ squeue --long
Tue Aug 11 15:18:21 2020
             JOBID PARTITION     NAME     USER    STATE       TIME TIME_LIMI  NODES NODELIST(REASON)
                 6   compute       j2   centos  RUNNING       0:37 UNLIMITED      2 ip-10-1-21-[175,212]
                 5   compute       j1   centos  RUNNING       0:35 UNLIMITED      2 ip-10-1-21-[101,146]


$ sinfo --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-101      gpu:tesla:1         gpu:tesla:1(IDX:0)
ip-10-1-21-146      gpu:tesla:1         gpu:tesla:1(IDX:0)
ip-10-1-21-175      gpu:tesla:1         gpu:tesla:1(IDX:0)
ip-10-1-21-212      gpu:tesla:1         gpu:tesla:1(IDX:0)

シナリオ2:マルチGPUインスタンスを利用

コンピュートフリートには GPU を4基搭載した g4dn.12xlarge インスタンスを用意します。

$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      1   idle ip-10-1-21-199
$ sinfo --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-199      gpu:tesla:4         gpu:tesla:0(IDX:N/A)

先程と同じく、2GPU のジョブを2つ連続して投げます。

$ sbatch --gpus=2 --job-name j1 my.script
Submitted batch job 2
$ sbatch --gpus=2 --job-name j2 my.script
Submitted batch job 3

1ノードで4GPUあるため、ノードを追加することなく、1ノードに完結して処理します。

$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 2   compute       j1   centos  R       0:07      1 ip-10-1-21-199
                 3   compute       j2   centos  R       0:01      1 ip-10-1-21-199


$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      1    mix ip-10-1-21-199
$ sinfo --Format=NodeHost,Gres,GresUsed
HOSTNAMES           GRES                GRES_USED
ip-10-1-21-199      gpu:tesla:4         gpu:tesla:4(IDX:0-3)

Slurm(ジョブスケジューラー)↔Auto Scaling Group間のノードのスケーリングについて

Slurm(ジョブスケジューラー)↔Auto Scaling Group間のノードのスケーリングについては、次のドキュメントで詳細に記載されています。

How AWS ParallelCluster works - AWS ParallelCluster

  • ジョブスケジューラーにノード追加が必要化チェックする jobwatcher
  • ASG によりノードの追加・削除されたイベントをジョブスケジューラーに通知する sqswatcher
  • コンピュートノードで idle 状態が続き、ノードの削除が必要化チェックする nodewatcher

などが裏方として活躍しています。

最後に

ジョブスケジューラーにGPU系ジョブを投げ、どのようにリソースに割り振られるのか確認しました。

EC2の最新のGPU系インスタンス G4 はSingle GPU VM(右記2サイズを除くすべて) と Multi GPU VM(g4dn.12xlarge と g4dn.metal) に分かれており、Single GPU VM は名前の通り1 GPU、Multi GPU VM の場合、g4dn.12xlarge は4個、g4dn.metalは8個となっています。

GPUクラスターを構成する際は、選択肢の広いSingle GPUインスタンスをたくさん並べてスケールアウトさせるのか、ノードあたりの火力が強力なハイエンドのMulti GPUインスタンスを並べるのか、十分にご検討ください。

それでは。

参照