はじめに
これは「スパコンを使う #1 〜申し込みからアクセスまで〜」の続きです。話の流れ的にこちらをざっとみていただけるとすんなり入れると思います。
今回も、「スパコン超入門」の講習会内容を主に参照しながら進めていきます。
目標は、スパコンに実際にコードを実行してもらい結果を手元のパソコンで見られるようにすることです。
目次
-
サンプルコードを実行してみる
1.1. ディレクトリ構造
1.2. 環境構築(Environment module)
1.3. コード準備
1.4. コンパイル
1.5. ジョブ実行
1.6. sftpコマンドを使ったファイルの送受信 - 補足
1. サンプルコードを実行してみる
この章ではスパコン超入門に従って、サンプルコードを実行できるまでになる。実行はC/C++, Fortran, Pythonで可能だが今回はC/C++でのやり方のみ書く。(余裕あったらPythonも書くかも)
1.1. ディレクトリ構造
スパコン超入門の資料を引用しながらざっくりとした理解をすると、操作するPCとスパコンへのログインを管理するPCと計算をするPCが違って、色々設定する必要があるから所々気をつける必要があるみたい。
資料の引用にある実行までの流れとしては、
- SSHでログイン:(Putty、Cygwin)、SSH、鍵認証
- プログラム作成:エディタ(emacs, vi, nano)、Linux 利用法
- コンパイル :環境モジュール、コンパイルオプション
- ジョブの投入 :ジョブスクリプトの作成、ジョブ管理
- 結果の確認
となるが、プログラム作成、ジョブスクリプト作成などについては手元のパソコンで(VScodeなどを利用して)作成してからsftp
コマンドを使って容易にデータ転送可能(後述)なので、エディタを覚える必要はなさそう(スパコン上でのちょっとしたプログラムの修正などでは使うかもしれない)。
ディレクトリ構造としては以下の図のようになっているらしい。使うのは多分/home
ディレクトリと/work
ディレクトリだけだと思う。
自分の理解ではログインノードの中に/home
と/work
があり、計算ノードにつながっているのが/work
という理解。LUSTREファイルシステムはよくわかんない。
ディレクトリ名は、ユーザーIDとプロジェクトコードによって分けられている。(そもそもそれ以外は使えないので間違えることはないけど)。ユーザーIDとプロジェクトコードは登録完了時にメールで送られてくる「Oakbridge-CX 利用登録のお知らせ」に記入してある(下図)。
1.2. 環境構築(Environment module)
C/C++またはFortranの場合コードをバイナリファイルにコンパイルする必要がある。またPythonの場合、バージョン2or3の選択が必要になる。それらを設定するためのコマンドがmodule
である。正直細かい話は必要ないと思うが、参考記事を載せておく。
コンパイラ等の選択
gnu コンパイラ, インテル製コンパイラ, python インタープリター...
ライブラリを利用した計算の高速化
離散フーリエ変換, 線形代数・連立1次方程式, …
$ module list
Currently Loaded Modulefiles:
1) impi/2019.9.304 2) intel/2020.4.304
デフォルトだとこんな感じになっていると思う。サンプルコードはintelコンパイラを使っているのでとりあえずそのまま。(スパコン入門ではバージョンを変えているから変えても問題ない。)
module コマンドの引数一覧(module [引数])
引数 | 説明 |
---|---|
avail | 利用可能な環境の一覧を表示 |
list | 現在ロードしている環境一覧を表示 |
load | 指定した環境のロード |
unload | 指定した環境のアンロード |
switch | 環境のロードとアンロードを同時に実行 |
purge | 環境を全てアンロード |
またPythonの場合はライブラリのインストールにpipを使ったり仮想環境を構築したりするが詳細は省略する(スパコン超入門資料の「スパコンでの機械学習実行超入門」に書かれているので参考にしてほしい。)余裕があれば書くかも。
1.3. コード準備
$ ssh 'userID'@obcx.cc.u-tokyo.ac.jp
でログイン。
$ pwd
/home/'userID'
となっていると確認できる。
スパコン超入門ではまずフィボナッチ数列の計算をさせようということでコードの作成をしている。ディレクトリの作成とエディタ(今回は簡単そうだったemacsを使う)でコードを作成していく。ここから手元のパソコンで作成したい人は1.5. sftpコマンドを使ったファイルの送受信を参照してほしい。
$ mkdir fibonacci
$ cd fibonacci
$ emacs fibonacci.c
ちなみに後述するが計算する際にはこのコードを/work/'groupname'/'userID'
で実行させるため、はじめから
$ cd /work/'groupname'/'userID'
$ mkdir fibonacci
$ cd fibonacci
$ emacs fibonacci.c
でも良さそう。(スパコン超入門では/home
は容量に限りがあるから基本/work
下で管理した方がいいと書いてあるけど、調べてないからわからない)
作成したコードが以下(fibonacci.c)。emacsの操作方法についてはリンクを参照した。
fibonacci.c
#include <stdio.h>
int main(void){
int i;
long a, b, tmp;
a = 1;
b = 1;
printf("%ld\n", a);
for (i=2; i<=92; i++){
tmp = b;
b = a + b;
a = tmp;
printf("%ld\n", a);
}
}
スパコンではこれに加えてジョブスクリプトと呼ばれるファイルが必要。これは計算ノードに計算してもらうための指示書のようなものである。スパコンはジョブという形でコードを計算ノードに投げてそれを実行してもらうことで、計算をおこなっている。後でも説明するがログインノードでコードを実行することはないので注意
ジョブスクリプトは.sh
形式で以下のように書く。
#!/bin/bash
#PJM -L rscgrp=lecture
#PJM -L node=1
#PJM -L elapse=0:01:00
#PJM -g gt00
#PJM -N fibonacci
#PJM -o stdout.txt
#PJM -j
model purge
module load intel/2020.4.304
./fibonacci.out
以下で説明していく
#!/bin/bash ← bashの宣言
#PJM -L rscgrp=lecture ← 自分の「利用可能なリソースキュー」、お試しなら「lecuture」だと思う。
#PJM -L node=1 ← 使用するノード数(契約で決められた上限は上回れないはず)
#PJM -L elapse=0:01:00 ← 実行時間上限(契約で決められた上限は上回れないはず)
#PJM -g gt00 ← プロジェクトコード
#PJM -N fibonacci ← ジョブの名前、実行中に確認した際表示される名前?
#PJM -o stdout.txt ← 標準出力先のファイル名
#PJM -j ← エラー出力を標準出力にマージ(他のオプションの設定は不明...)
これらについてはOakbridgeに特有な書き方である可能性があるので他のスパコン使う時は要確認。計算させる際のさまざまな設定を指定している。
module purge
module load intel/2020.4.304
./fibonacci.out
module
コマンドでコンパイル、実行環境を整える。
./fibonacci.out
は実行するコンパイルしたファイル名
1.4. コンパイル
ここではCのコンパイルについて書く。コンパイルは/home
ディレクトリでも/work
ディレクトリでもどちらでも良い。
$ icc fibonacci.c -o fibonacci.out
インテルコンパイラなのでicc
、-o fibonacci.out
でコンパイル後の実行ファイルの名前を設定。
ジョブスクリプトに記入する実行ファイル名とここの実行ファイル名は同じ名前に
1.5. ジョブ実行
(コンパイルした後)ログインノード上で直接プログラム実行することはしない!
ー 負荷がかかると、他のユーザーの同時作業の妨げとなる
/home
ディレクトリでコンパイルした場合はフォルダごと/work
ディレクトリにコピーする。
[ /home/userID ] $ cp –r fibonacci /work/group/userID/
$ cd /work/group/userID/fibonacci
fibonacciフォルダをコピー。実際は実行ファイルとジョブスクリプトだけで良さそうだけど。
$ pjsub fibonacci.sh
pjsub
でジョブを計算ノードに投げることができる。
ジョブの管理コマンド
コマンド | 説明 | 例 |
---|---|---|
pjsub | ジョブの投入 | $ pjsub “script.sh” |
pjdel | ジョブの削除 | $ pjdel “job ID” |
pjstat | ジョブの確認 | $ pjstat |
pjstatのオプションコマンド
オプション | 説明 |
---|---|
-H | 終了したジョブの確認 |
--rsc -b | 各リソースグループの混雑具合を確認可能 |
--rsc -x | 各リソースグループで要求可能なリソース量を出力 |
--nodeuse | OBCX全体での使用状況確認 |
1.6. sftpを使ったファイルの送受信
スパコン超入門のサンプルコードにはMPIを使ったコードもある。(pi_mpi.c)
pi_mpi.c.c
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
int main(int argc, char* argv[]){
int ndiv = 5600000000;
int ierr, myrank, nprocs;
int ndiv_local, i;
double x, width, sum, total_sum;
double t1, t2;
width = 1.0 / (double)ndiv;
ierr = MPI_Init(&argc, &argv);
ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
ierr = MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
t1 = MPI_Wtime();
sum = 0.0;
ndiv_local = ndiv / nprocs;
for(i = myrank*ndiv_local;i<(myrank+1)*ndiv_local;i++){
x = (i + 0.5)*width;
sum += width*4.0/(1.0+x*x);
}
MPI_Reduce(&sum, &total_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
t2 = MPI_Wtime();
if(myrank==0){
printf("PI(MPI) = %.18f\n", total_sum);
printf("Number of cores utilized = %d\n", nprocs);
printf("Exwcution time = %.8f (sec.)\n", t2 - t1);
}
ierr = MPI_Finalize();
return 0;
}
この時エディタで作成するのは(慣れていないのもあるが)やや大変。なので手元のパソコンのVScodeでコードを書いてからそれをスパコンのディレクトリに送信するという形で行う。
使ったコマンドはsftp
でSSH接続している人はこれでいける(他の方法でアクセスしている人はわかんないです、、、)
スパコンにログインしている人は、一旦exit
でログアウト。
手元のパソコンで
$ sftp userID@obcx.cc.u-tokyo.ac.jp
と入力。SSH接続同様パスワードを求められるので入力すると
Connected to obcx.cc.u-tokyo.ac.jp.
sftp>
となり、ファイルのやりとりが可能な状態でログインできる。
1. 手元のパソコンからスパコンにファイルを送信
ログインした状態の現在地は/home/userID
ディレクトリなのでそこにそのまま入れても良いし、/work
ディレクトリに移動してからでも良い
(sftp> cd /work/group/userID)
sftp> put -r desktop/スパコン/calc_pi_mpi
put
は送信するコマンドでオプションは他のファイル操作のコマンドと多分同じ
#フォルダを送信するとき
sftp> put -r フォルダのpath
#ファイルを送信するとき
sftp> put ファイルのpath
2. スパコンからファイルを手元のパソコンに受信
基本計算し終わったファイル(フォルダ)を手に入れたいと思うので移動してからget
コマンドで受信する。
sftp> cd /work/group/userID
sftp> get -r fibonacci
#フォルダを送信するとき
sftp> get -r フォルダのpath
#ファイルを送信するとき
sftp> get ファイルのpath
これで実行してそのデータを手に入れるまでのことはできようになりました。
さらなる理解は講習会の資料などで学ぶと良いと思います。
2. 補足
ここからはAdditionalで自分が試したことを書いておく。研究で扱うコードはサンプルとは違うところがいくつかある。
- C++で書かれている
- ヘッダーファイルの存在
- 入力データ、数値が存在する
- OpenMPを使っている
この4つがあるので注意が必要。
まずコンパイラはgccを使うので
$ module purge
$ module load gcc/7.5.0
$ module list
Currently Loaded Modulefiles:
1) impi/2019.5.281 2) gcc/7.5.0
にしておく。
編集中