SlurmでN枚GPUの刺さったノードにNジョブ割り当てるには

目次

これはrioyokotalab Advent Calendar 2020 4日目の記事です.

[追記:2021.04.06] この記事のきっかけとなったプロジェクト

2020年度のひなどりクラスタ - Rio Yokota Lab Blog

Slurmとは&この記事の内容について

Slurmの説明いらないですよね,みんな大好きジョブスケジューラです.
無料で使えますし,Ubuntuを使っている場合はaptで簡単にインストールできますし,ユーザがそれなりいるのでググれば情報はたくさん出てきます.
そういった点でとても使いやすいものとなっているのかなと思います.

それはそうと,世の中には1ノードに複数(N)GPUを搭載した計算機がたくさん存在します.
ノード数が少ないというのは管理の面から考えると楽なのです.
しかし,ジョブスケジューリングを行う場合,1ジョブに1ノードを割り当ててしまうと有効にGPUを利用できない可能性があります.
例えば,もし1ジョブが1GPUしか利用しない場合,残りの(N-1) GPUは稼働しないこととなるのです.
これは明らかに効率的なジョブスケジューリングとは言えません.
今回の話は,SlurmでN GPUをN ジョブに割り当てるにはどうすればいいかという話です.

どうやるの?

自分はこのリポジトリを参考に設定を行いました.
dholt/slurm-gpu - GitHub

SlurmにはGRES (General RESource)と呼ばれる機能があり,これを用いることで今回行いたい複数GPUを複数ジョブに割り当てることができます.
今回はこれを用いて設定していきます.
GRESは他にもNVIDIAのMPS (Multi-Process Service)やIntelのMIC(Many Integrated Core)にも対応しています.

環境

  • OS : Ubuntu 20.04
  • Slurm : 19.05.5

今回扱うクラスタは「ログインノード」と「計算ノード」からなります.
ログインノードでslurmdbdとslurmctldを立ち上げ,ジョブスケジューリングをさせます.

データベースの準備(on ログインノード)

データベースは別に何でもいいが,トランザクション管理もしてくれるストレージエンジンを使ってねとのこと.
aptでmysqlのインストールが終わったら
sudo /usr/bin/mysql_secure_installation
でデータベースの初期化を行います.
終わり次第
CREATE USER 'slurm'@'localhost' IDENTIFIED BY 'password';
CREATE DATABASE slurm_acct_db;
GRANT ALL ON slurm_acct_db.* TO slurm@localhost;
でユーザ,データベースの作成と権限付与を行います.
MySQLのどこかのバージョンから権限付与時にユーザの追加を同時に行うことができなくなったため,分けて行う必要がありました.

InnoDB周りの推奨設定があるらしので,念の為/etc/mysql/my.cnfに以下を追記.

[mysqld]
innodb_buffer_pool_size=1024M
innodb_log_file_size=64M
innodb_lock_wait_timeout=900
innodb_buffer_pool_sizeはRAMの半分くらいを指定してもいいかもとのこと.
追記次第mysqlを再起動.
sudo systemctl restart mysql.service

SlurmDBDのインスト〜ル(on ログインノード)

SlurmDBDというのはジョブの実行状況などをデータベースで管理するためのデーモンです.
別にインストールしなくともテキストベースの管理でSlurmは動きはするのですが,今回はこれをインストールしろと書かれているのでインストールし設定していきます.

aptで入れます.

sudo apt install slurmdbd

slurmdbdの設定ファイル/etc/slurm-llnl/slurmdbd.confを作成します.
passwordはデータベースの権限付与で設定したものに書き換えてください.
この設定ファイルではログファイルの出力先を/var/log/slurm/slurmdbd.logとしているため,このディレクトリを作成しておきます.

sudo mkdir /var/log/slurm
また,見ての通りデーターベースのパスワードを直書きしているため,この設定ファイル自体のアクセス権限を修正します.
sudo chown slurm: /etc/slurm-llnl/slurmdbd.conf
sudo chmod 600 /etc/slurm-llnl/slurmdbd.conf

最後にslurmdbdの起動&有効化を行ってインストールは完了です.

sudo systemctl enable --now slurmdbd

データベースへのクラスタの登録(on ログインノード)

Slurmのsacctmgrコマンドでデータベースへのクラスタの登録を行います.
cluster_nameは自身で決めたクラスタ名を指定します.

