SkylakeとEPYCの比較 : Bioinfomatics Applications(1)

SkylakeとEPYCの双方でいくつかのbioinfomatics applicationでベンチマークを取ってみました。

今回比較に使用したのは以下の4モデルです。

CPU コア数 クロック周波数(定格) クロック周波数(ターボ最大) クロック周波数(All Core Boost) 概算価格(Web上) ※
Xeon Gold 5118 12 2.3 GHz 3.2 GHz 2.7 GHz $1,273
Xeon Gold 6126 12 2.6 GHz 3.7 GHz 3.3 GHz $1,776
EPYC 7351 16 2.4 GHz 2.9 GHz 2.9 GHz > $1,100
EPYC 7401 24 2.0 GHz 3.0 GHz 2.8 GHz $1,850

※ XeonはIntelのWebサイトの希望カスタマー価格から、EPYCはanandatech のWebサイトから

numactlで見るEPYCの特徴

性能面を考慮するときにコア数が多いという点は大きな特徴なのですが、
OSからは8コア単位で別のCPUコアとして認識されるため少し注意が必要です。

例えば、Dual CPU構成のマシンにおいてnumactl -H をXeonで実行した時、
下記のようになり、node0がCPU0、node1がCPU1を示しているのですが、

Xeon

# numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 96938 MB
node 0 free: 87276 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 98304 MB
node 1 free: 92604 MB
node distances:
node   0   1 
  0:  10  21 
  1:  21  10

EPYC

EPYCの場合はDaul CPU構成でも下記のようになりまるで4coreのCPUを8個搭載しているように見えます。
末尾のnode distancesの行列は各コア間のメモリへのアクセスの相対的距離を示しているのですが
EPYCの場合はXeonに比べて同じ物理CPU間でも(node0 – node3)の間でも距離が生じ、物理的に遠いCPUの
メモリにアクセスした場合の距離はXeonに比べて1.5倍ほどになっています。

# numactl -H
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3
node 0 size: 65444 MB
node 0 free: 40188 MB
node 1 cpus: 4 5 6 7
node 1 size: 65535 MB
node 1 free: 41572 MB
node 2 cpus: 8 9 10 11
node 2 size: 65535 MB
node 2 free: 41057 MB
node 3 cpus: 12 13 14 15
node 3 size: 65535 MB
node 3 free: 41075 MB
node 4 cpus: 16 17 18 19
node 4 size: 65535 MB
node 4 free: 41153 MB
node 5 cpus: 20 21 22 23
node 5 size: 65535 MB
node 5 free: 41604 MB
node 6 cpus: 24 25 26 27
node 6 size: 65535 MB
node 6 free: 39944 MB
node 7 cpus: 28 29 30 31
node 7 size: 65535 MB
node 7 free: 41523 MB
node distances:
node   0   1   2   3   4   5   6   7 
  0:  10  16  16  16  32  32  32  32 
  1:  16  10  16  16  32  32  32  32 
  2:  16  16  10  16  32  32  32  32 
  3:  16  16  16  10  32  32  32  32 
  4:  32  32  32  32  10  16  16  16 
  5:  32  32  32  32  16  10  16  16 
  6:  32  32  32  32  16  16  10  16 
  7:  32  32  32  32  16  16  16  10 

ベンチマーク1 : Bowtie2-2.3.1

全コア使用時の比較

bowtieのベンチマークとは書きましたが、
sraファイルを取ってきてfastqを生成し、bowtie 〜 samtoolsを実行してbamファイルを生成してインデックスをつけるところまでを
一連のスクリプトで実行した場合のそれぞれの実行時間(単位:秒)です。
マルチスレッドに対応しているコマンドは全コア使用して実行するようにしています。

Xeon 5118 (24thr) Xeon 6126 (24thr) EPYC 7351 (32thr) EPYC 7401 (48thr)
fastq-dump(1thr) 286.97 241.44 295.52 280.88
bowtie2-build(All threads) 1040.15 883.99 1380.66 1374.31
bowtie2(All threads) 1138.18 982.78 904.81 672.82
sam2bam(All threads) 274.47 236.21 309.12 173.46
sam index(1thr) 133.30 109.04 131.43 124.93
合計(秒) 2873.07 2453.46 3021.54 2626.40

合計時間ではXeonが若干優位ですが、これはbowtie2-buildの実行時間に大きな差が生じていることが原因です。
bowtie2に限ってみればコア数の多さも手伝ってEPYCが優位という結果となりました。

EPYC: bind有無による性能比較

上で書いたnumactlの件があったので、
numactlでcpu,memoryをbindした場合としない場合の比較をしてみました。
bindした方の実行コマンドは以下の通りです。

  • 4thread # numactl --cpubind=0 --membind=0 bowtie2 -p 4 -x hg19chr_build -1 SRR067579_1.fastq -2 SRR067579_2.fastq -S SRR067579.sam
  • 8thread # numactl --cpubind=0,1 --membind=0,1 bowtie2 -p 8 -x hg19chr_build -1 SRR067579_1.fastq -2 SRR067579_2.fastq -S SRR067579.sam
  • 16thread # numactl --cpubind=0,1,2,3 --membind=0,1,2,3 bowtie2 -p 16 -x hg19chr_build -1 SRR067579_1.fastq -2 SRR067579_2.fastq -S SRR067579.sam
EPYC 7351(no bind) EPYC 7351 (bind)
4 threads 6238.84 5471.70
8 threads 3368.63 2871.93
16 threads 1905.74 1488.22
32 threads 904.81

bindするしないでかなりの差が出ました。
(Xeonでも測定はしましたがbind/no bindいずれもほとんど変わらない結果でした。)

