PBSProを普通に使う場合にはcpu coreの空き数、メモリ搭載量とかでジョブの配送先が決まる。

ただ最近ではGPUの空き枚数でジョブの配送が決まってほしい場合もあり、基本のままでは不十分になりつつある。
例えば64coreなマシンで4枚GPUを搭載しているノードにジョブを入れたい場合、
64coreすべてを使用するような形でジョブを投げる必要がある
もし16coreで投げると、そのマシンはまだまだジョブを受け付けられる状態にあり、その他のジョブがGPUを使うようなら
4枚のGPUはその計算リソースを供給され遅くなるか、最悪ジョブが停止されてしまう。

2020y02m16d_200727527.png

ここではGPUの枚数で計算ノードが決定され(resource定義)、かつそのGPUがそのジョブにしか使われないようにしてみる(hook定義)。
*openpbs-20.0.1を使っています

初期

一応「pbsnodes」コマンドには「ngpus」という欄がある. だた何もしなければ「0」のままで、

[saber@openpbs ~]$ pbsnodes -aS
vnode           state           OS       hardware host            queue        mem     ncpus   nmics   ngpus  comment
--------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- ---------
pbs-node1       free            --       --       pbs-node1       --              8gb       4       0       0 --
[saber@openpbs ~]$
 
[saber@openpbs ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=0 -I
qsub: Unknown resource: ngpus
[saber@openpbs ~]$

かつそれを使うことも出来ない. 表記はされているが使えない状態で、まずはこれを調整します

resource

既定ではGPUを定義する項目がないので、その定義項目をジョブ管理ノードに追加します。

[root@openpbs ~]# qmgr
Qmgr: create resource ngpus type=long, flag=nh   <--「create resource ngpus type=long, flag=nh」を実行
Qmgr: list resource                              <--「list resource」で確認
#
# Create resources and set their properties.
#
Resource ngpus
    type = long
    flag = hn
 
Qmgr: quit
[root@openpbs ~]#

その後、pds機能を一旦停止させ、新たなリソース名として「ngpus(数値型)」を追加
「sched_config」を修正してpbsを再起動

[root@openpbs ~]# systemctl stop pbs
[root@openpbs ~]# vi /var/lib/pbs/sched_priv/sched_config
- resources: "ncpus, mem, arch, host, vnode, aoe, eoe"
+ resources: "ncpus, mem, arch, host, vnode, aoe, eoe, ngpus"     <--- 242行目あたり、「ngpus」を追加
 
[root@openpbs ~]# systemctl start pbs

この後に、計算ノードにGPUを定義します. ここでは 計算ノードpbs-node1 にGPU1枚定義してます

[root@openpbs ~]# qmgr -c "set node pbs-node1 resources_available.ngpus=1"
 
(確認)
[root@openpbs ~]# qmgr -c "print node pbs-node1"
#
# Create nodes and set their properties.
#
#
# Create and define node pbs-node1
#
create node pbs-node1 Mom=pbs-node1.sybyl.local
set node pbs-node1 state = free
set node pbs-node1 resources_available.arch = linux
set node pbs-node1 resources_available.host = pbs-node1
set node pbs-node1 resources_available.mem = 8146060kb
set node pbs-node1 resources_available.ncpus = 4
set node pbs-node1 resources_available.ngpus = 1       <--- ここが追加されます.
set node pbs-node1 resources_available.vnode = pbs-node1
set node pbs-node1 resv_enable = True
[root@openpbs ~]#

ここでqsubのインターラクティヴモードで GPU を1つ使うようにしてみる

[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 7.openpbs to start
qsub: job 7.openpbs ready
 
[illya@s ~]$

nvidia-smiコマンドでgpuリソースを確認すると、、、

[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
GPU 1: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)
[illya@s ~]$

と2つのGPUが列挙されてしまう。1つだけ使いたいのに、、っでそれを解消するのがhook

hook

参照先: https://www.altair.com/resource/altair-pbs-professional-support-on-nvidia-dgx-systems

まずは下記を実行して「pbs_cgroups.json」を得ます。

[root@openpbs ~]# qmgr -c "export hook pbs_cgroups application/x-config default" > pbs_cgroups.json

取得した「pbs_cgroups.json」の中身に修正を加えます。
https://help.altair.com/2022.1.0/PBS%20Professional/PBS2022.1.pdf の AG-346(538ページ) 「6.5.5.4 Isolating NVIDIA GPUs」を参照

{
    "cgroup_prefix"         : "pbs_jobs",
    "exclude_hosts"         : [],
    "exclude_vntypes"       : ["no_cgroups"],
    "run_only_on_hosts"     : [],
    "periodic_resc_update"  : true,
    "vnode_per_numa_node"   : false,
    "online_offlined_nodes" : true,
    "use_hyperthreads"      : false,
    "ncpus_are_cores"       : false,
    "discover_gpus"         : true,
    "manage_rlimit_as"      : true,
    "cgroup" : {
        "cpuacct" : {
            "enabled"            : true,
            "exclude_hosts"      : [],
            "exclude_vntypes"    : []
        },
        "cpuset" : {
            "enabled"            : true,
            "exclude_cpus"       : [],
            "exclude_hosts"      : [],
            "exclude_vntypes"    : [],
            "mem_fences"         : true,
            "mem_hardwall"       : false,
            "memory_spread_page" : false
        },
        "devices" : {
            "enabled"            : true,     <--ここを「false」から「true」に変更
            "exclude_hosts"      : [],
            "exclude_vntypes"    : [],
            "allow"              : [        #  allow部分を下記に全変換(「"c *:* rwm"」はいれないように)
                "b *:* m",
                "b 7:* rwm",
                "c *:* m",
                "c 195:* m",                     # 195は「ls -l /dev」で表示されるデバイス番号. 195は /dev/nvidiaX, /dev/nvidiactl を持ちます
                "c 136:* rwm",                   # 136は「ls -l /dev/pts」にあるデバイス番号
                ["infiniband/rdma_cm","rwm"],    # infinibandを持たないなら削除
                ["fuse","rwm"],
                ["net/tun","rwm"],
                ["tty","rwm"],
                ["ptmx","rwm"],
                ["console","rwm"],
                ["null","rwm"],
                ["zero","rwm"],
                ["full","rwm"],
                ["random","rwm"],
                ["urandom","rwm"],
                ["cpu/0/cpuid","rwm","*"],
                ["nvidia-modeset", "rwm"],       # /dev/nvidia-modeset が存在しないなら外してもいいのかも...
                ["nvidia-uvm", "rwm"],
                ["nvidia-uvm-tools", "rwm"],
                ["nvidiactl", "rwm"]
            ]
        },
        "hugetlb" : {
            "enabled"            : false,
            "exclude_hosts"      : [],
            "exclude_vntypes"    : [],
            "default"            : "0MB",
            "reserve_percent"    : 0,
            "reserve_amount"     : "0MB"
        },
        "memory" : {
            "enabled"            : true,     # メモリー確保とか面倒ならfalseへ
            "exclude_hosts"      : [],
            "exclude_vntypes"    : [],
            "soft_limit"         : false,
            "default"            : "256MB",
            "reserve_percent"    : 0,
            "reserve_amount"     : "64MB"
        },
        "memsw" : {
            "enabled"            : true,     # メモリー確保とか面倒ならfalseへ
            "exclude_hosts"      : [],
            "exclude_vntypes"    : [],
            "default"            : "256MB",
            "reserve_percent"    : 0,
            "reserve_amount"     : "64MB"
        }
    }
}

修正した「pbs_cgroups.json」ファイルをシステムに戻して反映させる

[root@openpbs ~]# qmgr -c "import hook pbs_cgroups application/x-config default pbs_cgroups.json"
hook 'pbs_cgroups' contents overwritten
[root@openpbs ~]#

その後に「pbs_cgroup」を有効にする

(現状の確認)
[root@pbspro ~]# qmgr
Qmgr: list hook
Hook pbs_cgroups
    type = site
    enabled = false
    event = execjob_begin,execjob_epilogue,execjob_end,execjob_launch,
        execjob_attach,
        execjob_resize,
        exechost_periodic,
        exechost_startup
    user = pbsadmin
    alarm = 90
    freq = 120
    order = 100
    debug = false
    fail_action = offline_vnodes
 
(hookを有効にする)
Qmgr: set hook pbs_cgroups enabled = true
 
(有効になったかの確認)
Qmgr: list hook
Hook pbs_cgroups
    type = site
    enabled = true   <-- trueに代わる
    event = execjob_begin,execjob_epilogue,execjob_end,execjob_launch,
        execjob_attach,
        execjob_resize,
        exechost_periodic,
        exechost_startup
    user = pbsadmin
    alarm = 90
    freq = 120
    order = 100
    debug = false
    fail_action = offline_vnodes
 
Qmgr:
[root@pbspro ~]#

あとはpbs_serverと対象の計算ノードのpbsサービスを再起動します

[root@openpbs ~]# systemctl restart pbs
 
 
(gpuを持つ計算ノード)
[root@pbs-node1 ~]# systemctl restart pbs

計算ノードが cgroups v2 な場合はGPU制御ができないので cgroups v1 に変更します

rockylinux9は基本が cgroups v2 で稼働しています. 目下 OpenPBS は v1 としてリソース管理をしているので、そのままではGPUリソース制御は働きません。
参照 https://community.openpbs.org/t/openpbs-cgroups-v2-support/2667

この場合は cgroups v2 を cgroups v1 に変更して対応します.

cgroups v1ならkubernetesに影響あるとか...微妙なのですが..

目下のcgroupsのバージョン確認は

stat -fc %T /sys/fs/cgroup/

を実行して「cgroup2fs」が出れば cgroups v2. 「tmpfs」が出れば cgroups v1 となります

もしv2からv1へ変更したければ、下記のようにして修正します

(v2からv1へ)
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
reboot
 
(元に戻す)
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=1"
reboot

reboot後に「stat -fc %T /sys/fs/cgroup/」の出力が「fmpfs」になっている事を確認します.
selinuxはenforcingのままでもいいみたい.
これで rockylinux9 もGPUリソース制御が達成できました.

テスト

同じようにqsubのインターラクティヴモードでテスト
この際、「-l nodes=1:ppn=1:ngpus=2」な書式はダメみたいで「-l select=1:ncpus=1:ngpus=2」と「select」と「ncpus」でないと無理みたい

[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 22.openpbs to start
qsub: job 22.openpbs ready
 
[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@s ~]$ exit
 
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=2 -I
qsub: waiting for job 23.openpbs to start
qsub: job 23.openpbs ready
 
[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
GPU 1: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)
 
[illya@s ~]$ exit
 
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1 -I
qsub: waiting for job 24.openpbs to start
qsub: job 24.openpbs ready
 
[illya@s ~]$ nvidia-smi -L
No devices found.
 
[illya@s ~]$

1個指定、2個指定も問題なく使えたみたい。また何も指定しないとデバイスすら見えないみたい

複数のclientからGPUを一つづつ貰い受けた時のGPU IDはそれぞれ0となります(それぞれ別々のGPUです)
なので、8GPUマシンで4GPU毎に使用してもGPUカードは被りません

[illya@client ~]$ qsub -l select=1:ncpus=1:ngpus=1:mem=1gb -I                [illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 11.openpbs to start                                    qsub: waiting for job 10.openpbs to start
qsub: job 11.openpbs ready                                                   qsub: job 10.openpbs ready
                                                                             
[illya@s ~]$ nvidia-smi -L                                                   [illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)       GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@s ~]$                                                                 [illya@s ~]$

留意
ngpus=2でジョブリソースを確保しても、ncpusが余っていればジョブの投入は可能です. 単にGPUリソースにアクセスできないだけ

一応これでGPUリソースの排他的制限は出来たけど、今度は逆にCPUリソースの排他的制限は可能なのかと疑問がでる...未調査です


qsubで1coreリソースを確保して、でも展開されるスクリプトには1core以上を使うアプリが仕込まれると厄介極まりない...
1計算機ノード1coreな世界なら心配要らない話だけど、昨今のハイブリッドMPIなプログラムだと考慮が必要なのかも

つーる

「qload」と名付けてます

yum install perl-JSON
 
(ubuntu)
apt install libjson-perl
鴻鴻
-
!
 
 
 
 
 
 
 
-
|
!
 
-
|
|
|
|
!
 
-
|
!
 
 
-
|
|
|
|
|
|
|
|
!
-
|
!
 
-
|
-
|
!
!
 
-
!
 
-
|
|
-
-
|
|
|
-
|
|
|
!
!
!
-
|
|
|
!
-
|
|
|
|
|
!
-
|
|
-
-
|
-
|
!
!
|
!
#!/usr/bin/perl
use JSON;
use strict;
 
my %queue = (
        "cpu"=>["em01","em02"],
        "gpu"=>["g06","g07","g08","g09","g10","g11","g12","a01","a02","b01","b02","b03","b04","b05","t01"],
         );
my @q0 = ("cpu","gpu");
#-------------------------------------------------------------------#
# qstat
my (%tot,%que,%run);
open(OUT, "qstat -Q 2>&1 | tail -n +3 |");
while(<OUT>){
   my @line = split(/\s+/,$_);
   $tot{$line[0]}=$line[2];
   $que{$line[0]}=$line[5];
   $run{$line[0]}=$line[6];
}
close(OUT);
#-------------------------------------------------------------------#
# pbsnode
my (%state,%total,%runing,%subpend,%mem,%ncpus,%nmics,%ngpus);
my $pbsnodes=`pbsnodes -aSj -F json`;
my $json=decode_json($pbsnodes);
while (my ($node) =  each( %{ $json->{'nodes'} }) ){
     $state{$node}=$json->{'nodes'}->{$node}->{'State'};
     $total{$node}=$json->{'nodes'}->{$node}->{'Total Jobs'};
     $runing{$node}=$json->{'nodes'}->{$node}->{'Running Jobs'};
     $subpend{$node}=$json->{'nodes'}->{$node}->{'Suspended Jobs'};
     $mem{$node}=$json->{'nodes'}->{$node}->{'mem f/t'};
     $ncpus{$node}=$json->{'nodes'}->{$node}->{'ncpus f/t'};
     $nmics{$node}=$json->{'nodes'}->{$node}->{'nmics f/t'};
     $ngpus{$node}=$json->{'nodes'}->{$node}->{'ngpus f/t'};
}
#-------------------------------------------------------------------#
# pbsnode -l
my %down;
open(OUT, "pbsnodes -l  |");
while(<OUT>){
    chomp;
    if ( $_ =~ /^(\S+)\s+(.*),(.*)$/ ){
        $down{$1} = $2;
    }
}
close(OUT);
#-------------------------------------------------------------------#
printf("%5s%4s%5s%6s%5s%16s%13s\n","Queue","Run", "wait", "Host","CPU","usage","GPU");
 
for(my $i = 0; $i <= $#q0 ; $i++ ){
  my $q = $q0[$i];
  my $n; my $job; my $np;
  foreach $n ( 0 .. $#{ $queue{$q} } ){
    if ( $n == 0 ){
        printf("%5s%4s%5s%6s%6s%22s%6s %s %s\n", $q, $run{$q}, $que{$q}, $queue{$q}[$n], &conv($ncpus{ $queue{$q}[$n] }),
                        &jobbar( &conv($ncpus{ $queue{$q}[$n] })), &conv($ngpus{$queue{$q}[$n]}), 
                        &jobbarG( $ngpus{$queue{$q}[$n]} ), $down{ $queue{$q}[$n] } );
    }else{
        printf("%20s%6s%22s%6s %s %s\n", $queue{$q}[$n], &conv($ncpus{ $queue{$q}[$n] }),
                        &jobbar( &conv($ncpus{ $queue{$q}[$n] })), &conv($ngpus{$queue{$q}[$n]}),
                        &jobbarG( $ngpus{$queue{$q}[$n]} ), $down{ $queue{$q}[$n] } );
    }
  }
}
sub conv{
  my @value = split(/\//, "@_");
  my $v = $value[1] - $value[0];
return "$v/$value[1]";
}
sub jobbarG{
  my @value = split(/\//, "@_");
  if ( $value[1] == 0 ){ return;}
  my $jobbar= "*" x ( $value[1] - $value[0] );
  $jobbar = $jobbar . "-" x $value[0];
return $jobbar;
}
sub jobbar{
  my @value = split(/\//, "@_");
  my $jobbar="";
  for ( my $i=0;$i<20;$i++){
         if ( $i/20 < $value[0]/$value[1] ){
            $jobbar=$jobbar."*";
         }else{
            $jobbar=$jobbar."-";
         }
  }
  return $jobbar;
}

中身は「pbsnodes -aSj」と同じなんだけどね。複数のqueueがあった場合の対策として準備

だいたいこんな出力になります

Queue Run wait  Host  CPU           usage          GPU
  cpu   1    0  em01 20/20  ********************   0/0 
                em02 24/48  ***********---------   0/0
  gpu   2    0   g01 16/16  ********************   2/4 **--
                 g02 16/16  ********************   4/4 ****
最新の60件
2024-12-08 2024-12-05 2024-12-04 2024-11-28 2024-11-23 2024-11-22 2024-11-15 2024-11-14 2024-11-12 2024-11-06 2024-11-05 2024-11-04 2024-11-02 2024-11-01 2024-10-29 2024-10-28 2024-10-27 2024-10-23 2024-10-18 2024-10-17 2024-10-15 2024-10-14 2024-10-13 2024-10-11 2024-10-10 2024-10-09 2024-10-08 2024-10-05 2024-10-04 2024-10-03 2024-10-02 2024-10-01 2024-09-30 2024-09-29 2024-09-28 2024-09-27 2024-09-22 2024-09-20 2024-09-17

edit


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2024-10-27 (日) 23:59:29