前に、お手元のマシンとスパコンを比較する方法と言うなんともアホっぽい記事を書いた。更に思った。最近は、GPUの性能が上がっており、GPUを使って演算することが流行っている。LINPACKベンチマークを、aws g2インスタンス(CUDA)で動かしてみたらどうだろう?
スパコンは、メモリもストレージもネットワーク性能も段違いに高性能なので、真に受けないように。
ベンチマークの内容を詳しく分かっているわけではないので、間違っているかも知れない。
AWS g2.2xlargeでLINPACK ベンチマークを動かす。
という訳で、AWSで最もCPUが早そうなマシンを使って、スパコンと性能の比較をしてみる。
今回使用したマシンはこちら
g2.2xlarge
モデル | vCPU | メモリ | GPU |
---|---|---|---|
g2.2xlarge | 8core | 15GB | 1 |
- 1,536 CUDA コアと 4GB のビデオメモリを搭載した高パフォーマンスの NVIDIA GPU
LINPACKベンチマーク環境の構築
CUDA実行環境の構築は結構大変だ。
linpackプログラムの準備
https://devtalk.nvidia.com/default/topic/819284/linpack-benchmark-for-cuda/
こちらを参考。CUDA Registered Developer Programというのに入って、上のリンク
https://developer.nvidia.com/rdp/assets/cuda-accelerated-linpack-linux64
こちらから、hpl-2.0_FERMI_v15.tgz
を手に入れる。
インスタンス立ち上げ
nvidiaが用意しているCUDAドライバーが事前に入っている環境を利用する。
AWS marketplaceで「grid」で検索すると出てくる
Amazon Linux AMI with NVIDIA GRID GPU Driverを利用する。
初期設定
次のものを入れる
sudo yum groupinstall -y "Development Tools"
sudo yum install -y emacs
sudo yum install -y tmux
sudo yum install -y openmpi openmpi-devel
sudo ln -s /opt/nvidia/cuda /usr/local/cuda
INTEL MKLを利用する。
次のページからインテルのMath Libraryを取得する。ついでに利用するシリアルナンバーを用意する。
https://software.intel.com/en-us/qualify-for-free-software
登録すると、シリアルナンバーを送ってくれるのでそれを用意する。
l_mkl_11.3.0.109.tgz
などが、手に入るので、展開して install.sh
を実行する。対話的なやり取りを(その際シリアルナンバーを打ち込む)する。シリアルナンバーを打ち込む以外は、エンターを押せばOK.展開時に、silent.cfg
が展開されるのでそちらを設定してもよい。やり方はこちら。
デフォルトで、/opt/intel
以下にインストールされる。
LINPACKベンチマークの作成
展開
どこでも良いが、/home/ec2-user/prog
以下に展開する(以下、それを前提とする)。
[ec2-user@ip-10-125-132-16 hpl-2.0_FERMI_v15]$ ls
bin COPYRIGHT HISTORY INSTALL Make.CUDA Makefile Make.top README src TODO www
BUGS CUDA_LINPACK_README.txt include lib Make.CUDA~ makes man setup testing TUNING
環境設定の作成
~/.bashrcに以下を追加
# User specific aliases and functions
export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/opt/intel/compilers_and_libraries/linux/lib/intel64:/home/ec2-user/prog/hpl-2.0_FERMI_v15/src/cuda:/usr/lib64/openmpi/lib
export PATH=/usr/lib64/openmpi/bin:$PATH
source ~/.bashrc
Make.CUDAの編集
殆どはMake.CUDAの編集をすれば良い
サンプルはこちら
上を編集して
make
を実行すれば、bin/CUDA
にxhpl
が出来上がる.lddでsoへのパスが通っているか確認してください。libdgemm.so.1
とlibmpi.so.1
のパスが通ってなかった。
run_linpackの編集
bin/CUDA以下にあるrun_linpackの編集を行なう
#location of HPL
HPL_DIR=/home/ec2-user/prog/hpl-2.0_FERMI_v15
と
CPU_CORES_PER_GPU=8
にする。
HPL.datの編集
ベンチマークはHPL.datの編集を行なう。そのままでは動かない。PsとQsを1に指定する。
サンプルはこちらにある
2 # of problems sizes (N)
25000 30000 40000 50000 60000 39007 39000 20960 364160 359424 276480 138240 115200 23040 354432 236160 95040 9600 20737 16
129 16128 Ns
4 # of NBs
768 1024 1280 1536 640 768 896 960 1024 1152 1280 384 640 960 768 640 256 960 512 768 1152 NBs
上の2は、25000,30000までやるという意味っぽい
4は
768,1024,1280,1536
までやるという意味だ。
最適な場所を探すと、GFlopsの最適値がわかると思う。
LINPACKベンチ実行
mpirun -np 1 -host localhost ./run_linpack
と実行すれば、ベンチマークが走る
実行結果
================================================================================
T/V N NB P Q Time Gflops
--------------------------------------------------------------------------------
WR10L2L2 25000 1024 1 1 70.41 1.480e+02
--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)= 0.0053278 ...... PASSED
================================================================================
T/V N NB P Q Time Gflops
--------------------------------------------------------------------------------
WR10L2L2 30000 1024 1 1 117.29 1.535e+02
--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)= 0.0044912 ...... PASSED
================================================================================
長いので省略した。全部の結果はこちらのgistにある .
結果を見ると、150GFlops位になりそうだ。
ちなみに、その時にGPUの使用率はこんなもん。nvidea-smiで状態を把握する。
$nvidia-smi -q -d UTILIZATION -l
GPUを使っているようだ。
(倍精度の計算は)思ったより速くない
世の中はGPGPU花盛りだ。ドワンゴが、ディープラーニング用のGPUサーバファーム、紅莉栖を作るくらいだし、GPUで数TFlopsくらい行くのかなと思っていた。
しかし、linpackを実行してみると、 150GFlops位と、そこまで速くないという感触だ。理由は、今回使ったAWSのg2インスタンで採用しているGPUは単精度の演算は速いが、倍精度はそこまで速いわけではないと言うことだ。
例えば、wikipediaのFLOPSの項目から今回使用したGPU「kepler」を搭載しているGeForce GTX 680の項目を見てみよう。1536CUDAコアを搭載してる。
理論値で比較すると、単精度では、3090 GFLOPS 倍精度で129 GFLOPSと大体24倍程度違う。
これは、NVIDAのGPU戦略で、GPUで主に使う3Dグラフィックでは、倍精度(double)ではなく単精度(float)が主に使われ、そのため倍精度にはあまり注力せずその代わり単精度での性能を上げる(数TFLOPS出る)選択をしたということだ。最近にわかに注目を集めているデープラーニングも単精度を使うようだ。
そのため、倍精度でベンチマークを取るLINPACKではそこまで性能が上がらなかったということのようだ。
追記、nbodyで計算してみる。
LinpackではGPUのハードウェアの実効性能が出せなかったので、違うプログラムをGPUの実効性能が出せないか調べてみた。
CUDAサンプルのnbodyがflopsを計測出来るそうなので試してみた。
nbodyのプログラムに、
NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
と書いているように本当の所に計測には不適当であるのであまりまに受けないように。
NBodyはCUDAのサンプルに入っている。場所は
/usr/local/cuda-9.0/samples/5_Simulations/nbody
になる(うろ覚え)。
倍精度と単精度でFLopsを調べられるので、調査してみた。
理論値では、こちらのページにGRID K520のスペックが載っている。
モデル | FP32(TFLOPS) | FP64(TFLOPS) |
---|---|---|
GRID K520 | 2.458 * 2 | 0.096 * 2 |
とのことだ。倍精度の演算性能は、大体単精度の24分の一位らしい。
実際に調査してみた。
単精度
ubuntu@********:/usr/local/cuda/samples/bin/x86_64/linux/release$ ./nbody -benchmark -numbodies=2048000 -device=0
> Single precision floating point simulation
> 1 Devices used for simulation
gpuDeviceInit() CUDA Device [0]: "GRID K520
> Compute 3.0 CUDA device: [GRID K520]
number of bodies = 2048000
2048000 bodies, total time for 10 iterations: 683818.250 ms
= 61.337 billion interactions per second
= 1226.731 single-precision GFLOP/s at 20 flops per interaction
単精度で、1226.731 single-precision GFLOP/s が出た。
倍精度
ubuntu@********:/usr/local/cuda/samples/bin/x86_64/linux/release$ ./nbody -fp64 -benchmark -numbodies=2048000 -device=0
gpuDeviceInit() CUDA Device [0]: "GRID K520
> Compute 3.0 CUDA device: [GRID K520]
number of bodies = 2048000
2048000 bodies, total time for 10 iterations: 15422665.000 ms
= 2.720 billion interactions per second
= 81.587 double-precision GFLOP/s at 30 flops per interaction
倍精度で、81.587 double-precision GFLOP/s が出た。
単精度で、1226GFlops 倍精度で、81GFlopsくらい出た。
単精度は、倍精度の大体15倍位の性能がある。81GFlopsの24倍は、1944GFlopsなので、もう少し性能は出せるのだろう。
関連エントリー
AWSとスパコンを比較する方法-スパコン用ベンチマークソフトを動かしてみる
お手元のマシンとスパコンを比較する方法-スパコン用ベンチマークソフトを動かしてみる