cloudpackシンジです。

EC2にもGPUが搭載されているインスタンスがあるけど、科学技術計算用途に使えるのか試してみました。

結論から書くと、Marketplaceに用意されているNVIDIAのAMIは古くてなんとなく嫌なので、全部セットアップしてサンプル流してって軽く考えていたら大変だった。。。

結果的にはGPU1ノードで単精度1TFLOPSは出せたのでなかなか良いのではないのでしょうか?

まずEC2に用意されているGPUインスタンスは2種類しかありません。今回はg2.2xlargeを利用します。

ec2-gpu-1tflops-benchmark_01

Marketplaceからお手軽に試したい人は以下のリンクからどうぞ。
https://aws.amazon.com/marketplace/search/results/?page=1&searchTerms=GPU

いい感じのAMIが無い

美しいCUDA環境を作りたいが為にCentOS6.5を使いたいわけですが、先月まではあったはずのHVMインスタンスが無くなくなっている上に、「普通のCentOSから自分でHVM作るのはしんどいからやめた方がいいですよ」という神の声もあったので、やむを得ず公式のRHEL6.5 HVMを選択します。必ずHVMを選択してください。でないとGPUが使えません。

ec2-gpu-1tflops-benchmark_02

TokyoリージョンではGPUインスタンスが使えないので、N. Virginiaリージョンで立てます。

ハマったポイント
なんだか分からないけどこのAMIはrootのボリュームが拡張できないので、とりあえず100GBのEBSをアタッチしました(20GBもあれば十分)。でないと、CUDAインストールで空き容量が足りません的なメッセージと共に悲しみにふけることになります。これは後からでも追加可能。

SSHでログインしてセットアップ開始

起動後はとりあえずおまじないを少々

[ec2-user@~]$ sudo su -
[root@~]$ yum groupinstall "Development Tools"
[root@~]$ yum update

ちなみに以下コマンドでGPUが本当にあるのか確認できます。

[root@~]$ lspci | grep -i nVidia
00:03.0 VGA compatible controller: NVIDIA Corporation GK104GL [GRID K520] (rev a10)

rpmforgeのリポジトリを追加する

[root@~]$ yum install http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm

ドライバがインストールできるようにgrubを編集

OSが始めから持っているドライバでGPUが動作している状態なので、OS起動時にNVIDIAドライバを使わないようにgrubを編集します。

カーネルの起動オプションに rdblacklist=nouveau を追加して再起動するだけ

[root@~]$ vim /etc/grub.conf

kernel /boot/ほにゃららの行の最後に追加すればよいです。保存したら必ずrebootしましょう。

最新のNVIDIAドライバをインストールする

NVIDIAのWebからドライバをダウンロードしますが、方法は何でも良いです。今回はwgetで落としました。落としたら権限を与えて実行します。

[root@~]$ wget http://jp.download.nvidia.com/XFree86/Linux-x86_64/331.49/NVIDIA-Linux-x86_64-331.49.run
[root@~]$ chmod +x NVIDIA-Linux-x86_64-331.49.run
[root@~]$ ./NVIDIA-Linux-x86_64-331.49.run

規約読んでねページはxキー連打でスイスイ進みます。ドライバインストール時にいろいろ聞かれますが、基本的にはデフォルトインストールで良いです。途中で32bitOpenGLあれこれ入れますか?と聞かれますが、習慣でインストールしました。

CUDAのインストール先EBSを用意する

rootボリュームはパンパンになる上にインストールは失敗するし、拡張にチャレンジするものの何故かうまくいかず挫折したので、別にEBSを用意しておいてそこにCUDAをインストールします。

EBSアタッチの詳細は検索すると沢山でてくるのでそれらを参考してほしいですが、ポイントはマウントポイントのパスを以下のようにしましょう。SELinuxも無効にします。

/usr/local/cuda-5.5
 [root@~]$  fdisk /dev/xvdb
 [root@~]$  mkfs.ext4 /dev/xvdb1
 [root@~]$  mkdir /usr/local/cuda-5.5
 [root@~]$  mount /dev/xvdb1 /usr/local/cuda-5.5
 [root@~]$  df -h
 [root@~]$  umount /usr/local/cuda-5.5/
 [root@~]$  blkid /dev/xvdb1
 [root@~]$  vim /etc/fstab
 [root@~]$  mount -av -t ext4
 [root@~]$  getenforce
 [root@~]$  vim /etc/selinux/config
 [root@~]$  setenforce 0
 [root@~]$  mount -av -t ext4

CUDA5.5をRPMインストール

最近はRPMで配布されていてなんだか便利

[root@~]$ yum install http://developer.download.nvidia.com/compute/cuda/repos/rhel6/x86_64/cuda-repo-rhel6-5.5-0.x86_64.rpm
[root@~]$ yum clean expire-cache
[root@~]$ yum install cuda

パスを通す

CUDAのユーティリティなどなどが使えるようにパスを通します。方法は何でも良い

