バッチ型HPCジョブでシステム情報のモニタリングを簡易化してみる

# 背景
　PBSに代表されるHPC用のバッチジョブスケジューラは、CAEシミュレーションなどにおいて複数のユーザーが効率的に計算リソースを利用するために便利です。HPC用のスケジューラはリソース管理だけではなく、アプリケーションの実行に必要なセットアップやコマンドをラッピングしており、ユーザーは非常に簡易なコマンドだけでアプリケーションを実行可能です。このようなシステムはSaaSとしても提供されており、Rescale社が提供するScaleXプラットフォームでは多くのソフトウェアを利用可能です。
　これらのシステムは決まったタスクを実行するためには便利な反面、本来の目的以外の事をやろうとすると突如として不便になる場合があります。例えば、パフォーマンス向上のためにはシステム情報から状況を把握する必要がありますが、バッチ型ジョブシステムにおいてはユーザーによるシステム情報のモニタリングは前提とされていません。そのためユーザーが計算の状態を把握しにくいことが多くなっています。

# 解決したいこと
　高度な計算プログラムが十分にその性能を発揮するためには、ボトルネックとなる様々な要因を取り除く必要があります。そのためにはハードウェア構成や、実行中の各計算ノードにおけるCPU利用率やディスクI/Oなどの情報が手がかりとなります。
　今回はRescale社が提供するScaleXにおいて、ジョブを実行している環境で上記の情報を簡単に取得することが目的です。


# やってみる
　システム情報の取得に利用するコマンド一群をシェルスクリプトとしてラッピングして実行します。ジョブによって必要な情報はほとんど変わらないため、一度作成しておけば他ジョブでも同様に実行するだけです。少し内容を変更すれば、ScaleXに限らず一般的なHPCジョブスケジューラでも適応可能です。

## 前提条件
　ScaleXの環境であれば、最初から導入済みです。

  - MPIクラスタが構成されており、それぞれsshでパスレスでログインできること。
  - スケジューラがシェルコマンドを受け付けてくれること。
  - NFSマウントされた共有のデータ領域を保有していること。
  - ホスト情報が記載されたmachinefileが提供されること。
  - `sar`コマンド利用のため、sysstatが導入済みであること。


## 内容
　ハードウェア情報や環境変数を、特定のフォルダにテキスト情報として出力します。InfiniBandが存在しそうな場合、その情報の取得も試みます。実行中のシステム情報を取得するため、`sar`コマンドを各計算ノードにSSHのリモートコマンドで送り込みます。情報の取得間隔があまりにも短いとパフォーマンスに悪影響を及ぼすので、予想される計算の実行時間に応じて程々に。
　送り込む先はMPIプロセス実行時に用いるmachinefileから取得します。もし取得できない場合は`# Make Hostlist`以下を、適宜編集ください。

```shell:getSystemStatuses.sh
#!/bin/sh

# Common Settings
NFS_WORKING_DIR=${RESCALE_SHARED_DIR}/SystemInfo
MACHINEFILE=~/machinefile 
SAR_INTERVAL=360

mkdir -p ${NFS_WORKING_DIR}


# Make Hostlist
if [ -f ${MACHINEFILE} ]; then
  list=(`sort ${MACHINEFILE} | cut -d':' -f1 | uniq`)
fi


# Standard Info
env | sort     >> ${NFS_WORKING_DIR}/env.log
cat /etc/hosts >> ${NFS_WORKING_DIR}/hosts.log

lscpu    >> ${NFS_WORKING_DIR}/lscpu.log
lspci -v >> ${NFS_WORKING_DIR}/lspci_v.log
ifstat   >> ${NFS_WORKING_DIR}/ifstat.log
ip addr  >> ${NFS_WORKING_DIR}/ip_addr.log


# Infiniband Info
if hash ibv_devinfo 2>/dev/null; then
  ibv_devinfo   >> ${NFS_WORKING_DIR}/ibv_devinfo.log
  ibnetdiscover >> ${NFS_WORKING_DIR}/ibnetdiscover.log
  ibhosts       >> ${NFS_WORKING_DIR}/ibhosts.log
  ibswitches    >> ${NFS_WORKING_DIR}/ibswitches.log
  
  ibstat -i >> ${NFS_WORKING_DIR}/ibstat_i.log
  ibstat -n >> ${NFS_WORKING_DIR}/ibstat_n.log
  ibstat -p >> ${NFS_WORKING_DIR}/ibstat_p.log
  ibstat -v >> ${NFS_WORKING_DIR}/ibstat_v.log
fi


# Copy home file
ls -aF ~/ | grep -v / | tr -d "*" | tr -d "@" | tr -d "|" | xargs -I {} cp ~/{} ${NFS_WORKING_DIR}/


# excute sar for each node
for target in "${list[@]}"; do
  command="sar -o ${NFS_WORKING_DIR}/sar-${target}.data ${SAR_INTERVAL} >> ${NFS_WORKING_DIR}/sar-${target}.log & "
  ssh ${target} ${command}
done

```

|

　計算実行後、各計算ノードにまいたsarプロセスを停止させます。後々解析するのは面倒なので、一緒にテキスト化も行っておきます。最後に作業用フォルダから整理しやすい位置に移動させて完了。

```shell:terminateSystemStatuses.sh
#!/bin/sh

# Common Settings
NFS_WORKING_DIR=${RESCALE_SHARED_DIR}/SystemInfo
SYSTEMINFO_DIR=${RESCALE_WORKING_DIR}/SystemInfo
MACHINEFILE=~/machinefile 


# make hostlist
if [ -f ${MACHINEFILE} ]; then
  list=(`sort ${MACHINEFILE} | cut -d':' -f1 | uniq`)
fi


# tarminate sar process
for target in "${list[@]}"; do
  ssh ${target} 'kill `ps auxw | grep "sar -o"| grep -v grep | grep -v sudo | cut -d" " -f2 ` '
  sar -f ${NFS_WORKING_DIR}/sar-${target}.data -n ALL >> ${NFS_WORKING_DIR}/sar-${target}_net.log
  sar -f ${NFS_WORKING_DIR}/sar-${target}.data -b     >> ${NFS_WORKING_DIR}/sar-${target}_io.log
  sar -f ${NFS_WORKING_DIR}/sar-${target}.data -r     >> ${NFS_WORKING_DIR}/sar-${target}_mem.log
  sar -f ${NFS_WORKING_DIR}/sar-${target}.data -W     >> ${NFS_WORKING_DIR}/sar-${target}_swap.log
done

mv ${NFS_WORKING_DIR} ${SYSTEMINFO_DIR}
```


## 実行方法

　上記のスクリプトをインプットファイルと一緒にアップロードして、
実行したいコマンドの前後にこれらのスクリプトで挟んで、実行するだけです。

```shell-session:command
./getSystemStatuses.sh
  # some_execution_commands
./terminateSystemStatuses.sh
```

## 結果
　取得した情報は全て`SystemInfo`以下に集めるようにしました。ScaleXでは実行結果がブラウザから簡単に閲覧できるので、試しにディスクI/Oの一例を見てみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/294952/03bed0cc-e4cf-06d6-0b0f-f9140e9dc26f.png)
いい感じに取れてそうです（テストのため`INTERVAL`を10秒に設定しています）。

　あとはこのまま眺めるなりダウンロードするなり、グラフで可視化するなり。もし定型化している解析作業があれば、`terminateSystemStatuses.sh`に一緒に入れ込んでしまうのがおすすめです。