このあたりは、上記のメモリが遠いことも関係してそうですし
OS/kernel周りの最適化などでEPYC向けの最適化が進めばもう少しましになるのではないかと期待したいですが、
現状ではbindしないことによるペナルティが大きいです。

ベンチマーク2 : BWA-0.7.17

全コア使用時の比較

bwaもbowtie2同様、fastq-dump〜bwa〜samtoolsの処理を一連のスクリプトにして実行した各実行結果です。

Bowtie Xeon 5118 Xeon 6126 EPYC 7351 EPYC 7401
fastq-dump(1thr) 124.66 103.15 133.93 131.68
bwa index(1thr) 261.49 227.23 228.07 231.14
bwa mem(All threads) 413.93 360.47 468.24 314.18
sam2bam(All threads) 64.85 56.85 59.45 54.48
sam index(1thr) 52.69 43.85 51.05 48.46
合計(秒) 917.62 791.55 940.74 779.94

EPYC: bind有無による性能比較

こちらもbowtie2同様にEPYC 7351を使ってbind/no bindで測定しました。
bowtie2ほどでは無いにせよ、1割前後の性能差が出ています。

EPYC 7351(numa) EPYC 7351(no-numa)
4 threads 2251.20 2671.92
8 threads 1239.04 1368.78
16 threads 670.60 714.75
32 threads 468.24

ベンチマーク3 : Stream Benchmark

bioinfomaticsのアプリケーションでは無いのですが、
冒頭のnumactlの結果を見るとやはりメモリのアクセス速度のところの性能差がどのようになるのか
気になるのではないかと思いますので載せてみます。(単位:MB/s)

メモリの仕様に関してですが、
SkylakeはCPUあたり6チャネル、EPYCはCPUあたり8チャネルを持っています。
メモリ動作速度の最大はどちらも2666MHzです。

Skylake
numa Copy Scale Add Triad 説明
numactl –cpubind=0 –membind=0(16core/96G) 64409.9 64554.2 72856.2 72906.3 同一ソケット内でのメモリアクセス
numactl –cpubind=0 –membind=1(16core/96G) 33926.9 33933.1 34168.7 34161.8 遠い方のメモリへのアクセス
no numa(32core/192G) 129168.4 129021.6 145590.5 145569.8 BindせずDual Socketの全コア使用
EPYC
numa Copy Scale Add Triad 説明
numactl –cpubind=0 –membind=0(4core/64G) 23979.4 23771.1 26700.0 26728.0 同一ソケット内の同一node
numactl –cpubind=0,1 –membind=0,1(8core/128G) 47986.7 47878.3 52967.8 53028.5 同一ソケット内の2node使用時
numactl –cpubind=0,1,2,3 –membind=0,1,2,3(16core/256G) 95562.5 95557.8 105311.1 105500.6 同一ソケット内の全コア使用時
no numa(32core/512G) 135144.3 134846.0 141459.4 142717.5 BindせずDual Socketで全コア使用

Skylakeの場合、bindせずに全コア使用した場合のメモリ帯域が、同一ソケット内でのメモリ帯域の2倍になっていることから
明示的にbindしなくても自動的に近い方のメモリアクセスをするようになっているということが上記の結果からわかります。

反面、EPYCの場合、Single Socketの結果から、Dual Socketでは200GB/s近いメモリ帯域が出るのではいないかという期待が膨らむものの
実際にはSkylakeと同程度の帯域しか得られませんでした。このあたりはOS/Kernel周りの最適化で今後改善されるか期待を持ってみたいと思います。

Optane SSDとNVMe, RAMDiskの比較

Optane SSDとは

IntelとMicronが共同開発した3D Xpointという新しい不揮発性メモリの技術を使ったSSDです。
インターフェースはNVMeで、Form FactorもNVMeと同様、PCIe拡張カードタイプ(AIC)と2.5″タイプ(U.2)があります。

DRAMとNANDの間の性能ギャップを埋める製品。今回はConsumer用の900pというモデルを使いましたが、DataCenter用のP4800xというモデルはDRAMとOptane SSDで一つのメモリプール空間を構成することが可能です。
https://www.intel.co.jp/content/www/jp/ja/architecture-and-technology/intel-optane-technology.html

特にDRAMとOptane SSDで同一のメモリ空間を構成できるという点が面白そうです。現在のSkylake世代のXeonは、通常のSKUで768GB/CPU、High Memory SKUで1.5TB/CPUですが、これを使うことで下記の動画を見ると、DRAMとSSDで階層化のやりとりを行うようです。
https://www.intel.com/content/www/us/en/software/intel-memory-drive-technology.html

今回は、Optane SSD 900pを評価してみました。従来のNVMeとの性能比較だけでなく。
Memory Drive Technologyを見据えて、RAM Diskとの性能差についても比較してみました。


NVMe SSDとOptane SSDの比較

Sequetial Read/Write (IOR)

測定概要

結果

同時I/Oファイル数(-Nの後ろの数字)に関わらず、NVMeより大幅に高速
特にファイル数が少ないケースのReadの性能差は顕著です。

** Sequential Read **

-N1 -N2 -N4 -N8
Intel SSD DC P3520 NVMe(2TB) 398.19 MB/s 641.67 MB/s 1214.79 MB/s 1758.74 MB/s
Intel Optane SSD 900p(280GB) 2070.20 MB/s 2391.51 MB/s 2707.66 MB/s 2707.15 MB/s

** Sequential Write **

