サーバ関連:torque_pbs

torque (旧OpenPBS)

  • 計算機クラスターのジョブ管理スケジューラ
    • 異なるジョブを逐次処理させたい場合に便利 (以下の条件の時とか?)
      • メモリや CPU を最大まで使うジョブが複数あり、同時に流すとリソースの取り合いになる。最悪の場合、計算機が落ちる。
      • コマンドラインで、 && とか ; で複数のジョブをつなげても実現できるけど、その後に追加のジョブが入った場合は?
      • ジョブの終了時間を予測し、マージンをとって、at コマンドで時間を指定してジョブを実行する方法もあるけど、マージン分の時間がもったいない。予測が外れたらリソースの取り合いになる。
    • 要はプリンターの印刷状況画面のキュー (印刷データ) が、ジョブに置き換わっただけ。
    • 別に計算機クラスターである必要はなく、自分の PC に入れても問題ない
  • Ubuntu (Debianも?)では、torque-server (サーバ用)、torque-scheduler (スケジューラ)、torque-mom (ノード用) の 3 つのパッケージで機能する
    • スケジューラを変えるなどすることもあるようだ
  1. インストール
    • サーバでもジョブを処理させる場合
      $ sudo apt-get install torque-server torque-mom torque-client torque-scheduler
  2. 起動中の torque を終了させる
    1. 起動中の torque を確認
      $ ps -e | grep pbs
    2. root 権限で終了させる (service コマンドの stop や kill) する
      $ sudo service torque-mom stop
      $ sudo service torque-scheduler stop
      $ sudo service torque-server stop

      ※service コマンドで torque-server が終了しない場合

      $ sudo kill 24277

      24277 は、pbs_server の PID で ps -e | grep pbs で確認する

  3. 設定ディレクトリの設定
    $ sudo mkdir /var/spool/torque/server_priv
    $ sudo chmod 777 /var/spool/torque/spool /var/spool/torque/undelivered
    $ sudo chmod o+t /var/spool/torque/spool /var/spool/torque/undelivered
  4. サーバ名の設定
    $ sudoedit /etc/torque/server_name

    ホスト名を入れる

  5. 新たにサーバプロファイルを作成 (このコマンドを実行すると torque_server が起動する)
    $ sudo pbs_server -t create
  6. ノードの設定
    $ ps -e | grep pbs
    $ sudo kill xxxxx
    $ sudoedit /var/spool/torque/server_priv/nodes
    • 中には ノード名 np=CPU数 を列挙していく
    • 例:
      server np=8
      node1  np=4
      node2  np=4
      node3  np=2
  7. ホスト名の設定
    $ sudoedit /etc/hosts
    • 127.0.0.1 は localhost からホスト名に変更
    • 127.0.1.1 はコメントアウト
    • ノードのホスト名も入れていく
  8. サーバやキューの設定 (設定ファイルを読み込ませる)
    $ sudo service torque-server start
    $ sudo qmgr < queue.conf
    • 設定ファイル (queue.conf) は以下の通り
      queue.conf
      #
      # Create queues and set their attributes.
      #
      #
      # Create and define queue F
      #
      create queue F
      set queue F queue_type = Execution
      set queue F resources_default.ncpus = 1
      set queue F resources_default.nodes = 1
      set queue F enabled = True
      set queue F started = True
      #
      # Create and define queue Q2
      #
      create queue Q2
      set queue Q2 queue_type = Execution
      set queue Q2 max_running = 1
      set queue Q2 resources_max.ncpus = 4
      set queue Q2 resources_max.nodes = 1
      set queue Q2 resources_default.ncpus = 1
      set queue Q2 resources_default.nodes = 1
      set queue Q2 resources_available.ncpus = 4
      set queue Q2 resources_available.nodes = 1
      set queue Q2 enabled = True
      set queue Q2 started = True
      #
      # Create and define queue Q4
      #
      create queue Q4
      set queue Q4 queue_type = Execution
      set queue Q4 max_running = 1
      set queue Q4 resources_max.ncpus = 4
      set queue Q4 resources_max.nodes = 1
      set queue Q4 resources_default.ncpus = 1
      set queue Q4 resources_default.nodes = 1
      set queue Q4 resources_available.ncpus = 4
      set queue Q4 resources_available.nodes = 1
      set queue Q4 enabled = True
      set queue Q4 started = True
      #
      # Create and define queue Q1
      #
      create queue Q1
      set queue Q1 queue_type = Execution
      set queue Q1 max_running = 1
      set queue Q1 resources_max.ncpus = 4
      set queue Q1 resources_max.nodes = 1
      set queue Q1 resources_default.ncpus = 1
      set queue Q1 resources_default.nodes = 1
      set queue Q1 resources_available.ncpus = 4
      set queue Q1 resources_available.nodes = 1
      set queue Q1 enabled = True
      set queue Q1 started = True
      #
      # Create and define queue Q3
      #
      create queue Q3
      set queue Q3 queue_type = Execution
      set queue Q3 max_running = 1
      set queue Q3 resources_max.ncpus = 4
      set queue Q3 resources_max.nodes = 1
      set queue Q3 resources_default.ncpus = 1
      set queue Q3 resources_default.nodes = 1
      set queue Q3 resources_available.ncpus = 4
      set queue Q3 resources_available.nodes = 1
      set queue Q3 enabled = True
      set queue Q3 started = True
      #
      # Set server attributes.
      #
      set server scheduling = True
      set server default_queue = F
      set server log_events = 511
      set server query_other_jobs = True
      set server scheduler_iteration = 600
      set server node_check_rate = 150
      set server tcp_timeout = 6
      set server node_pack = False
      set server allow_node_submit = True
    • F: 制限がないキュー
    • Q1〜Q4: 1 ジョブしか流せないキュー
  9. 起動
    $ sudo service torque-scheduler start
    $ sudo service torque-mom start
  10. サーバ名の確認
    $ qstat -q
  11. サーバの設定状況の確認
    $ pbsnodes -a
  12. テスト
    $ echo "sleep 30" | qsub
    $ qstat
  1. インストール
    $ sudo apt-get install torque-server torque-scheduler
  1. インストール
    $ sudo apt-get install torque-mom torque-client
  • ジョブ投入
    $ qsub [オプション] ジョブファイル
    Job id                    Name             User            Time Use S Queue
    ------------------------- ---------------- --------------- -------- - -----
    760.servername            JOB_NAME1        hoge            311:35:2 R F              
    762.servername            JOB_NAME2        hoge            165:50:2 R F              
    860.servername            JOB_NAME3        fuga            03:03:40 R F              
    • Job id: 投入順に番号が付けられる (job id を指定するコマンドでは、最初の数字だけで十分)
    • Name: ジョブ名
      • qsub の -N オプションや、ジョブファイルの PBS -N で指定が可能
      • オプションなどで指定されていない場合は、ジョブファイル名の先頭から15文字が使われる
    • User: ジョブを投入したユーザ名
    • Time: ジョブ処理にかかっている時間 (複数の CPU を指定している場合は、CPU 数に合わせて倍になる)
    • S: ステータス
      • R: Running (処理中)
      • Q: Queue (待機中)
      • H: Hold (保留中; ジョブの順番が回ってきても処理しない)
      • E: Exit (終了; ?)
      • T: 移行中(?)
      • W: 待機中(?)
    • Queue: ジョブが所属しているキュー
  • ジョブ一覧
    $ qstat [オプション]
  • ジョブ削除
    $ qdel ジョブID ...
    • ジョブIDは複数指定が可能
  • ジョブの順序の入れ替え
    $ qorder ジョブID1 ジョブID2
  • ジョブの保留(ジョブ実行の順番が回ってきても実行しない)
    $ qhold ジョブID1 ジョブID2 ...
  • ジョブの保留解除
    $ qrls ジョブID1 ジョブID2 ...
  • ジョブの実行
    $ qrun ジョブID1 ジョブID2 ...
  • キューの変更
    $ qmove 変更後のキュー名 ジョブID
  • ジョブにシグナルを送信
    $ qsig -s シグナル ジョブID
    • STOP: ジョブのサスペンド(ジョブを停止することなく、CPU を空ける; ただし、torque としては CPU が空くわけではないので、次のジョブは実行されない)
    • CONT: サスペンドしたジョブの再開
  • ジョブの内容を書いたシェルスクリプト
  • シバン行 (#!/bin/bash など) に続いて、#PBS … で始まるジョブ指定
  • 例 (bash ベースの場合): \\
    jobfile.sh
    #!/bin/bash
    #PBS -V
    #PBS -l nodes=1:ppn=4
    #PBS -j oe
    #PBS -N jobname
     
    cd ${PBS_O_WORKDIR}
     
    実行コマンド
     :
  • ${PBS_O_WORKDIR}: torque が利用する作業ディレクトリ (必ず書く必要がある)
  • オプション (qsub のオプションと同じ)
オプション 意味
-Vジョブを投入した所の環境変数をすべて、ジョブファイルにも適用する
-vジョブを投入した所の環境変数を指定した分だけ、ジョブファイルにも適用する
-qキューの指定
-j出力ファイルの制御oe: 標準出力と標準エラーを標準ファイル(*.oジョブID)にまとめる, eo: 標準出力と標準エラーを標準エラーファイル(*.eジョブID)にまとめる, 指定しない場合は、それぞれのファイルが出力される
-o標準出力ファイルのパス
-e標準エラーファイルのパス
-mメール送信の方法次の文字の組み合わせでメールの送信タイミングを指定 a: ジョブが失敗, b: ジョブが開始, e: ジョブが終了, n: 何もしない
-Mメールの送信先
-lリソースの指定(複数ある場合は、カンマで区切る)walltime=24:00:00
nodes=2:ppn=2 (2CPUずつ2ノードを使う; 計4CPU)
nodes=ノード1:ppn=3+ノード2:ppn=2+ノード3:ppn=1 (特定のノードを利用する場合はノード名を書いて + で結合する)
mem, ncpu が使える
-Nジョブ名指定しない場合は、ジョブファイル名の先頭から15文字

set server … で始まる項目

項目 意味 値 (太字がデフォルト)
schedulingスケジューリングの有効化true or false
default_queueデフォルトのキューを設定
log_eventsログの出力内容
query_other_jobsroot以外のユーザが他人のジョブを閲覧する許可true or false
scheduler_iteration?
node_check_rateノードが死亡していると判断するまでの時間(秒)整数値 (600)
tcp_timeoutpbs_serverとpbs_mon間のTCPソケットのタイムアウト時間(秒)整数値 (8)
node_pack1つのノードを埋めてから次のノードを利用するかtrue or false
allow_node_submitノードからのジョブ投入の許可true or false

キュー設定

set queue キュー名 … で始まる項目

項目 意味 値 (太字がデフォルト)
queue_typeキュータイプ execution(e) or route(r)
resource_default.ncpusデフォルトで指定されるCPU数
resources_default.nodesデフォルトで指定されるノード数
enabledジョブの受け入れ(このキューでのジョブ投入を許可するか)true or false
startedジョブを実行するか(falseならhold状態で投入される)true or false
  • qmgr の設定を表示
    $ echo 'p s' | sudo qmgr
    • 'p s' は 'print server' でも可
  • 長時間ジョブを別々のキューで走らせた時に後方にある一方のキューが動かない
    • 例:
      1. CPU が 2 つある計算機上で、CPU を 1 つのみ使い、1 つずつしか走らせることができないキュー A, B にジョブを 3 つずつ投入する予定である (計6ジョブ)
        • ジョブ A1, A2, A3
        • ジョブ B1, B2, B3
        • それぞれのジョブは 25 時間以上かかるものとする
      2. 先にキュー A に 3 ジョブ (A1, A2, A3) 投入する (CPU は 1 つしか使っていない状態)
      3. 25時間後に、キュー B の 3 ジョブ (B1, B2, B3) を投入する (本来ならば、キュー B のジョブの処理がすぐに開始されるはず…)
      4. なぜか、キュー B のジョブが開始しない
    • 原因: starving job 機構
      • ジョブスケジューラはジョブの処理数を上げるため、指定された walltime が短いジョブから順に処理していく。
      • しかし、これだと walltime が長いジョブは、短いジョブが後から次々と投入されると、一向に処理されない状態になる
      • これを解決するために、starving job 機構があり、待機状態にあるジョブ (walltime が長いジョブ) が一定時間超えると、そのジョブを優先的に処理しようとする。
      • torque の starving job 機構のデフォルトの設定時間は 24 時間
      • 例で示した場合、A1 の処理中に 24 時間が経過し、A2, A3 が優先的に処理されるように設定されるが、キュー A はそもそも同時に 1 つしか処理できないため、CPU が 1 つ空いたまま、B1, B2, B3 は待機状態となる。
      • キューに使用 CPU や同時ジョブ処理数の制限がかかっていると、例のような問題が起こる
    • 解決方法 (/var/spool/torque/sched_priv/sched_config の編集)
      • starving job 機構の無効化
        • help_starving_jobs true ALL の true を false に変える
      • 機構が有効になるまでの時間の変更
        • max_starve: 24:00:00 の時間を長くする
    • job starving 機構の問題の見分け方
      • $ qstat -f でジョブ状態を表示し、その中に comment = Not Running: Draining system to allow starving job to run とあれば、この問題でジョブが処理されないことになる。
  • サーバ関連/torque_pbs.txt
  • 最終更新: 2016/06/01 20:30
  • by mumeiyamibito