生まれてこの方GPUというものにふれてこず印象はなんか計算が早くなるんでしょみたいな解釈しかしてませんでした。
とはいえさわってみないと分からないので今回は実際にさわってみてその効果のほどを確認することにしました。
まずGPUインスタンスを搭載したマシンをどう調達するかについてですが、今年のAWSのEC2で5月に東京リージョンへGPUを搭載したP2インスタンスがきたのでそれを使用することにしました。
なんと最大でGPUが16搭載したインスタンスが用意できると言う….凄い世界だ…
Amazon EC2 P2 Instances are now available in Asia Pacific (Tokyo) and Asia Pacific (Sydney) Regions
今回やること
Chainerを使用してその中でサンプルとしてMulti-Layer Perceptron for MNIST Classificationを使ってGPUを使ってない場合と使った場合を比較する。
動作環境
- インスタンスタイプ: p2.xlarge
- AMI: NVIDIA CUDA Toolkit 7.5 on Amazon Linux
- 今回はGPUを使用するためのドライバとかをいれる時間を省くためにそれらが入ったAMIを使用しました。
GPUの情報はnvidia-smi
というコマンドで確認できます。
$ nvidia-smi Sat Jul 29 02:13:54 2017 +------------------------------------------------------+ | NVIDIA-SMI 352.99 Driver Version: 352.99 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 Tesla K80 On | 0000:00:1E.0 Off | 0 | | N/A 42C P8 25W / 149W | 55MiB / 11519MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
検証準備
ドライバなどは入っているので、後はChainerを使用するのでPythonとChainerを入れるだけです。
(とその時は思ってた)
$ python --version
Python 3.6.2
ChainerのインストールとGPUを使用する時に必要なcupyもいれます。
# chainerは2.0.1, cupyは1.0.1が入りました
$ pip install chainer cupy
検証
まずはGPUを使用していないものから検証しました。
GPUを使用しない
$ python chainer-2.0.1/examples/mnist/train_mnist.py GPU: -1 # unit: 1000 # Minibatch-size: 100 # epoch: 20 epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time 1 0.192339 0.11301 0.941083 0.9648 17.211 2 0.0733699 0.0710786 0.977117 0.9774 36.1076 3 0.0475365 0.0789325 0.98475 0.9769 55.7616 4 0.0348562 0.0745593 0.98885 0.9787 75.8827 5 0.0277311 0.102257 0.9907 0.9724 96.4579 6 0.0241048 0.0879807 0.992483 0.9779 117.416 7 0.0219072 0.0710079 0.992833 0.9818 138.455 8 0.017988 0.0681981 0.993783 0.982 160.079 9 0.0172883 0.0842126 0.994467 0.9804 181.897 10 0.0123837 0.0860014 0.99585 0.9809 204.486 11 0.0167936 0.081263 0.9943 0.9822 227.67 12 0.0123561 0.0797155 0.996233 0.9839 251.241 13 0.0113728 0.100481 0.9964 0.9814 275.906 14 0.0119349 0.120433 0.996317 0.9799 301.254 15 0.00982063 0.13196 0.996917 0.9787 327.206 16 0.0106473 0.119098 0.99675 0.9797 353.597 17 0.0108263 0.103797 0.997133 0.9806 380.39 18 0.00896206 0.0968817 0.99725 0.9837 408.096 19 0.00930343 0.100058 0.9972 0.9808 436.251 20 0.00915619 0.130336 0.997133 0.9789 465.153
GPUを使用する
続いてがGPUを使用した時で--gpu [GPU ID]
オプションを指定するだけです。
GPU IDは先程nvidia-smi
コメンドで確認した際のGPU
というカラムの値の数値を使用します。
今回はIDが0なので--gpu 0
と指定して実行します。
ただこの時1つ問題がありました。
まずは No such file or directory: 'nvcc'
と出てそもそも実行されない。
これは単純に/usr/local/cuda/bin/nvcc
にパスが通ってないだけなのでexport PAHT=$PATH:/usr/local/cuda/bin
とパスを通してあげたらいけました。
これで実行できるようになったのですが、次は cuDNN is not enabled.
が出てWARNINGが出たのですが、この解決が少し厄介でした。
ソース自体はここから落としてくるのですが、まずユーザー登録をしないといけないです。
ユーザー登録をして先程のリンクを開くとcuDNNがバージョンとプラットフォームごとに提供されているので、今回はcuDNN v6.0 (April 27, 2017), for CUDA 7.5
のcuDNN v6.0 Library for Linux
を使用しました。
今回は一度ローカルにファイルを落としてscpでインスタンスにアップロードしました。
ここから少しはまったのですが、どうやらchainerとかcupyを再インストールする必要があり、再インストールした後に無事動きました。
動いた結果が下記になります。
$ python chainer-2.0.1/examples/mnist/train_mnist.py --gpu 0 GPU: 0 # unit: 1000 # Minibatch-size: 100 # epoch: 20 epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time 1 0.191885 0.118277 0.941883 0.9621 3.53774 2 0.0720202 0.081614 0.977799 0.9763 6.58676 3 0.0503432 0.0710561 0.984349 0.9785 9.64134 4 0.0356193 0.0623461 0.988699 0.9829 12.7405 5 0.0277371 0.082205 0.990815 0.9782 15.8074 6 0.0252137 0.0703964 0.992082 0.9842 18.9066 7 0.018074 0.0871086 0.994048 0.9794 21.9982 8 0.0193796 0.0948052 0.993699 0.979 25.0666 9 0.0176497 0.0816459 0.994315 0.9799 28.1616 10 0.0145537 0.105795 0.995649 0.975 31.252 11 0.0136489 0.0991074 0.995982 0.9787 34.3346 12 0.0139412 0.0984373 0.995632 0.9811 37.4096 13 0.0116104 0.104966 0.996449 0.981 40.4892 14 0.0111883 0.0863221 0.996499 0.9835 43.5692 15 0.011418 0.0900974 0.996432 0.9827 46.6455 16 0.00842275 0.112952 0.997332 0.9796 49.7249 17 0.00932168 0.0908319 0.997299 0.9827 52.8396 18 0.0130952 0.106359 0.996282 0.9814 55.9584 19 0.00778945 0.120892 0.997666 0.9789 59.0483 20 0.00633532 0.106582 0.998116 0.9836 62.1564
結果
最後に
今回はとりあえず動かしてみただけなのでソースとか動作的な動きまでは追ってないですが、
コードを見る感じだとわりと簡単にかけそう?な感じ。