-N1 -N2 -N4 -N8
Intel SSD DC P3520 NVMe(2TB) 1495.49 MB/s 1519.79 MB/s 1536.00 MB/s 1501.45 MB/s
Intel Optane SSD 900p(280GB) 1513.91 MB/s 2193.01 MB/s 2233.80 MB/s 2248.58 MB/s

Random Read/Write

測定概要

  [global]
  bs=4k
  ioengine=libaio
  size=2g
  direct=1
  directory=/xxx
  numjobs=32
  group_reporting

  [Rand-Read-4K-QD32]
  iodepth=32
  rw=randread 

  [Rand-Write-4K-QD32]
  iodepth=32
  rw=randwrite
  • 測定対象デバイス
    • Intel DC P3520(2TB)
    • Intel Optane 900p(280GB)
    • ramdisk (DDR4-2666 16GB x12 の中から100GBを切り出し)

結果

RAM Disk >>> Optane > NVMe という結果となりました。
RAM DiskとOptaneは文字通り桁が違う性能差で、これだけの差が生じると同じメモリプールに入れてもアプリケーションに
影響が出るかもしれませんがどうなのでしょうか。
いずれ実アプリケーションでのベンチマークを行なってこちらでも紹介したいと思います。

** Ramdom Read **

IOPS BandWidth
Intel SSD DC P3520 NVMe(2TB) 382 k 1494 MiB/s
Intel Optane SSD 900p(280GB) 586 k 2290 MiB/s
RAM Disk 8224k 31.4 GiB/s

** Ramdom Write **

IOPS BandWidth
Intel SSD DC P3520 NVMe(2TB) 149 k 583 MiB/s
Intel Optane SSD 900p(280GB) 246 k 963 MiB/s
RAM Disk 8020 k 30.7 GiB/s

