メインコンテンツに移動

AlmaLinux/RMS_function

SLURM機能確認

ジョブのメモリーサイズを確認

ジョブ実行後に

# sl -l
19        sugimoto B   NewSLURM  COMPLETED   00:04:06 2025-03-29T11:32:47 2025-03-29T11:36:53  sun2
19.batch  batch  COMPLETED   00:04:06 2025-03-29T11:32:47 2025-03-29T11:36:53  1.46G 0 sun2

いちおう出力する気はあるようである.

宣言を超えるメモリー使用量

メモリーを宣言以上に使用しても,エラーしない.デフォルトではslurm.confで DefMemPerCPU=4000  つまり4GBまで許容.ううん?理由は不明だ.

DefMemPerCPU=4000 は,スレッド1つ当たり4GBである. 8CPUで32GBで,「そんな計算機,ないっす」と言われる. そこでジョブ文に #SBATCH --mem=31000 とか書くと, 動く.

あ?メモリーサイズが超えているとしばらく時間がかかるが, CANCELされるぞ.

slurmstepd: error: StepId=70.batch exceeded memory limit (12826103808 > 83886080), being killed
slurmstepd: error: Exceeded job memory limit
slurmstepd: error: *** JOB 70 ON sun2 CANCELLED AT 2025-03-29T14:19:58 ***
slurmstepd: error: StepId=70.batch exceeded memory limit (12826103808 > 83886080), being killed
slurmstepd: error: Exceeded job memory limit
slurmstepd: error: --task-epilog failed status=9

この例では,JOB文で

#SBATCH --cpus-per-task=8
#SBATCH --mem-per-cpu=10

と書いたので, 10 MB x 8 = 83886080 バイト使用すると申請したのだが,実行中に 12826103808 バイト使用しているのがバレて, 銃殺刑になったのだ.

OMP使うとどうなる?

まずOMPを使うプログラムを作成. ターミナルで実行すると

 PID     USER        PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
143467 sugimoto  20   0   29.6g  24.0g   3456 R 795.7   78.1        9:40.89 omp

こんな感じだから,できてる.ではジョブを打ってみる.あり?1CPUだなこりゃ

PID USER      PR  NI    VIRT                  RES    SHR S  %CPU  %MEM     TIME+ COMMAND
143763  sugimoto  20   0   12.0g  795808   3328 D  49.7   2.5   0:25.90 omp

あれえ?ジョブ文に

export OMP_NUM_THREADS=4

とか自分で書いたら動かない. あれ?/usr/local/etc/cgroup.conf でConstrainRAMSpace=no にしたら正常だ.なんだこれ. なんでRAMspaceとコア数が関連するんだ?バグってんじゃん.まあええか.

PID        USER       PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
148970 sugimoto  20   0   12.0g  11.9g   3456 R  598.3       38.7   0:50.65 omp

まあ動いたな!

MPI使うと死ぬのか

MPIを使ってみる.プログラムはこんなの:

//mpic++ bmpi.cpp -fopenmp -o bmpi -lboost_mpi
#include <omp.h>
#include <boost/asio.hpp>
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/LU>
#include <random>
namespace bmpi = boost::mpi;
int main(int argc, char** argv)
{
bmpi::environment env(argc, argv);
bmpi::communicator world;
std::cout << "Rank : " << world.rank() << "/" << world.size() << " on " << boost::asio::ip::host_name() << std::endl;
unsigned int N=14000,Nr=1;
Eigen::MatrixXd A;
Eigen::VectorXd b;
A.resize(N,N);
b.resize(N);
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
std::uniform_real_distribution<> UNI(-1.,1.);
for(size_t repeat=0;repeat<Nr;repeat++) {
#pragma omp parallel for
for(size_t i=0;i<N;i++) for(size_t j=0;j<N;j++) A(i,j)=UNI(engine);
#pragma omp parallel for
for(size_t i=0;i<N;i++) b(i)=UNI(engine);
auto X=b.transpose()*A*b;
std::cout << "Pass[" << repeat << "]X= " << X << std::endl;
}
return 0;
}

で実行してみると

 PID        USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
150752 sugimoto  20   0 1745540   1.5g   9344 R 199.3   4.8   0:13.72 bmpi
150750 sugimoto  20   0 1745540   1.5g   9344 R 199.0   4.8   0:13.69 bmpi
150753 sugimoto  20   0 1745540   1.5g   9344 R 199.0   4.8   0:13.69 bmpi
150751 sugimoto  20   0 1745540   1.5g   9472 R 198.3   4.8   0:13.64 bmpi

なるほど. 4Processで2Threadづつ, ちゃんと使っておるな.

$ sq
JOBID PART NAME USER ST TIME TIME_LEFT NODE CPU NODELIST(REASON)
76 B MPIJOB sugimoto R 0:04 3:04:56 1 8 sun2

GANGスケジューリング

GANGスケジューリングとは,優先度の高いジョブが低いジョブの上に乗っかって走るやつである.色々試した挙句, slurm.confが

PreemptType=preempt/partition_prio
PreemptMode=SUSPEND,GANG
...
PartitionName=B Nodes=ALL MaxTime=10-12:0:0 DefaultTime=0-03:05 OverSubscribe=FORCE:2 PriorityTier=20 Default=YES
PartitionName=E Nodes=ALL MaxTime=30-12:0:0 DefaultTime=0-03:05 OverSubscribe=FORCE:2 PriorityTier=10

こんな感じにして,コンピュータそのものを再起動すると,動くみたいである. 同じクラスのジョブなら

$ sq
JOBID PART NAME USER ST TIME TIME_LEFT NODE CPU NODELIST(REASON)
104 E OTHERJOB sugimoto R 0:20 3:04:40 1 8 sun2
103 E MPIJOB sugimoto S 0:54 3:04:06 1 8 sun2

仲良く,お互いにサスペンドしながら進める. 高位ジョブが入ると, メモリー不足ならばなら

$ sq
JOBID PART NAME USER ST TIME TIME_LEFT NODE CPU NODELIST(REASON)
105 B OMPJOB sugimoto PD 0:00 3:05:00 1 8 (Resources)
104 E OTHERJOB sugimoto R 0:44 3:04:16 1 8 sun2
103 E MPIJOB sugimoto S 1:24 3:03:36 1 8 sun2

いくら身分が高いジョブでも,殺しは許可していないので,待ってしまう.メモリーが足りると

$ sq
JOBID PART NAME USER ST TIME TIME_LEFT NODE CPU NODELIST(REASON)
105 B OMPJOB sugimoto R 0:07 3:04:53 1 8 sun2
103 E MPIJOB sugimoto S 2:18 3:02:42 1 8 sun2

高位ジョブが走り始める.身分の高いジョブは,下の者のケアは一切しない.自分が終了するまで,身分の低いジョブを待たせておく.

ま,世の中,そんなものですよね.