こんにちは、ニューラルネット老人こと糟谷勇児です。
以前化石集めが趣味という話を書きましたが、最近はコロナのせいかあまり新しい化石が流通せず、ちょっと退屈です。
そこでフローライトやラブラドライトなどのいわゆる天然石を集めています。
それはそうと前回の予告通り、今回はGPGPUをやっていこうと思います。
前回はこちら。
buildersbox.corp-sansan.com
GPGPUは速いのか
GPGPU(General-purpose computing on graphics processing units)はGPUをグラフィックの計算以外に使う技術です。
AlexNetでマルチGPUが使われ、論文にはマルチGPUがなければ、これほど試行錯誤できず、AlexNetを作ることは難しかっただろうと書かれていたことが印象に残っています。
今やディープラーニング=GPUという感じさえありますね。
しかし、本当にGPUで速くなるのでしょうか。
ちょっと調べてみるとこちらの記事でCore i7(Broadwell)が560ギガFLOPS、Tesla P4は5.5テラFLOPSとあります。
FLOPSは浮動小数点演算を1秒間に何回できるかという論理値です。
とするとカタログスペックではその差はおよそ100倍ということになります。
とはいえ、メモリ転送の時間などオーバーヘッドもあるので実際どこまで速くなるのかはよくわからないところです。
いくつかのブログで検証されていますが、実際20倍ぐらい速いという話もあります。
Tensorflowを使ったDeep LearningにおけるGPU性能調査 | Kabuku Developers Blog
さて、本当なのか、謎の半導体メーカーの陰謀なのか、実際検証していこうと思います。
環境構築
今回はGCPで環境を作って検証していきます。
最終的にはC#で自分で作ろうと思うのでサーバーはWindowsを選択しました。
やっぱりGUIが欲しい!GoogleCloudPlatformでWindows GPU環境 - ひつじ工房
こちらのブログを参考に環境構築しました。
やってみて思ったのは、ハードディスクが100GBは最低欲しいということです。
CUDAのインストーラーが2GBあり、それを展開すると16GBなどになります。もともとOSが使っている領域もありますし、さらにここにTensorflowやPyTorchの対応バージョンを入れるのでそれらも数GBの空き容量を必要とします。
そうすると最低の50GBでは結構かつかつで、インストール後にインストーラーを消すなどしながら節約していかなければいけません。まあストレージは後から増やせるので大丈夫ですが。
ストレージの増やし方はこちら。
ディスクの作成とアタッチ | Compute Engine ドキュメント | Google Cloud
環境構築はTensorFlow-GPUでGPUが認識されず、dllの名前を書き換えたら直ったということはありましたが、結構同じところで詰まっている人は多いのでstack overflowなどを見ながら試行錯誤すれば何とかなるかなと思います。
なお、今回はGPUはT4一つ、CPUはvCPU16コアで実験します。
なぜ16コアかというとT4 + vCPU4コアの価格がだいたいvCPU 16と一致するので金額で公平な勝負になると考えたからです(インスタンスは標準のN1マシン)。
T4は時間当たり$0.55、vCPU 4コアのマシンは$0.19で足すと$0.84、vCPU 16コアは$0.76になります。
GCPの料金は複雑ですし、CPU優先のインスタンスにすればもう少し16コアでも安くなるので完全に公平ではないですが、
まあ大体合っているのかなと思います。
料金表はこちら。
すべての料金 | Compute Engine ドキュメント | Google Cloud
実験
では実際やっていきましょう。
今回はPyTorchで行きます。
こちらの記事を参考にコンボリューショナルネットを構築してみます。
【前編】PyTorchでCIFAR-10をCNNに学習させる【PyTorch基礎】 - 株式会社ライトコード
こちらの記事でLeNetとして紹介されているネットワークを実装してみます。
(実際には活性化関数など、一部元論文と異なります)
と記載されているようにほぼほぼVGGなネットワークですが、今回はそのあたりはどうでもいいので学習にかかる時間を見ていきます。
まずはそのまま学習してみます。まずは10エポックでいきます。
あれ、あまり変わらないですね。ネットワークがシンプルなものだと、オーバーヘッドもあるのでGPUの性能を発揮できないのでしょう。
そこで、あえてネットワークを複雑にしていきます。
100チャンネルのコンボリューション層を1層ずつ追加していきます。
ネットワークが複雑になって計測に時間がかかるのでここからは3エポックで評価します。
だいたい15倍の差が出ました。20倍という他のブログの話とかなり近い値です。
ではCPUのほうをもう少し詳しく見ていきましょう。
CPUをvCPU1~32まで変えていきます。
並列化効率がかなり低いのが気になります。
実際vCPUが4以上では60%のCPUしか使用されていません。
どなたか、CPUを全部使うように設定する方法をご存じの方がいましたら教えてください。
おそらく、並列化の仕方がデータ並列化ではなく、数値計算レベルの並列化になっているのかなと思います。
そのほうがメモリ面などで無難ですしね。
とはいえ、仮にCPUを並列化効率100%で使えたとしても、vCPU16で153秒かかるので、34秒のGPUと比較すると5倍程度の速度差はあります。
5倍差があるとCPU 16コアで5日学習にかかるネットワークがあったとしても1日で学習が終わるので一週間でできる試行錯誤の回数は相当増えます。
確かにこれはすごい。
また、データ並列化をするにしてもバッチサイズ以上コア数を増やしても並列化効率が上がらないので、天井はあります。バッチサイズを512にしていてもオーバーヘッドを考えると128コアぐらいで限界が来そうです。
一方でGPUはまだ並列化する余地を残していますし、より高性能なGPUもあります。まだあと2回変身を残しているフリーザぐらいポテンシャルを感じますね。
まとめと次回
ある程度簡単なニューラルネットにおいてはGPUとCPUであまり速度は変わらないことが分かりました。
一方、複雑なニューラルネットを学習する際はGPUを使うと同価格帯のCPUと比較して、PyTorchで15倍以上速くなり、もし理想的な並列化が実現できたとしても5倍速くなることが分かりました。
俄然GPGPUを勉強したくなってきました。
次回は自分でGPGPUをプログラミングするところにトライしてみようかと思います。
ところでディープラーニングはコンピューターサイエンスを網羅的に学ぶ教材としては最適かもしれませんね。
浮動小数点数の単精度/倍精度、SIMD、並列化、GPGPUなど基本的な知識が必要になってくるので。