まとめ

  • Optane SSDはNVMeよりも30%〜高速(条件次第では5倍程度高速なケースも)
  • ただ、[ここ](https://www.intel.com/content/www/us/en/products/memory-storage/solid-state-drives/gaming-enthusiast-ssds/optane-900p-series/900p-480gb-aic-20nm.htmlNVMe SSD) にもあるようにNVMeとの価格差が大きい
  • 価格とも関連するが、ラインナップされているシリーズの容量がまだまだ小さい(P4800Xで750GB: 将来的なロードマップはわからないが)
  • DataCenter向けのP4800Xで使用可能と言われる、Intel Memory Drive Technologyは要注目

閉鎖系ネットワークで環境パッケージ管理ツールpipやcondaなどを利用する

便利なパッケージ管理ツール

昨今は研究系ITの環境はとてもよくなり、以前であればソースをダウンロードし、
./configure 、 makeして、make install、
といった複数手順を踏まなければならなかった解析ソフトウェアのインストールも、
pip install chianer
や、
conda install picard
といったコマンド一発でインストールできるようになりました。それも、ソフトウエアを複数のユーザーで共有する従来からのモデルはもちろんですが、各ユーザーがroot権限を必要とすることなく、自分のホームディレクトリ内で自分の環境をつくることができます。これらのツールは、インストールしたいソフトウェアが必要としている別のソフトウェアを判断し、すべてインターネットから自動的にインストールしてくれます。

環境によって突如旧石器時代へ

 ところが、取り扱うデータの機密性の事情もあり、インターネットから切り離さざるを得ない閉鎖系ネットワーク環境では事情が激変します。pipやcondaは機能しないため、ユーザーは依存しているソフトウェアの調査から、手動でパッケージをかき集め、順番を気にしながらインストールすることになります。
例えば、pip install chainer を実行した場合、chainerのほか、filelock numpy protobuf sixなどのパッケージが自動でインストールされますが、インターネットにつながらないため、そもそもどのパッケージが必要かの判断さえも実行されなくなるのです。

解決方法

 この問題を解決するのに良い方法はふたつ、ひとつはdockerコンテナ技術を利用し、解析ツールをコンテナ化することです。コンテナはあるソフトウェアが動作するために必要な最低限の環境をパッキングしてくれるため、インターネットに接続しているマシンで解析用のコンテナをつくり、それを閉鎖系ネットワーク環境にある計算機にもってきて利用します。

 もうひとつの方法として、pipのダウンロードもとであるpypi、condaのリポジトリ、centosやepelなどのリポジトリを丸ごと閉鎖系ネットワークで動かしてしまう方法があります。この方法はインターネットに接続しているマシンを利用する感覚に最も近く、その瞬間必要で欲しいパッケージをコマンド一発で入れられるようになるため、必ずしも環境構築の専門家とはいえないデータサイエンティストを閉鎖系ネットワークであることによる困難から解放します。

mirrored repository server

update用のサーバーはjenkinsによる定期ジョブ実行で自動的に各種リポジトリを最新にしてくれます。閉鎖系への適用は随時、任意のタイミングで行うことができます。

mirrored repository を利用してできること

mirrored repositoryのある環境では、例えば作りたての新しいユーザー環境に対して、chianermnを動作させるところまで環境構築をすることができます。

管理者として必要な環境の構築・アップデート

openmpiのセッティング、cudaのアップデート、centosやepelのリポジトリにある必要なパッケージのインストール

一般ユーザー環境にpyenvを導入、必要なPythonをインストール

複数バージョンのPythonを自分のホームディレクトリにインストールし、切り替えて利用できるpyenvを導入できます。

pipコマンドで必要なpythonパッケージをインストール

virtualenvもインターネットに接続されたマシンと同様に
pip install virtulenv
でインストールできます。
ほか、
pip install numpy
pip install scipy
pip install chainer
pip install chainercv
pip install chainermn
などももちろん可能です。

condaコマンドも利用可能

condaでないと利用できないパッケージもあります。
標準リポジトリのほか、例えばbiocondaなども構築可能です。
conda install bwa
conda install bowtie2
conda install picard

まとめ

今回はインターネットから隔離された環境で、インターネットに強く依存した便利なパッケージ管理ツールを利用する方法を紹介しました。特に試行錯誤の必要な研究フェーズにおいては役に立つのではないでしょうか。詳細をご希望の際は弊社営業かエンジニアへお問い合わせください。

NFS over RDMA : NFS(tcp)やLustreとの性能比較

RHEL7.4が8月にリリースされ、それまで長らくTech Preview扱いだったNFS over RDMAが正式サポートされることになりました。ということで今回、NFS(tcp)とNFS over RDMAとの性能比較をしてみました。また、NFSではないですが同じくRDMAを使っている共有ファイルシステムということでLustreについて比較したデータも紹介したいと思います。

RDMA (Remote Direct Memory Access)
言葉の通り、ネットワーク越しの別のマシンのメモリに直接アクセスできるというもので、この場合の直接というのは、CPUを介すること無くという意味です。主にInfiniBandで使われることが多く、複数ノードでMPI並列のジョブを実行するの性能に効果を発揮するものです。
参考URL : https://community.mellanox.com/docs/DOC-1963

性能比較(IOR) : NFS(tcp) vs NFS(rdma)

テスト環境

  • NFS領域: 20本のHDD(7.2Krpm)でHardware RAID6(18+2)
  • NFS領域のFilesystem: XFS
  • NFS Client: 1台
  • Network: QDR InfiniBand
  • 測定ツール: IOR-3.0.1(openmpi-3.0.0)

結果

下記のグラフの通りRead/WriteともにNFS(tcp)に比べてNFS(rdma)の方が性能が出ていることがわかります。特にReadに関しては50%ほどの性能差が出ています。

性能比較(dd) : NFS(tcp) vs NFS(rdma)

Read性能に差がかなりの差が出ているので念の為ddでも測定してみました。Writeは差がでないものの、Readは2倍の差が出ました。

  • Write性能 :
$ time dd if=/dev/zero of=25G bs=1M count=25000
NFS(tcp) : 27.977s(937MB/s)
NFS(RDMA) : 27.421s(956MB/s)
  • Read性能 :
$ time cat 25G > /dev/null
NFS(tcp) : 19.998s(1250MB/s)
NFS(RDMA) : 9.792s(2553 MB/s)

性能比較(IOR) : NFS(tcp) vs Lustre

続いてNFS(tcp)とLustre(rdma)の性能比較です。上記とは異なる環境で実施しています。
テスト環境は下記の通りで、実際に1台のサーバーでMDS/OSSを兼ねてLustreを構築することは実運用上はほとんどないかと思いますが、
あくまでテスト用の環境です。

テスト環境

  • NFS領域: 20本のHDD(7.2Krpm)でHardware RAID6(18+2)
  • NFS領域のFilesystem: ZFS
  • LustreのBackend Filesystem: ZFS
  • NFS/Lustre Client: 4台
  • Network: QDR InfiniBand
  • 測定ツール: IOR-3.0.1(openmpi-3.0.0)
  • Lustre version: 2.9.59_32

結果

4台のNFS/Lustre ClientからIORを実行した結果は以下の通りです。
NFS(rdma)との比較同様、同じHardware構成であってもSingle構成のLustreはNFS(tcp)に対してRead/Writeともの大きな性能差を発揮しています。

まとめ

  • IORでは、NFS(rdma0はNFS(tcp)に比べてWriteで10-20%、Readで40-50%程度高い性能をIO性能が得られる
  • 同じくRDMAで通信を行うLustreで測定した場合でも同様にNFS(tcp)に対して高い性能が得られる
  • 基本的にはNFSv3,v4どちらでも使えるが、NFS ServerのNFS領域がZFSで構成されている場合は、IORがエラーとなって実行できず(v3なら問題なし)
    • Server側
      kernel: svcrdma: send: invalid request error (9/0x8a)
    • Client側
      kernel: RPC: rpcrdma_recvcq_process_wc: rep ffff88203bd60540: local length error
      kernel: rpcrdma: connection to 192.168.255.1:20049 on mlx4_0, memreg ‘frwr’, 128 credits, 16 responders

実アプリケーションでの評価も行う必要がありますが、NFS over RDMAをお使いのTakeruで使いたいという場合には担当の営業かエンジニアまで
ご連絡いただければと思います。

Galaxy Reporting機能紹介

概要

Galaxyにはより詳細な情報を得られるレポート機能があります。標準では動作していませんが、本稿ではこのレポート機能について紹介します。

レポート機能について

本機能では、Galaxyの運用上で有用な様々な情報を得ることができます。
Jobs, Histories, Tools, Workflows, Users, Systemといったメニューがあり、Galaxy上のユーザーやジョブ、データ領域などについての情報を得られます。
管理者はこれらのデータをもとにユーザーやディスク容量の管理、ツールやワークフローの改善の計画などを行うことができます。

レポート機能へのアクセス

標準ではポート9001で動作します。
正しく設定し、起動できていると、
http://[IPアドレス]:9001
でアクセスできます。

jobsメニュー

Jobsでは、今現在動作しているジョブの情報、1ヶ月毎に実行されていたジョブ数の確認、エラーや完了できなかったジョブの情報、ユーザーあたり実行していたジョブの数、ツールあたり実行されていたジョブの数、などが確認できます。

[例:実行されていたジョブの月次報告]

[例:各ユーザーのジョブ実行状況確認]

Historiesメニュー

Historiesでは、各ユーザーの持っているHistoryやデータ量の情報が得られます。例えば管理者として、エラー状態のデータを多く持っているユーザーの把握が可能になりますので、積極的に利用者の支援を行うことも可能です。

[例:各ユーザーのHistory数やデータ数確認]

[例:History毎の状況確認]

Toolsメニューについて

Toolsではツールごとにエラーの多いものや利用状況などの情報を得られます。また、実行時間についても平均値や最大値などの情報が得られます。

[例:StateがOKであるツールの上位一覧]

[例:ツール毎の平均実行時間等の情報]

Workflowsメニューについて

Workflowsではworkflowの実行状況についての情報が得られます。

[例:ワークフロー毎の実行回数一覧]

Usersメニューについて

Usersでは、ユーザーがいつ登録されたか、最後にログインしたのはいつなのか、といった情報を得られます。また、ユーザーの持つHistoryの数や、ディスク容量の使用状況も得られます。

[例:ユーザー毎のディスク使用状況一覧]

[例:月次別ユーザー作成状況一覧]

Systemメニューについて

Systemでは、ディスクの使用状況について情報が得られます。
例えば4GB以上のデータを一覧し、データの所有者やどのHistoryで使われているかなどの情報も得られます。

[例:ディスクの使用状況および、サイズの大きいデータ一覧]

まとめ

Galaxyには標準では動作していないものも多いのですが様々な機能があります。
単にGalaxyのユーザーといっても、ダウンロードして試しに動作させている方から、本家Galaxyなどのように複数のセンターを拠点とした巨大なものまであるためのようです。

今回はレポート機能を紹介いたしました。
Galaxyを運用していると出てくる、ディスク容量の把握や予測、効率良く実行できているかの確認、ユーザーの管理などに有用な情報が得られるようになります。

ユーザーや利用状況の情報が多く得られるものですので、実装の際はセキュリティに配慮する必要があります。
本機能に興味がございましたら担当営業やエンジニアに直接お問い合わせください。

Univa Grid Engine : DockerをUGEで管理する

概要

Univa Grid Engine(以下UGE)の8.4.0以降のバージョンではUGEはDockerに対応しています。
とは言っても、正直言ってこれが意味するところはすぐにはピンと来ないかもしれません。
それは、対応するしないにかかわらず、
$ qsub -b y -N DOCK -cwd docker run -it --rm .....
というように、dockerのジョブであることを意識せずに非dockerのジョブと同じようにqsubすれば
ハードウェアリソースの状況を見てジョブをスケジューリングするということが可能である、
ということが一因としてあるのではないかと思います。

今回は、UGEがDockerに対応していることのメリットについて少し挙げてみたいと思います。


UGEがDockerに対応していることのメリット

a) ホスト毎のdockerの有無をリソースとして管理している

計算ノード内でdockerのdaemonが動いているノードと動いていないノードがあった場合、
dockerが動いているノードを実行対象としてくれます。
” # qstat -F docker “と実行してhl:docker=1となっていればそのホストではdockerのジョブの実行が可能です。
hl:docker=0の場合はdockerのジョブは投入されません。

$  qstat -F docker
queuename                      qtype resv/used/tot. np_load  arch          states
---------------------------------------------------------------------------------
all.q@n000                      BIP   0/0/24         0.00     lx-amd64      
              hl:docker=1

b) ホスト毎に保持しているコンテナイメージのリストも管理している