sudo sacctmgr add cluster cluster_name
設定が正しく終わると
mysql -p -u slurm slurm_acct_db
mysql> show tables;
でクラスタ名から始まるテーブルがいくつか見えるはずです.

cgroupsの設定(on 計算ノード)

GPUの数だけ1ノードにジョブを割り当てるのが今回の目的ですが,同時にCPUやメモリと行った資源も分割して提供できるようにします.
/etc/default/grubGRUB_CMDLINE_LINUXという変数があるため,この右辺に以下を追記します.

cgroup_enable=memory swapaccount=1
再起動させて反映させます.

次にcgroupで管理するものリストを作成します.

  • /etc/slurm-llnl/cgroup.conf
    CgroupAutomount=yes
    CgroupMountpoint="/sys/fs/cgroup"
    CgroupReleaseAgentDir="/etc/slurm-llnl/cgroup"
    
    ConstrainCores=yes
    ConstrainDevices=yes
    ConstrainRAMSpace=yes
    
    AllowedDevicesFile="/etc/slurm-llnl/allowed_devices.conf"
    
  • /etc/slurm-llnl/allowed_devices.conf
    /dev/null
    /dev/zero
    /dev/urandom
    /dev/cpu/*/*
    /dev/nvidia*
    

MUNGEの設定(on ログインノード&計算ノード)

MUNGEはSlurmで使われている認証サービスで,ホスト間の接続の暗号化などを行ってくれるものです.
aptで必要なパッケージをインストールします.

sudo apt install munge libmunge-dev libmunge2
インストール後mungeを起動&有効化します.
sudo systemctl enable --now munge
ここまで行うと/etc/munge/munge.keyという鍵が出来上がるかと思います. これをクラスタの全ノードで共有する必要があるため,方法は何でもいいのでログインノードの鍵を全ノードへ頑張ってコピーします.
計算ノードへ鍵の配布が終わったらmungeを再起動して完了です(本当に必要かはしらん).

Slurmのインストール(on ログインノード&計算ノード)

aptで必要なパッケージをインストールします.

sudo apt install slurm-wlm

Slurmの設定ファイル(ログインノード&計算ノード)

次にSlurmの設定ファイル/etc/slurm-llnl/slurm.confを作成or編集します.
デフォルトのファイルはここにあります.
SchedMD/slurm slurm/etc/slurm.conf.example - GitHub 変更すべき点はこれです.
dholt/slurm-gpu #scheduling-resources-at-the-per-gpu-level - GitHub

これを反映させて私が今使っている設定ファイルはこちらです.

GRESの設定(計算ノード)

GRESの設定ファルではCPUコアとGPUの対応を/etc/slurm-llnl/gres.conf記述します.

Name=gpu File=/dev/nvidia0 CPUs=0-7
Name=gpu File=/dev/nvidia1 CPUs=8-15

自動生成するツールもあります(作りました).
enp1s0/gres_config_gen - GitHub
Ansibleなんかで便利かも.

ぼやき

ノード起動時に/dev/nvidiaXがない場合があったのですが,nvidia-smiを実行すると生まれることがわかったため,nvidia-smiを実行するだけのsystemdのサービスを作って起動時に自動で実行されるようにしています...

Slurmの起動&有効化(ログインノード&計算ノード)

最後に計算ノードではslurmdを,ログインノードではslurmdbdを起動&有効化ます.
すでにmungeが起動していることを確認してから行ってください.

計算ノード

sudo systemctl enable --now slurmd

ログインノード

sudo systemctl enable --now slurmctld

使ってみる

取り敢えずsrunで1 GPUでnvidia-smiを実行してみます.

srun --gres=gpu:1 nvidia-smi
バッチジョブではこんな感じ.

cgroupによりメモリ使用量やCPUのコア数の制限を行う場合は,

srun --gres=gpu:1 --ntasks-per-node=8 --mem=1000 nvidia-smi
のように資源量を指定します.
仮にcgroup制限をかけてもtop/htop等のコマンドでは全資源が見えるようです.
本当に制限が行えているかはprocコマンドでコア数を見たりすると確認できます.

終わりに

自分がクラスタの設定を行っているときの悪戦苦闘メモを記事に書き起こしてみましたが,メモが若干雑なので何か書き漏らしているかもしれません,ごめんなさい.

カテゴリー:サーバ
記事作成日:2020-12-04