前置き
前回の記事で「短期決戦・スクラッチ向き」とか書いた途端に、永続的ストレージの発表があり、頭を抱えた筆者です。多数のユーザーが混在するクラウド上においてはパフォーマンスと同時にセキュリティも重要ですが、条件付きながらデータ転送も保存データも暗号化されています。普通のLustreでは行われていないOSTの2重化すら実現しています。さらにパフォーマンス向上も実現しています。これでAWS上に「普通のLustre」をつないだ「普通のスパコン」を運用する上で必要な、ある意味それ以上の「モノ」はほぼ揃ってしまいました。今回はその作り方と使い方を簡単に勉強しておきましょう。
AWSとHPC環境について
地球シミュレータや京、中国のSunway TaihuLightは、一般には入手不可能な専用ハードウエアを使った特殊なコンピュータでしたが、現在多くのスパコンは汎用機材を組み上げて作られるクラスターマシンです。つまり、多数のマシンをつなぎ合わせれば同様なものができてしまいます。それを効率的に使えるようにしたりする仕組みも用意されているので、クラウド上にスパコンを作りたいユーザー側の技術的な困難は大幅に削減されました。もちろんそれを実現するバックグラウンドには驚嘆すべき技術が盛り込まれています。
かつてEC2の発表とほぼ同時に、それを科学技術計算に使おうという試みは始まり、様々なベンチマークが取られました。初期のものはユーザーが満足できるものではなかったわけですが、一貫して大規模計算に向けた環境が用意され続けており、Top500でもEC2上に作られたクラスターが昨年6月に136位、11月に同システムが179位にランクインしています。そうした中でMITで開発されたStarClusterは、2009年にGuthubへバージョン0.9が登録されていて、簡単な設定ファイルを用意すればクラスターを自動構成でき、運用と利用の一連の作業が完結できるソフトウエアです。しかし使えるインスタンス名が直書きされていたり、いちいちAPIとsshを連携させるような作りになっていて、言ってみれば手作業でクラスターを作る流れをスクリプト化したのに近いものでした。それゆえ昨今のクラウド利用方法とは相容れず、バージョン1.0に至る前に開発が止まり、AWSから発表されたCfnClusterへその座を譲りました。CfnClusterはAWSに馴染みがある人にはおわかりの通り、CloudFormationの仕組みを使ったものですが、ユーザーから見た使い勝手はStarClusterをほぼ踏襲しています。そして2018年11月のタイミングでParallel Clusterに名称が変更されました。それ以降も絶えず機能強化が行われ、今回とりあげているFSx for Lustreにも対応かつ、シンプルに使えるようになっています。
ちなみにParallel Clusterには詳しいマニュアル、しかも日本語のものがあります(機械翻訳らしく、たまに変なところがあります)。VPCやEC2に関する初歩的な知識さえあれば読める内容で、使うだけならCloudFormationの知識は一切不要です。インストールなどについては他に譲るとして、早速使ってみましょう。以下で解説するのは標準的なHPCクラスターに関するものですが、ここではあえてスパコンと呼んで煽り気味に行ってみましょう。
スパコンを作る
HPCクラスターは基本的に、ユーザーがログインして使うホストと呼ばれるマシン(マスターノードやホストノードと呼ばれる)と、アカウント情報を共有した多数のマシン(計算ノード)からなり、共有ファイルシステムで同一のパスで同じファイルが見えるようにしてあります。そのためどのマシンにログインしてもホスト名以外に違いはない状態を作っています。ここでは初期コンフィグとほぼ変らない以下の設定を使います。外部からログインを可能にしているマスターノードと、そうでない計算ノードは別々のサブネットに割り当てられています。
$ cat ~/.parallelcluster/config [aws] aws_region_name = us-west-1 [global] cluster_template = default update_check = true sanity_check = true [aliases] ssh = ssh {CFN_USER}@{MASTER_IP} {ARGS} [cluster default] key_name = tech-blog@hpc.co.jp base_os = centos7 scheduler = slurm master_instance_type = t3.micro compute_instance_type = c5n.xlarge maintain_initial_size = true vpc_settings = default cluster_type = spot [vpc default] use_public_ips = false vpc_id = vpc-XXXXXXXXXXXXXXXXX master_subnet_id = subnet-YYYYYYYYYYYYYYYYY compute_subnet_id = subnet-ZZZZZZZZZZZZZZZZZ
この設定でpcluster create tech-blog
とすると、AWSの上で様々な機構が動き出します。10分弱かかりますがtech-blog という名前のクラスターがデフォルト設定で作られ、t3.microの小さなマスターノードだけが起動します。マスターノードにsshログインしてみましょう。
$ pcluster create tech-blog Beginning cluster creation for cluster: tech-blog Creating stack named: parallelcluster-tech-blog Status: parallelcluster-tech-blog - CREATE_COMPLETE ClusterUser: centos MasterPrivateIP: 10.0.0.147 $ pcluster ssh tech-blog Last login: Wed Mar 18 03:28:29 2020 [centos@ip-10-0-0-147 ~]$
パブリックIPアドレスを知る必要もなく、ユーザーcentosでsshログインまでできました。
多数の計算処理(ジョブ)を多数のノード上で実行するわけですが、その割り当てを人手でやるのはいささか面倒です。ましてユーザーが複数いたらリソースの奪い合いで戦争が起こります。そこでわんこそばのように、状況をモニタリングしつつ空いたリソースにジョブを自動的に投げ込んでくれるソフトウエアがあります。ジョブスケジューラと呼ばれるそれは、有償製品としてはIBM Spectrum LSF Suite、Univa Grid Engine、Adaptive Computing Moab HPCなどが存在します。Parallel Clusterが標準で用意しているのはフリーのTorque, SGE, Slurmの3つですが、もうひとつ、自分で作成したコンテナベースでジョブ実行をコントロールするAWS Batchを使うことも可能です。最近のアップデートで、AWS BatchコンテナからFSx for Lustreにアクセスできるようになりました。ここでは最近よく使われるSlurmを使う設定にしています。
スパコンの使い方
まず指定したスケジューラが使えるかの確認をします。
$ lsid Slurm 19.05.5, May 1 2019 Copyright SchedMD LLC, 2010-2017. My cluster name is parallelcluster My master name is ip-10-0-0-147 $ sinfo PARTITION AVAIL TIMELIMIT NODES STATE NODELIST compute* up infinite 0 n/a
lsid
は元々はLSF由来のコマンドですが、スケジューラの名称などを確認できます。バージョン19.05.5のSlurmが使えています。sinfo
はクラスターの状態を表します。多数のノードやスペックが異なるマシンが混在している場合に、それらを別々に扱うパーティションという概念があります。ここでは唯一computeというパーティションだけあります(末尾の*はデフォルトを示しています)が、ノード数は0になっています。リストも空っぽです。
アプリケーションの起動コマンドやファイルパスはマスターノードも計算ノードも同一になっているので、ユーザーはそれをマスターノードからスケジューラに投げ、あとは待っているだけという使い方をします。スクリプトを投げっぱなしにする場合はsbatch
コマンド、インタラクティブに実行するsrun
コマンド、他のジョブが入り込んでこないよう予約しておいて使うsalloc
コマンドがあります。ユーザーはジョブがどのマシンで動いているかを気にする必要はありません。ジョブはキューという待ち行列で管理されます。ファミレスの入り口でいつもやる名前と人数などを書き込んでおくアレと一緒で、席が空いたら店員(スケジューラ)が先頭から順番に割り当てていきます。計算ノードにログインして勝手にジョブを起動してしまうことは出来ますが、そういうマナー違反は社会的に抹殺されることでしょう。ちゃんとスケジューラを使うようにして(させて)ください。待ち行列のことをキューと呼び、キューの状況を見るのがsqueue
コマンドです。
$ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
まだ何もしてないので空っぽです。 そこで以下のようなジョブスクリプトを書いて、どさっとキューに投げ込んでみましょう。sbatch
コマンドを使うのでした。
$ cat job.sh #!/bin/bash date >> jobs.log hostname >> jobs.log sleep 180 $ sbatch job.sh # これを15回ほど繰り返す。 Submitted batch job 2 $ sbatch job.sh Submitted batch job 3 ......
ジョブにはユニークなIDがふられていき、この番号でジョブを管理できます。さてキューの状態を見てみましょう。
$ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 2 compute job.sh centos PD 0:00 1 (Nodes required for job are DOWN, DRAINED or reserved for jobs in higher priority partitions) 3 compute job.sh centos PD 0:00 1 (Nodes required for job are DOWN, DRAINED or reserved for jobs in higher priority partitions) ...中略... 14 compute job.sh centos PD 0:00 1 (Nodes required for job are DOWN, DRAINED or reserved for jobs in higher priority partitions) 15 compute job.sh centos PD 0:00 1 (Nodes required for job are DOWN, DRAINED or reserved for jobs in higher priority partitions)
処理を実行するための計算ノードがないのでステータス(ST)がペンディング(PD)のままです。しかし3〜5分ほどしてsinfo
を実行すると以下のようにノードが7に増えて、NODELISTにホスト名が並びます。そしてsqueue
の結果も変わり、ジョブのステータスは実行中(R)となり、実際に割り当てられた計算ノードのホスト名が表示されます。
$ sinfo PARTITION AVAIL TIMELIMIT NODES STATE NODELIST compute* up infinite 7 alloc ip-10-0-20-123,ip-10-0-21-4,ip-10-0-23-68,ip-10-0-24-245,ip-10-0-27-19,ip-10-0-28-110,ip-10-0-29-54 $ squeue JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 2 compute job.sh centos R 0:13 1 ip-10-0-20-123 3 compute job.sh centos R 0:13 1 ip-10-0-20-123 ...中略... 4 compute job.sh centos R 0:13 1 ip-10-0-21-4 5 compute job.sh centos R 0:13 1 ip-10-0-21-4
ここで起動しているc5.large
はコア数が2のインスタンスなので、2〜15の14個のジョブを同時に終わらせるには7ノードあれば実現できるため、7インスタンスが起動されています。スケジューラは起動して利用可能になった計算ノードへ、オプションでコア数などの要求がない今回のジョブについて1つずつを割り当てて実行しています。
デフォルトでは計算ノード数は最小値が0、最大値が10となっていますが、起動が許されているインスタンス数までは拡大可能ですし、最小値に0以外を設定すればノードを常時起動させておくことも出来ます。キューが空いてジョブが数分間投入されなければ、自動的に計算ノードはシャットダウンされ、無駄な課金を防ぎます。マスターとクラスター設定は残るので、またジョブを投入したら計算ノードが起動します。HPCでは計算ノードにハイスペックなインスタンスを使うことが多いので、それを多数起動していてはお金がいくらあっても足りません。config
ファイルでspot
となっているのに気づいた方はいらっしゃるかもしれませんが、指値を入れなければオンデマンド料金が自動的に設定されます。素晴らしいですね
さて、出力結果jobs.log
を見てみましょう。
$ cat jobs.log Mon Mar 23 02:32:24 UTC 2020 Mon Mar 23 02:32:24 UTC 2020 ip-10-0-23-68 ip-10-0-23-68 32:24 UTC 2020 ip-10-0-20-123 2:24 UTC 2020 ip-10-0-27-19ipip-10-0-29-54 ip-10-0-27-19
データが上書きされて壊れていることが分かります。ホームディレクトリはホストノードのものをNFS共有していますが、たった十数個でも複数プロセスからNFS上の単一ファイルに書き込もうとするとこういうことが起こります。NFSはファイルのロックや同期に関して厳密ではなく、ばらばらに動いているうちは良いのですが、複数のプロセスがファイルへ書き込む必要がある場合や、あるジョブの出力に依存して次のジョブが実行される場合などには、かなり意識していないと問題が顕在化します。Lustreの上でこれをやると、行の順番こそ保証されませんがデータの上書きなどが生ずることはありません。ちょっとやってみましょう。
はじめてのLustre
`/.parallelcluster/config
に追加するのは最小4行だけです。
[cluster default] ...中略... fsx_settings = lustre-blog # ここで名前を付けます。 [fsx lustre-blog] # ここで名前を付けた設定を書きます。 deployment_type = SCRATCH_2 # SCRATCH_1(デフォルト), SCRATCH_2, PERSISTENT_1 が利用可能 shared_dir = /lustre # 各ノードでの共有ディレクトリ storage_capacity = 1200 # 容量(GB)
deployment_type
はSCRATCH_1が従来通りのFSx for Lustreで、SCRATCH_2
が最近アップデートされたバーストできるもの、そして冗長構成が入った永続的ストレージと呼ばれるモードがPERSISTENT_1
になります。目的に応じて設定します。容量が最小1.2TBで、2.4TB、3.6TBとなっているのは、OSTのサイズが1.2TBごとなのでしょう。そしてスループットが容量指定できまるのは、OSS/OSTが増えていくことに対応しているのだと理解できます。逆に数百GBを超えるようなファイルを抱える場合には、ストライプ設定を入れないと厳しいかもしれません。実際にLustreの構成情報をとってみましょう。
$ lfs df # ターゲット別に空き容量を見ます。 UUID 1K-blocks Used Available Use% Mounted on 3ovshbmv-MDT0000_UUID 36030976 5248 36023680 0% /lustre[MDT:0] 3ovshbmv-OST0000_UUID 1168351232 4608 1168344576 0% /lustre[OST:0] filesystem_summary: 1168351232 4608 1168344576 0% /lustre $ lfs df -i # i-node数(保存可能ファイル数)に関する空き容量を見ます。 UUID Inodes IUsed IFree IUse% Mounted on 3ovshbmv-MDT0000_UUID 7188215 221 7187994 0% /lustre[MDT:0] 3ovshbmv-OST0000_UUID 241884486 224 241884262 0% /lustre[OST:0] filesystem_summary: 7188215 221 7187994 0% /lustre
MDTが36GB、OSTが1.2TBが1つずつという構成で、そもそも並列にすらなっていません。ジョブ実行スクリプトを書き換えて/lustre/jobs.log
へ追記するようにし、sbatch
コマンドで20個同時に投げ込んでみます。
$ for i in {1..20}; do sbatch jobs.sh; done Submitted batch job 3 Submitted batch job 4 ...中略... $ cat /lustre/jobs.log Mon Mar 18 06:52:04 UTC 2020 Mon Mar 18 06:52:04 UTC 2020 ip-10-0-17-130 ip-10-0-17-130 Mon Mar 18 06:52:04 UTC 2020 Mon Mar 18 06:52:04 UTC 2020 ip-10-0-17-162 ip-10-0-17-162 Mon Mar 18 06:52:04 UTC 2020 Mon Mar 18 06:52:04 UTC 2020 ip-10-0-19-32 ip-10-0-19-32 ...中略...
ファイルが壊れることもなく、ちゃんとしていますね。今回はスパコン(HPCクラスター)を作る練習と使う練習をして、LustreとNFSの顕著な違いと実際に起こりうる問題を見てもらいました。前回少し触れたように、Lustreはクラスターの多数のノードを一つのシステムとして見なせるような作りになっていることの片鱗を感じ取っていただければ今回の記事は成功です。
さて、クラスターはしばらく使わないのであれば、pcluster delete tech-blog
のようにして止めておきましょう。この設定で起動しているマスターノードはスポットで起動しているt3.micro
なので課金も大したことはないのでしょうが、Lustreは常時稼働です。不要なものを起こしておいて良いことはありません。
次回こそは事例をやりたいと思います。