ジョブの中で指定されたコンテナイメージを持っているホストにジョブが投入されるので
pullする時間を待つ必要が無く、効率的にジョブが実行される
(上記はデフォルトの動作で、”-soft” オプションを付けるとイメージを保持しているホストが無かったり、リソースが埋まっていて
すぐにジョブが投入されないような場合には、イメージを持っていないホストにジョブが投入され、docker pullも行われるようになります)

“# qstat -F docker_images”と実行すると各ホストで持っているイメージのリストがカンマ区切りで表示されます。

$  qstat -F docker
queuename                      qtype resv/used/tot. np_load  arch          states
---------------------------------------------------------------------------------
all.q@n000                      BIP   0/0/24         0.00     lx-amd64      
             hl:docker_images=docker.io/bgruening/galaxy-stable:latest,docker.io/nvidia/cuda:latest,docker.io/centos:latest

c) ジョブが完了したらコンテナを削除してくれる

若干地味なメリットかもしれませんし、--rmを付けるのを忘れなければいいという話でもあるかもしれませんが。
ジョブが完了した時だけでなく、何らかの原因でUGEの実行デーモンが落ちてしまったようなケースでも、
sge_container_shepherdというプロセスが残っており、次回デーモン起動時にフォローして削除してくれます。


ジョブの例

例1) centos:latestのコンテナを使って日時とホスト名を返すだけのジョブ

  • ジョブスクリプト
#!/bin/bash

#$ -N DOCKER_DEMO
#$ -l docker
#$ -l docker_images="*centos:latest*"

echo  =="DATE"
date
echo
echo  =="HOSTNAME"
hostname
  • UGEの結果ファイル
==DATE
Mon Oct  9 13:33:04 UTC 2017

==HOSTNAME
2240452d3be2

例2) UGEの-xdオプションを使ってdockerのオプションをUGEに渡すジョブ

  • ジョブスクリプト
#!/bin/bash

#$ -N DOCKER_DEMO
#$ -l docker
#$ -l docker_images="*centos:latest*"
#$ -xd "-v /home:/home" 
#$ -cwd

echo  =="DATE"
date
echo
echo  =="HOSTNAME"
hostname
echo
echo =="HOME"
ls -l /home
  • UGEの結果ファイル : “-v /home:/home”が正しく渡されてホスト機側でls -l /home/と実行したのと同じ出力が得られています。