[root@~]$ cd
[root@~]$ vim .bashrc
export PATH=/usr/local/cuda-5.5/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-5.5/lib64:/lib:$LD_LIBRARY_PATH
:wq

試しにGPUの状態を見てみる

[root@~]$ nvidia-smi -l
Fri Mar 7 18:47:22 2014
+------------------------------------------------------+
| NVIDIA-SMI 5.319.37   Driver Version: 319.37         |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GRID K520           Off  | 0000:00:03.0     Off |                  N/A |
| N/A   45C    P8    17W / 125W |        9MB /  4095MB |      0%      Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Compute processes:                                               GPU Memory |
|  GPU       PID  Process name                                     Usage      |
|=============================================================================|
|  No running compute processes found                                         |
+-----------------------------------------------------------------------------+

サンプルプログラムでベンチマークを取る

今回は、粒子法シミュレーション記述言語による多体問題を投げます、というと聞こえはそれっぽいですが、要するにnBodyをコンパイルして実行します。

[root@~]$ cd /usr/local/cuda-5.5/samples/5_Simulations/nbody/
[root@~]$ make
/usr/local/cuda-5.5/bin/nvcc -ccbin g++ -I../../common/inc  -m64    -gencode arch=compute_10,code=sm_10 -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=\"sm_35,compute_35\" -o nbody.o -c nbody.cpp
/usr/local/cuda-5.5/bin/nvcc -ccbin g++ -I../../common/inc  -m64    -gencode arch=compute_10,code=sm_10 -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=\"sm_35,compute_35\" -o bodysystemcuda.o -c bodysystemcuda.cu
ptxas /tmp/tmpxft_00000e5b_00000000-14_bodysystemcuda.compute_10.ptx, line 2565; warning : Double is not supported. Demoting to float
/usr/local/cuda-5.5/bin/nvcc -ccbin g++ -I../../common/inc  -m64    -gencode arch=compute_10,code=sm_10 -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=\"sm_35,compute_35\" -o render_particles.o -c render_particles.cpp
/usr/local/cuda-5.5/bin/nvcc -ccbin g++   -m64        -o nbody nbody.o bodysystemcuda.o render_particles.o  -L../../common/lib/linux/x86_64  -lGL -lGLU -lX11 -lXi -lXmu -lglut -lGLEW -lcufft
mkdir -p ../../bin/x86_64/linux/release
cp nbody ../../bin/x86_64/linux/release

出来ました。指示通り実行ファイルのある場所に移動します

[root@~]$ cd ../../bin/x86_64/linux/release/

nbodyにbenchmarkオプションと問題数を渡せば実行できますが、今回は連続して問題を投げたときFLOPSの値が安定しているかも含めて見たかったので、簡単なシェルスクリプトを書いて実行し、その裏でnvidia-smi -lも見つつGPUの頑張り具合を観察してみます

nbody.shとして以下のようにしました

#!/bin/bash
NDEV=`nvidia-smi -q | grep -c "Product Name"`
sleep 3
mkdir -p log
echo "nbody start"
while :
do
./nbody -benchmark -numbodies=${NDEV}00000 -numdevices=${NDEV} >> log/nbody.log
done
[root@~]$ sh nbody.sh

もう1つ端末を開いて、状況を見てみます

[root@~]$ nvidia-smi -l
+-----------------------------------------------------------------------------+
| Compute processes:                                               GPU Memory |
|  GPU       PID  Process name                                     Usage      |
|=============================================================================|
|  No running compute processes found                                         |
+-----------------------------------------------------------------------------+
Fri Mar  7 19:04:49 2014
+------------------------------------------------------+
| NVIDIA-SMI 5.319.37   Driver Version: 319.37         |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GRID K520           Off  | 0000:00:03.0     Off |                  N/A |
| N/A   67C    P0   102W / 125W |       65MB /  4095MB |     99%      Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Compute processes:                                               GPU Memory |
|  GPU       PID  Process name                                     Usage      |
|=============================================================================|
|    0      3892  ./nbody                                               54MB  |
+-----------------------------------------------------------------------------+

GPU温度も上がり、タスクが投げられ、消費電力も上がってるのが分かります。

計算結果はlogに出力されているので確認してみます。

[root@~]$ cat log/nbody.log
number of CUDA devices  = 1
> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
GPU Device 0: "GRID K520" with compute capability 3.0

> Compute 3.0 CUDA device: [GRID K520]
number of bodies = 100000
100000 bodies, total time for 10 iterations: 1963.470 ms
= 50.930 billion interactions per second
= 1018.605 single-precision GFLOP/s at 20 flops per interaction

単精度ですが1TFLOPS程度は安定して出ていることが分かりました 。

今回はEC2の初期設定(時刻設定など)を省いて、とりあえずGPUを使ってみようと言うことと、綺麗なOSかつ最新のドライバで計算させたいということをやってみました。並列計算も試せてないし、まだまだ美しいHPC-AMIを作るという意味では詰められる余地が大いにありました。

元記事は、こちら