1. 概要¶
VeloC (Very Low Overhead Checkpointing System) は、大型計算向けマルチレベルチェックポイント/リスタートツールです 1。 プログラム内に VeloC API を適切に実装することにより、高速なチェックポイント・リスタートを行うことが可能になります。 ここではスーパーコンピュータ「富岳」で、VeloCを利用したC/C++およびFortranプログラムのコンパイル・リンク方法を示します。
VeloCに関する詳細な情報は、https://veloc.readthedocs.io/ 等を参考にしてください。
2. 実装例¶
2.1. C/C++での実装¶
VeloCのテストプログラムを参考にVeloCの導入で重要な部分について解説します。 VeloCのテストプログラムはGitHub上に公開されています( https://github.com/ECP-VeloC/VELOC/tree/main/test )。 ここでは、"heatdis_mem.c" を参考にVeloCの実装方法を説明します。 まず、VeloC APIをプログラムから呼び足すため、VeloCのヘッダーファイルをインクルードします。
6 #include "include/veloc.h"
次に、VeloCの初期化として "VELOC_Init" を導入します。
91 if (VELOC_Init(MPI_COMM_WORLD, argv[2]) != VELOC_SUCCESS) {
92 printf("Error initializing VELOC! Aborting...\n");
93 exit(2);
94 }
ここで、"VELOC_Init" の "MPI_COMM_WORLD" はMPIコミュニケータ、argv[2]はVeloCの設定ファイル名で、"heatdis_mem.c"では標準入力より与えています。 この設定ファイルについての詳細は、後述の "VeloCの設定" を参照してください。
VeloCでチェックする変数や配列の登録は、"VELOC_Mem_protect" より次の様に行います。
110 VELOC_Mem_protect(0, &i, 1, sizeof(int));
111 VELOC_Mem_protect(1, h, M * nbLines, sizeof(double));
112 VELOC_Mem_protect(2, g, M * nbLines, sizeof(double));
VELOC_Mem_protectの第1引数はメモリ領域を識別するためのID、第2引数は変数や配列のポインタ、第3引数は要素数、第4引数は要素のサイズです。
VeloCにおけるリスタートは次の様に実装されます。
115 int v = VELOC_Restart_test("heatdis", 0);
116 if (v > 0) {
117 printf("Previous checkpoint found at iteration %d, initiating restart...\n", v);
118 // v can be any version, independent of what VELOC_Restart_test is returning
119 assert(VELOC_Restart("heatdis", v) == VELOC_SUCCESS);
120 } else
まず、"VELOC_Restart_test" よりリスタートの可否を判定しています。 ここで第1引数の "heatdis" はチェックポイントのラベルです。第2引数はリスタートに用いるチェックポイントのバージョンを指定します。 0は最新バージョンの指定に対応しています。この関数の戻り値はチェックポイントのバージョンです。 次に、登録していた変数や配列を元に戻すために "VELOC_Restart" を呼び出しています。 ここで、"heatdis" はチェックポイントのラベル、"v" はチェックポイントのバージョンです。
チェックポイントを生成するために、適当なタイミングで "VELOC_Checkpoint" を呼び出しています。
122 while(i < ITER_TIMES) {
123 localerror = doWork(nbProcs, rank, M, nbLines, g, h);
124 if (((i % ITER_OUT) == 0) && (rank == 0))
125 printf("Step : %d, error = %f\n", i, globalerror);
126 if ((i % REDUCE) == 0)
127 MPI_Allreduce(&localerror, &globalerror, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
128 if (globalerror < PRECISION)
129 break;
130 i++;
131 if (i % CKPT_FREQ == 0)
132 assert(VELOC_Checkpoint("heatdis", i) == VELOC_SUCCESS);
133 }
ここで、"VELOC_Checkpoint" の "heatdis" はチェックポイントのラベル、iはチェックポイントのバージョンです。
最後に、"VELOC_Finalize" を呼び出してVeloCの終了処理を行なっています。
139 VELOC_Finalize(1); // wait for checkpoints to finish
2.2. Fortranでの実装¶
サンプルソースコードが、https://github.com/ECP-VeloC/VELOC/blob/fortran/test/fheatdis.f90 で公開されています。 このサンプルソースコードに基づいて、VeloCの実装の重要な点について示します。
VeloCに関する変数・関数を利用するため、VeloCモジュールをロードします。
5 use VELOC
VeloCの初期化関数を呼びます。comm はMPIコミュニケータ、fheatdis.cfg は設定ファイル名です。 設定ファイルの内容については、実行方法で説明します。
29 call VELOC_Init(comm, 'fheatdis.cfg', err) !see with argc argv
VELOC_Mem_protect関数を用いて、チェックする変数・配列を登録します。 配列はそのまま登録できますが、変数はポインタにしておく必要があります。
46 ptriter => i
47 call VELOC_Mem_protect(0, ptriter, err)
48 call VELOC_Mem_protect(1, h, err)
49 call VELOC_Mem_protect(2, g, err)
VELOC_Restart_test関数を用いて、restartか否かを判定します。 restartの場合、VELOC_Recover_mem関数を用いて登録しておいた変数・配列を元の状態に復帰させます。
56 call VELOC_Restart_test("fheatdis", 0, restart_iter)
57 print '("test restart", I5)', restart_iter
58 if (restart_iter > 0) then
59 print '("Previous checkpoint found at iteration ",I5," initiating restart...")', restart_iter
60 call VELOC_Restart_begin("fheatdis", restart_iter, err)
61 call VELOC_Recover_mem(err)
62 call VELOC_Restart_end(restart_success, err)
63 else
64 i = 1
65 endif
メインループの中で、適当なタイミングでVELOC_Checkpoint関数を呼び、チェックポイントを生成します。
80 if (mod(i, CKPT_FREQ) == 0) then
81 call VELOC_Checkpoint_wait(err)
82 call VELOC_Checkpoint_begin("fheatdis", i, err)
83 call VELOC_Checkpoint_mem(err)
84
85 call VELOC_Checkpoint_end(ckpt_success, err)
86
87 if (err /= VELOC_SCES ) then
88 print '("Error during checkpoint: ", I5)', err
89 exit
90 endif
91 endif
VELOC_Finalize関数を用いて、終了処理を行います。
102 call VELOC_Finalize(0, err)
3. コンパイル・リンク¶
コンパイル・リンク時に指定が必要なオプションを示します。
コンパイル時に必要となるオプション
言語
オプション
C/C++
-I/vol0004/apps/oss/veloc
Fortran
-I/vol0004/apps/oss/veloc/include
リンク時に必要となるオプション
言語
オプション
C/C++
-L/vol0004/apps/oss/veloc/lib64 -lveloc-client -lveloc-modules -ler -laxl -lkvtree -lshuffile -lredset -lrankstr
Fortran
-L/vol0004/apps/oss/veloc/lib64 -lveloc-client -lveloc-modules -ler -laxl -lkvtree -lshuffile -lredset -lrankstr -lvelocf
コンパイル例を次に示します。
C/C++コンパイル例
[_LNlogin]$ mpifccpx -o heatdis_mem -Kfast,parallel,optmsg=2 heatdis_mem.c -I/vol0004/apps/oss/veloc -L/vol0004/apps/oss/veloc/lib64 -lveloc-client -lveloc-modules -ler -laxl -lkvtree -lshuffile -lredset -lrankstr
Fortranコンパイル例
[_LNlogin]$ mpifrtpx -o fheatdis -Kfast,parallel,optmsg=2 fheatdis.f90 -I/vol0004/apps/oss/veloc/include -L/vol0004/apps/oss/veloc/lib64 -lveloc-client -lveloc-modules -ler -laxl -lkvtree -lshuffile -lredset -lrankstr -lvelocf
4. 実行方法¶
ここではVeloCを利用したテストプログラムによる富岳での実行方法を示します。
[前準備 (C/C++, Fortran共通)]
VeloC用の設定ファイルを記述します。C/C++ではheatdis.cfgを、Fortranでは fheatdis.cfg を指定していますが、内容は同じです。 また、ファイル名は自由に設定可能です。
scratch = tmp/scratch
persistent = tmp/persistent
meta = tmp/meta
max_versions = 2
scratch_versions = 1
mode = async
chksum = true
これらの設定は次の通りです:
scratch = <path> (一時的なチェックポイントデータのパス)
persistent = <path> (永続的なチェックポイントデータのパス)
meta = <path> (チェックポイントデータのチェックサム情報を保存するパス)
max_versions = <int> (persistentに残す過去のチェックポイントの数, default: 0 – 全て保存)
scratch_versions = <int> (scratchに残す過去のチェックポイントの数, default: 0 – 全て保存)
mode = async (VeloCの動作モード)
chksum = <boolean> (チェックポイントデータの確認の可否, default: false)
設定ファイルに設定の無いものについてはデフォルトの値が採用されます。この他の設定については、公式HPのUser Guideを参照してください。
ジョブを実行する前に、データを書き込むディレクトリを生成しておきます。
[_LNlogin]$ rm -rf tmp/scratch tmp/persistent tmp/meta [_LNlogin]$ mkdir -p tmp/scratch tmp/persistent tmp/meta
ジョブは以下のような形で記述します。
[C/C++実行例]
#! /bin/bash -x
#PJM -L node=1
#PJM -L elapse=00:10:00
#PJM -x PJM_LLIO_GFSCACHE=/vol0004
#PJM -g groupname
#PJM -s
#
export PARALLEL=1
export OMP_NUM_THREADS=1
BINDIR=/vol0004/apps/oss/veloc/bin
LIBDIR=/vol0004/apps/oss/veloc/lib64
export LD_LIBRARY_PATH=$LIBDIR:$LD_LIBRARY_PATH
export VELOC_BIN=$BINDIR
mpiexec ./heatdis_mem 1 heatdis.cfg
[Fortran実行例]
#! /bin/bash -x
#PJM -L node=4
#PJM -L elapse=00:10:00
#PJM -x PJM_LLIO_GFSCACHE=/vol0004
#PJM -g groupname
#PJM -s
#
export PARALLEL=1
export OMP_NUM_THREADS=1
BINDIR=/vol0004/apps/oss/veloc/bin
LIBDIR=/vol0004/apps/oss/veloc/lib64
export LD_LIBRARY_PATH=$LIBDIR:$LD_LIBRARY_PATH
export VELOC_BIN=$BINDIR
mpiexec ./fheatdis
注意
Checkpoint/restart用のデータを書き込むディレクトリが生成されていないと、正常にデータが書き出されないことがあります。
Footnote
- 1
Nicolae, B., Moody, A., Gonsiorowski, E., Mohror, K. and Cappello, F. 2019. VeloC: Towards High Performance Adaptive Asynchronous Checkpointing at Large Scale. IPDPS 19: The 2019 IEEE International Parallel and Distributed Processing Symposium, pp. 911-920, Rio de Janeiro, Brazil, (2019).