==DATE
Mon Oct  9 13:49:58 UTC 2017

==HOSTNAME
a2db6ea920ac

==HOME
total 0
drwx------ 4 1000 1000 153 Oct  9 13:47 beowulf
drwx------ 2 1001 1001  62 Oct  9 13:46 takeru
drwx------ 2 1002 1002  62 Oct  9 13:46 voyager

例3) 保持していないコンテナイメージを使って実行するジョブ

  • ジョブスクリプト (ubuntu:latestはどのホストにも無い状態です)
$ qsub -cwd -l docker,docker_images="*ubuntu:latest*" -soft demo.sh

あるいは

$ qsub -b y -cwd -l docker,docker_images="*ubuntu:latest*" -soft cat /etc/os-release

本来なら上記は全てスクリプトに書いた上で $ qsub [スクリプト] としたいところなのですが、
そのように実行すると -softオプションが正しく伝わらずにpullを試みてくれませんので
上記のように実行する必要があります。(調査中)


注意点

dockerのバージョン依存

CentOSでdockerを使う場合、現在は主に3つの選択肢があります。(docker-eeは省略)
– docker-ce(docker-ce.repo) : 10/9現在最新 v17.09
– docker-latest(centos repo) : 10/9現愛最新 1.13.1-23.git28ae36d.el7.centos.x86_64
– docker(centos repo) : 10/9現愛最新 1.12.6-55.gitc4618fb.el7.centos.x86_64
docker-latestとdockerの違いについてはこちらを >> http://rhelblog.redhat.com/2016/10/31/understanding-docker-latest-package/

ただ、docker-ceだとdockerのサービスが動作してる状態でも、hl:docker=1にならず動作しません。
パッケージ名がdocker-engineだった頃からマイナーバージョンの違いによってhl:dockerが0になったり1になったりするので
実際には使用するバージョンで試してみるしかないというところですが、少なくともdocker-ceは動かないと考えていいと思います。

centosのrepositoryから取得するdocker, docker-latestについてはいずれもhl:docker=1になって動作することを確認しています。


まとめ

上記のメリットのところでも挙げた通り、dockerの有無、dockerコンテナイメージの有無をUGE側で管理してくれるため
ユーザーがあまり意識をしなくても適切なノードにジョブを割り振ってくれるということが大きいのではないかと思います。
全ての計算ノードが同じハードウェア/ソフトウェア仕様で、保持しているコンテナも同じというような環境であれば
ジョブスケジューラー側での対応ということに特別な価値は無いのかもしれませんが、
ハードウェア構成の異なる機器でクラスタが構成されていたり、保持しているコンテナイメージもホスト毎に異なっている
といったケースでは、ジョブスケジューラーがDockerに対応しているということのメリットが享受できるはずです。

Skylake XeonのTurbo性能について

先月の話になりますが、IntelのXeonのE5-2600v4の後継の新しいXeonのCPUが発表されました。
今回からネーミングルールがIntel Xeon Scalable Processor Familyのもと
下記のような名称に変更となりました。(Skylakeはコード名で正式名称ではありません)

  • Platinum 81xx
  • Gold 61xx/51xx
  • Silver 41xx
  • Bronze 31xx

具体的にどういった点が変わったかについてはニュース記事などを参照して頂くとして
今回はタイトルの通り、Turbo性能に絞って書いてみたいと思います。

まず、CPUの製品一覧ページの表記が前世代も含めて変更になっていることに注目したいと思います。
これまでは、一覧ページにはベースクロックだけが表示されていたように思いますが
今回の変更からは、Turbo Boost時のMaxクロック周波数が先に表示されるようになっています。
(ブラウザの表示幅によって表示される項目数が変わるようです)

Turbo Boostというのは、熱的に余裕がある場合にCPUのクロック周波数を上げて性能を向上させる機能のことで
BIOSとOSの設定でONにしておけばあとはユーザーは気にせずとも勝手に上げ下げをしてくれます。

上記のURLには定格のクロック周波数とMaxのクロック周波数しか記載がありませんが、
Maxのクロック周波数というのは概ね1コア,2コア程度のみ使用している場合の動作周波数のことで、
Activeなコア数が増えるに従って、徐々に低下していきます。
ただ、全コアがActiveな場合でもクロック周波数は定格周波数まで落ちるということはなく、
定格に比べれば高い周波数で全コアが動作します。
先日確認した限りでは温度エラーのアラートが出るThresholdの温度に至るまではBoostされた周波数で動作していましたので
よほど温度環境が厳しい場合を除けば、基本的にはBoostされた周波数で動作するはずです。

そうなると気になってくるのは、何コアを使用した時にどんな周波数で動作するのかということですが、
Intelの公開されている資料に記載されていて、これについても仕様で決まっています。

E5-2600v4世代との比較のため下記の通りグラフにしてみました。
X軸がCPUの型番、Y軸がクロック周波数(GHz)となっていて、
青い点が各型番のベース周波数、赤い帯がターボ時の周波数の範囲を示しています。
(赤い帯の上端は1core,2coreのみActiveなときのActiveなコアのクロック周波数、
赤い帯の下端は全コア使用した際のクロック周波数です)

型番が多く全ては載せられませんでしたが、Skylake世代のPlatinum/Goldシリーズに関しては、
E5-2600v4世代よりもクロック周波数が高めになっていて、スペック上のターボ性能が向上していることがわかります。
(ベースクロックとMin Turbo Frequencyの間がE5-2600v4世代よりも広い傾向)

