「ディープ・ラーニングで映画から自転車を探す」ではGPUを活用すればより早く自転車を探すことができるようになるのではないか、という赤松正行の仮説があった。ディープ・ラーニングの推論では大量の行列と行列の計算が必要だが、こういった処理は、CPUよりもGPUの得意分野だからだ。
今回、筆者がビデオ・ゲーム用途として購入したGPUが手元にあり、GPUによる機械学習にも興味があったため、自転車探しの協力を申し出ることにした。
使用したGPUはNVIDIA Geforce RTX 2080 Tiだ。搭載されているCUDAコア(演算ユニット)の数は4352個。コア・クロックはリファレンスモデルよりも120MHzオーバー・クロックされた1665MHz. 消費電力は最大300Wというモンスターマシンだ。4K(3840 x 2048ピクセル)の環境で最高画質のビデオ・ゲームを楽しみたい、熱狂的なゲーマー向けのフラグシップ製品だ。
参考までに、現役世代のビデオ・ゲームをフルHD(1920 x 1080 ピクセル)の解像度でカジュアルに遊ぶことができる、NVIDIA Geforce GTX 1650のCUDAコア数は896, 消費電力は75W程度だ。
今回は赤松の取り組みと同じくkeras-yolo3を使用した。keras-yolo3はYOLOv3のオブジェクト検出モデル・手法をKerasで利用できるようにした実装だ。KerasはPythonで利用可能なニューラル・ネットワーク用のライブラリだ。Kerasが実際の処理に使用するバックエンドはいくつかあるが、デフォルトはGoogleが開発を進めている機械学習のライブラリであるTensorFlowだ。今回はGPUに対応したTensorFlow-GPUをバックエンドとして使用している。
前回は2分13秒の映像をCPUで処理し、42分11秒かかっていた。同じ映像をGPUで処理したところ、3分26秒で処理が完了した。おおよそ1/12の時間まで短縮できたことになる。これらの時間には学習モデルの読み込みやGPUの初期化など推論以外にかかる時間のオーバーヘッドも含まれている。
具体的なケースとして、映画一本分の処理時間も見てみよう。110分38秒の映像をGPUで実行した場合、160分30秒で処理が完了している。映像の長さの1.4倍の時間で処理が完了している。リアルタイム、すなわち映画の再生時間と同じ時間で処理を完了できるようになるまではもう一歩というところだ。
しかし、実際に処理を開始できるまでには依存関係の解決に悩まされることとなった。デバイス・ドライバ、CUDA Toolkit, TensorFlow-GPU, cuDNN, Python, OS, それぞれのバージョンがわずかに異なるだけでもGPUを認識しない、プログラムの非互換といった問題が発生した。参考までに、動作が確認できたバージョンは以下のとおりだ。
デバイス・ドライバ:440.33.11 CUDA Toolkit: 9.0 TensorFlow-GPU: 1.6.0 cuDNN: 7.0.5.15-1 Python: 3.5.2 OS: Ubuntu 16.04 LTS
Pythonのモジュール: $ pip3 freeze --all absl-py==0.9.0 apturl==0.5.2 astor==0.8.1 beautifulsoup4==4.4.1 bleach==1.5.0 blinker==1.3 Brlapi==0.6.4 chardet==2.3.0 checkbox-support==0.22 command-not-found==0.3 cryptography==1.2.3 cycler==0.10.0 defer==1.0.6 feedparser==5.1.3 gast==0.3.3 grpcio==1.27.1 guacamole==0.9.2 h5py==2.10.0 html5lib==0.9999999 httplib2==0.9.1 idna==2.0 Jinja2==2.8 Keras==2.1.5 kiwisolver==1.1.0 language-selector==0.1 louis==2.6.4 lxml==3.5.0 Mako==1.0.3 Markdown==3.2 MarkupSafe==0.23 matplotlib==3.0.3 numpy==1.18.1 oauthlib==1.0.3 onboard==1.2.0 opencv-python==4.2.0.32 padme==1.1.1 pexpect==4.0.1 Pillow==3.1.2 pip==20.0.2 plainbox==0.25 protobuf==3.11.3 ptyprocess==0.5 pyasn1==0.1.9 pycups==1.9.73 pycurl==7.43.0 pygobject==3.20.0 PyJWT==1.3.0 pyparsing==2.0.3 python-apt==1.1.0b1+ubuntu0.16.4.8 python-dateutil==2.8.1 python-debian==0.1.27 python-systemd==231 pyxdg==0.25 PyYAML==5.3 reportlab==3.3.0 requests==2.9.1 scipy==1.4.1 screen-resolution-extra==0.0.0 sessioninstaller==0.0.0 setuptools==39.1.0 six==1.14.0 ssh-import-id==5.5 system-service==0.3 tensorboard==1.6.0 tensorflow-gpu==1.6.0 termcolor==1.1.0 ubuntu-drivers-common==0.0.0 ufw==0.35 unattended-upgrades==0.1 unity-scope-calculator==0.1 unity-scope-chromiumbookmarks==0.1 unity-scope-colourlovers==0.1 unity-scope-devhelp==0.1 unity-scope-firefoxbookmarks==0.1 unity-scope-gdrive==0.7 unity-scope-manpages==0.1 unity-scope-openclipart==0.1 unity-scope-texdoc==0.1 unity-scope-tomboy==0.1 unity-scope-virtualbox==0.1 unity-scope-yelp==0.1 unity-scope-zotero==0.1 urllib3==1.13.1 usb-creator==0.3.0 Werkzeug==1.0.0 wheel==0.34.2 xdiagnose==3.8.4.1 xkit==0.0.0 XlsxWriter==0.7.3
このような事情から、今回の検証期間では最新バージョンのCUDA Toolkitを使用できなかった。GPUに搭載されている深層学習の推論に特化した演算ユニットであるTensor Coreも活用できていない状態だ。にもかかわらず、MacBook ProのCPUに対しては12倍速く、比較用に用意したデスクトップ向けのマルチコアCPUに対しても3.7倍早く処理を行うことができた。
これはいろいろな種類の命令を高速に処理するのが得意なCPUと、特定の命令を大量に並列処理するのが得意なGPUの特性の違いによるものだ。Tensor Coreの活用などチューニングを進めれば、さらに高速に処理する余地はあると言えるだろう。
今回はビデオ・ゲーム用途のGPUとディープ・ラーニングを組み合わせることで、より短時間で多数の映像から自転車を発見することに成功した。オブジェクト検出が表示されるプレビュー映像を眺めながら、ふと思い出したのは自動運転の技術だ。
以前はビデオ・ゲーム用GPUベンダーだったNVIDIAだが、現在はディープ・ラーニングを活用した自動運転のソリューションも展開している。プレス・リリースによると、歩行者、自転車など障害物の検知にも対応した、レベル2以上の自動運転を2020年にプロダクションレベルまで進める計画のようだ。これらの技術がより身近なものとなり、運転者の不注意による事故といった悲劇がなくなることを願う。
参考文献
Hisa Ando, GPUを支える技術 超並列ハードウェアの快進撃[技術基礎], 技術評論社,2017, p.16-17, p.248, p.258-259