特に6154,6134,6128,5122などは、1コアだけ使用している時も全コア使用している時も3.7GHzで動作する仕様になっていて
定格がこれでいいのでは?と思ってしまいます。

具体的なアプリケーションでの性能については別の機会に紹介したいと思いますが、Turboまわりのスペックを比較するだけでも
クロック周波数の性能向上が期待できますね。

Univa Grid Engine : GPGPUのリソース管理(RSMAP)

GPGPUのリソース管理について

CPUの場合、どのコアが使われるのかのスケジューリングはkernelによって行われるため
ジョブスケジューラーは使用コア数・空きコア数などの数を管理するだけでリソースが適切に配分されますが
GPGPUの場合は、ジョブやジョブスケジューラー側でその配分を行う必要があります。
そうしないと複数のジョブが重複して同じGPUで実行されてしまうケースを回避できません。

Univa Grid EngineのRSMAPというリソースタイプを使うと、各ホストのGPGPUの数(搭載GPU数と使用中のGPU数)の管理だけでなく、
各GPGPUに付けられたIDも含めた数の管理が可能となるため、各GPGPUに適切にジョブを振り分けることができます。

demo script

  • 1ジョブあたりGPUを1つ使用するジョブです。”-l gpu=1″
  • マシンには2枚のGPGPUが搭載されています。
  • IDは、SGE_HGR_[リソース名]の変数として出力されますので、アプリケーション側が要求するデバイス指定の書式に合わせる必要があります。
#!/bin/sh
#$ -N TEST_GPU
#$ -l gpu=1

if [ ${SGE_HGR_gpu} = "0" ]; then
GPU="--gpu 0"
fi

if [ ${SGE_HGR_gpu} = "1" ]; then
GPU="--gpu 1"
fi

time python chainer-2.0.2/examples/mnist/train_mnist.py ${GPU} -o out/out_`date +%y%m%d-%H%M%S-%N`

RSMAPが無い場合の挙動

  • ジョブ投入後の状態は下記のようになっています。
  • 下記例では、数の管理はできているため3つ目以降のジョブは待ち状態(qw)となっていますが
    nvidia-smiで確認するとジョブは2つともID:1のGPUに投入されてID:0のGPUが使われていない状態です。
$ qstat
job-ID prior name user state submit/start at queue jclass slots ja-task-ID
------------------------------------------------------------------------------------------------------------------------------------------------
5123 0.50617 TEST_GPU beowulf r 08/02/2017 22:37:06 node.q@demo01 1
5124 0.50617 TEST_GPU beowulf r 08/02/2017 22:37:07 node.q@demo01 1
5125 0.50617 TEST_GPU beowulf qw 08/02/2017 22:37:33 1
5126 0.50617 TEST_GPU beowulf qw 08/02/2017 22:37:34

$ qstat -j 5123 | grep resource
hard resource_list: gpu=1

$ nvidia-smi pmon -o T
#Time gpu pid type sm mem enc dec command
#HH:MM:SS Idx # C/G % % % % name
22:37:45 0 - - - - - - -
22:37:45 1 40725 C 14 4 0 0 python
22:37:45 1 40736 C 58 18 0 0 python
22:37:46 0 - - - - - - -
22:37:46 1 40725 C 36 11 0 0 python
22:37:46 1 40736 C 36 11 0 0 python

RSMAPを用いた場合の挙動

  • 投入スクリプトは上と同じものを使用
  • qstat -j の出力に上の例では無かった”resource_map”行が表示されています。
    ホスト名(demo01)の後ろの(0)と(1) がGrid Engine側で認識しているGPUリソースのIDです。
  • 5159のジョブでID:0のGPGPUが使用されているため、5160ではID:1が使用されて重複なく振り分けられていることがわかります。
  • nvidia-smiの出力を見てもそれぞれのGPUにジョブが振り分けられていることがわかります。
$ qstat -j 5159 |grep resource
hard resource_list: gpu=1
resource map 1: gpu=demo01=(0)
$ qstat -j 5160 |grep resource
hard resource_list: gpu=1
resource map 1: gpu=demo01=(1)

$ nvidia-smi pmon -o T
#Time gpu pid type sm mem enc dec command
#HH:MM:SS Idx # C/G % % % % name
23:10:30 0 46000 C 58 20 0 0 python
23:10:30 1 46117 C 74 24 0 0 python
23:10:31 0 46000 C 77 28 0 0 python
23:10:31 1 46117 C 54 16 0 0 python
23:10:32 0 46000 C 55 19 0 0 python
23:10:32 1 46117 C 56 18 0 0 python

RSMAPその他の活用法

RSMAPはGPGPUやXeon Phiなどのコプロセッサ向けに開発されたものなのでそれらのデバイスを使う際には必要な機能となりますが、
RSMAP自体は、1台のホスト内に搭載されている複数のデバイスそれぞれにIDを付けてリソース管理が行えるというものなので
それ以外にも使いみちがありそうです。

例えば、Dual CPUのサーバーに2本のNVMe SSDが搭載されていて、それぞれがそれぞれのCPUのPCIeバス上にあるという構成の場合、
コアバインディングと組み合わせて近い方のBUSのNVMeをスクラッチ領域として使うことができ、アプリケーションによっては効果がありそうです。

tuned: tuning daemon

tuned について

tunedは、cpu,disk,kernelなどに関する複数のパラメーターを一括して一つのプロファイルとして保存し、
コマンド一発で設定・切り替えを行うことができるツールです。

CentOS7の場合は、tuned のパッケージにはあらかじめいくつかのプロファイルが用意されていて
その中で変更するだけでも性能の違いを実感できますし、その他にカスタムのプロファイルも作成することができます。

デフォルトで用意されているプロファイル

  • デフォルトで用意されているプロファイルには以下の9つがあります。
    また、tuned-profile-xxx といったパッケージ名で用意されたものをインストールすると
    RHELのAtomic Host、Laptop、Oracleといった環境向けの他、spindown-diskといったディスクの省電力向けの
    プロファイルも追加されます。
# tuned-adm list
Available profiles:
- balanced                    - General non-specialized tuned profile
- desktop                     - Optmize for the desktop use-case
- latency-performance         - Optimize for deterministic performance at the cost of increased power consumption
- network-latency             - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance
- network-throughput          - Optimize for streaming network throughput.  Generally only necessary on older CPUs or 40G+ networks.
- powersave                   - Optimize for low power consumption
- throughput-performance      - Broadly applicable tuning that provides excellent performance across a variety of common server workloads.  This is the default profile for RHEL7.
- virtual-guest               - Optimize for running inside a virtual guest.
- virtual-host                - Optimize for running KVM guests

設定方法

manページを見ると、throughput-performanceがRHEL7のデフォルトである旨のことが書かれていますが
実際にはbalancedとなっているケースが多いです。

$ tuned-adm active :  現在有効となっているプロファイルが表示されます。

$ tuned-adm profile balanced : 左のケースでは"balanced"というプロファイルに設定されます。
このコマンドを実行するだけで、OSやサービスの再起動の必要なく、すぐに設定が適用されます。

実際に変更されているパラメーター

パッケージに含まれているプロファイルについては、/usr/lib/tuned/[プロファイル名]/tuned.conf に
実際に変更されているパラメーターとその設定値が記載されています。

下記はthroughput-performanceのtuned.confで
cpupower, x86_energy_perf_policyで設定されるようなCPUの電力管理系のプロファイル、
ディスクのread_ahead_kbのサイズ、kernelのパラメーターに関して記載されていることがわかります。

----
[main]
summary=Broadly applicable tuning that provides excellent performance across a variety of common server workloads.  This is the default profile for RHEL7.

[cpu]
governor=performance
energy_perf_bias=performance
min_perf_pct=100

[disk]
readahead=>4096

[sysctl]
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
vm.swappiness=10
----

性能の比較

結論から言えば、”throughput-performance” がたいていのケースではおすすめです。

ネットワーク、ファイルコピーの速度比較

  • InfiniBand : QDR
  • OS : CentOS7.2
  • Mode : Connected Mode
balanced network-throughput throughput-performance
Netperfでの速度比較 21,656 Mbps 23,909 Mbps 25,528 Mbps
ddで作成した10GBのファイルのコピー時間(NFS越し) 0m12.873s 0m8.616s 0m8.624s

fioでのIOPS測定

  • Device /dev/md0(NVMe x4)
  • Filesystem:XFS
  • Queue Depth : 32
  • numjobs: 1
Random Read(4K) Random Write(4K)
balanced 200569 IOPS 227951 IOPS
latency-performance 268315 IOPS 289342 IOPS

bowtie2 の実行時間比較

  • bowtie2 : 2.3.1
  • index : hg19
  • fastq : SRR067579_1.fastq, SRR067579_2.fastq,
threads throughput-performance
(intel_pstate)
balanced
(intel_pstate)
throughput-performance
(acpi_cpufreq)
8 2479s 2477s 2507s
16 1276s 1290s 1279s
32 679s 690s 676s
56 545s 649s 616s

NAMDの性能比較

  • NAMD : Nightly Build(2017-06-30)
  • data : stmv.namd
  • OS : CentOS 7.3
threads throughput-performance(ns/day) balanced(ns/day)
4 0.0578 0.0555
8 0.1083 0.1077
16 0.2094 0.2086
32 0.4028 0.3931
上の例では、ベンチマークツールで1-4割、アプリケーションレベルで数%から2割程度の性能差が出ています。

もちろん、常時"throughput-performance"に設定しておいても良いのですが、
コマンド一発でプロファイルの切り替えができるという特性を考えると
ジョブ実行前に"throughput-performance"に切り替え、ジョブ完了後に省電力モードに戻す
といった使い方(ジョブスケジューラーへのジョブ投入スクリプト内に追記)はシンプルで
効果もあるかもしれません。(省電力の効果のほどはいずれ確認したいと思いますが)

また、仮にアプリケーションやデータの種類などそれぞれに最適のプロファイルを用意できたとすれば
ジョブスケジューラー側の機能を使ってジョブの名前やその他の値から自動的にプロファイルを選択、
設定して実行させるいった使い方もできるのではないかと思います。

Univa Grid Engineの紹介

TakeruではこれまでデフォルトのジョブスケジューラーとしてOpen SourceのOpen Grid Schedulerを使ってきましたが、昨年からは同じくGrid Engine系ではあるものの有償版のUniva Grid Engine(以下、UGE)をデフォルトのジョブスケジューラーとしています。

主な背景として以下の2つの理由があります。

  • UGEがGPGPUやDockerに対応している点
  • UGEがOpen Grid Schedulerと同じコマンド体系である点

Open Grid SchedulerでもGPGPUのジョブやDockerのジョブを投入・管理することは可能です。
ただ、Open Grid Scheduler自体は2012年から開発が止まっているため、これらのテクノロジーに適切に対応できておらず、余分に手間がかかったり、不十分なリソース配分をしてしまう可能性があります。

今後の投稿では、Univa Grid Engineの以下のような機能について紹介をしていきたいと思います。

  • GPGPU/Xeon Phiなどのコプロセッサー対応
  • Docker 対応
  • JSV(Job Submission Verifier)
  • Job Class
  • その他