今年Ridge-iとNHKアートが共同開発したカラー化ディープラーニングを取り入れた「戦後ゼロ年 東京ブラックホール 1945-1946」という番組が先月NHKで放映されました。こちらは数あるディープラーニング手法のうち、GANと言われる手法をベースとして、放送品質で使えるべくチューニングしております。実装にはChainerを用いております。
これまでオンプレミスで対応してきていましたが、番組の反響もよく、よりニーズが高まってきているにあたり、計算資源をどう効率的かつスケーラブルに用意していくかが課題となってきております。つまり、限られた時間内にどれだけ多くの動画を早く処理できるかがキーとなり、主に次の4つの方法で実現ができます:
①1本の動画を高容量のGPUメモリを使用し高速処理 (SLI*)
②複数本の動画を多数のGPUにそれぞれ割り当てる並列処理
③複数本の動画をデータパラレル手法で分散処理
④複数本の動画をモデルパラレル手法で分散処理
③や④を試すにはコードの改変や分散処理機能をサポートしているフレームワークの使用が必要となるため、今回この記事では①と②の手法を試すことにします。
この実証実験のために、連携しているMicrosoftのクラウドサービスであるAzureで当該アルゴリズムを実装します。実際にクラウド環境を使うための手順、オンプレミス環境との違いを検証することで、当該アルゴリズムを回す上での、クラウド環境の長所・短所などを見極め効率的な使い方を見極めたい、というのが本投稿の趣旨です。
*SLI (Scalable Link Interface):複数枚のグラフィックカードを並列動作させ、1つに出力を集約させる技術
ディスクレーマー
今回の検証結果はあくまで、下記のような条件により結果が変わる可能性があります。
・使用言語・ライブラリー・フレームワーク
・使用アルゴリズム
・構築環境 (マシンのスペックやOSなどを含め)
・検証時期 (2017年8月)
環境詳細
まずは、今回の検証に使う各環境間のスペック比較です。
|
オンプレミス
|
Microsoft Azure
NC6
|
Microsoft Azure
NC24
|
CPU
|
Intel i7-7700K 4.20GHz
/ 8 Core
|
Intel Xeon E5-2690 v3
/ 6 Core
|
Intel Xeon E5-2690 v3
/ 24 Core
|
GPU
|
GeForce GTX 1080 Ti * 1
|
Tesla K80 * 1
(½ Physical Card)
|
Tesla K80 * 4
(2 Physical Card)
|
Memory
|
15.6 GiB
|
56 GiB
|
224 GiB
|
OS
|
Ubuntu 16.04 LTS
|
Ubuntu Server 16.04 LTS
|
Ubuntu Server 16.04 LTS
|
CUDA
コア数
|
3584
|
2496
|
2496 * 4
|
CUDA
|
version 8.0
|
||
cuDNN
|
version 6.0
|
具体的なセットアップ手順
本格的な検証に入る前にAzure上での環境構築が必要となり、次の手順で行いました。
CPUコア数上限の増加
Azureにはデフォルトで最大CPUコア数の制限が設けられています。
トライアルアカウントだと最大4で、普通のサブスクリプションだと、最大値が20に設定してあり、上限を増やすためにはカスタマーサポートに連絡をしなければいけません。
各種の上限についてはこちらを、具体的な上限の上げ方についてはこちらをご参考ください。
NC24の場合、24コアなので、まずは上限を24以上にしましょう。
Azure
まずは、Azureポータルでログインし、Ubuntu Server 16.04 LTSで仮想マシンを立てます。
インスタンスはNC6もしくはNC24を選び、地域はWest US 2にしました。
ここで要注意なのは、VM disk typeでHDDではなくSSDを選んでしまうと、NC系列のインスタンスが表示されないので、インスタンスが見つからないときには、HDDになっているかを確認してください。
また、地域によってもNCインスタンスが選択できないこともありますし、地域ごとに少し料金の差もあるので、気を付ける必要があります。
仮想マシンのセットアップが完了したら、sshで仮想マシンに接続します。
無事にアクセスできたらlspciでグラフィックカードが検出できるかを確認します。
NVIDIAドライバー & CUDA 8.0
確認ができたら、下記の順で基本的な設定を行います。
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo apt-get install build-essential ubuntu-desktop -y
その後、NVIDIAドライバーをインストールする前に、Nouveauカーネルドライバーを無効にします(NVIDIAとの衝突を防ぐため)。
“/etc/modprobe.d”の中に”blacklist-nouveau.conf”というファイルを作り、内容は下記の通りに書き込みます。
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off
そして、最後にsudo update-initramfs -u
でinitramfsを更新します。
ここまで終わったら、sudo reboot
で一回リブートします。
その次に、NVIDIAドライバーとCUDAをインストールします。
今回は、それぞれのバージョン8.0と375.26を使いますので、下記のコマンドを入力します。
wget https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda_8.0.61_375.26_linux-run
chmod +x cuda_8.0.61_375.26_linux-run
sudo sh cuda_8.0.61_375.26_linux-run
インストール中に幾つかのプロンプトが出ますが、次のように答えます。
NVIDIAドライバーインストール – Yes
OpenGLライブラリー設置 – No
nvidia-xconfig実行 – No
CUDA 8.0 Toolkitインストール – Yes
CUDA ディレクトリー指定 [default is /usr/local/cuda-8.0] – そのまま
Symbolic linkの生成 – Yes
CUDAサンプルのインストール – Yes
サンプルのディレクトリー指定 [default is /usr/local/cuda-8.0] – そのまま
ここまでできたら、もう一度再起動します。
起動できたら、ターミナルでnvidia-smi
を叩き、ちゃんと表示ができるかを確認します。
表示出来たら、グラフィックドライバーはインストール成功です。
nvcc --version
を叩くと、バージョンが表示されるのでCUDAのインストール確認ができます。
最後に、~/.bashrcファイルを開き、次のようにパスを登録します。
export PATH=/usr/local/cuda-8.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:${LD_LIBRARY_PATH}
書き込んだら、source ~/.bashrc
で再度~/.bashrcを読み込みます。
cuDNN
その次は、cuDNNを入れましょう。
現在最新はv7ですが、検証当時はv6が最新だったため、ここではv6を基準で説明します。
手順は下記のようになります。
cuDNNはこちらで直接ダウンロードする必要があり、そのためにはNVIDIAの会員登録しなければいけません。
ダウンロードが完了したら、当該ディレクトリーに移動し、まずはtar -zxvf cudnn-8.0-linux-x64-v6.0.tgz
でファイルを解凍します。
その後、次のコマンドを入力し、解凍されたファイルを移動させます。
sudo cp -a cuda/lib64/* /usr/local/cuda-8.0/lib64/
sudo cp -a cuda/include/* /usr/local/cuda-8.0/include/
sudo chmod a+r /usr/local/cuda-8.0/lib64/libcudnn*
sudo ldconfig
これで、NVIDIAドライバー、CUDA、cuDNNのセットアップが完了しました。
ここまでが共通の環境構築で、その後はお好みにより、設定を行ってください。
私の場合Anaconda、CuPy、Chainerなどを入れました。
ここまでの所要時間は、1時間程度でした。
検証1「1本の動画を高容量のGPUメモリを使用し高速処理」
- 目的 -
動画1本を学習させる際に、バッチサイズを上げることで高速処理を図ります。
- 方法・手順 -
条件
・学習データ:モノクロHD画像3枚 = 1 batch
・正解データ:カラーHD画像3枚
・使用動画数: 1本
・実験 epoch 数:1 epoch、 1000 epoch
・比較対象:オンプレミス、NC6、NC24
手順
1. オンプレミス環境で検証動画を学習させ、所要時間を計測
2. NC6環境で検証動画を学習させ、所要時間を計測
3. NC24環境で検証動画を学習させ、所要時間を計測
- 結果 -
epoch 数 |
オンプレミス |
NC6 |
NC24 |
1 epoch |
約 8秒 |
約 8秒 |
約 8秒 |
1000 epoch |
約 2時間 |
約 2時間 |
約 2時間 |
まず、オンプレミスとNC6は、学習速度という面では特に大きな差はありませんでした。たまに、オンプレミス環境でのリソース占有率により、学習速度の上下はありましたが、違いは微々たるものでしたので、今回の検証では考慮しませんでした。
GPUメモリの容量不足のため、バッチサイズを1より大きくすることはできませんでした。
また、NC24の場合、マルチGPUではありますが、少なくとも今回の検証においてSLI機能は具現できなかったので、結果的にはNC6と同じ検証環境になり、実際の結果もNC6と差はありませんでした。
- 考察 -
この検証の目的であった、バッチサイズを増加させることで高速処理を図ることはどの環境でもできませんでした。想定としては、GPUが4枚搭載されているNC24でバッチサイズを増やし処理速度の向上を図ることでしたが、今回の環境では実現できませんでした。CNTKなどが並列処理をサポートしているとの記載もありますが、今回の検証はあくまでコードを修正せず、現状のカラーライズアルゴリズムを用いて学習のパフォーマンスの向上が図れるかを試す検証であります。その為、ここでは追加の検証は行いませんが、後程余裕がある時、再度方法を模索してみたいと思います。
結論、上記の環境で当該アルゴリズムを利用した動画1本の学習だけだと、NC6のインスタンスで充分ですし、オンプレミスやNC24よりコストも削減できることがわかりました。
検証2 「複数本の動画を多数のGPUにそれぞれ割り当てる並列処理」
- 目的 -
2本以上の動画を処理させる場合、マルチGPUで並列演算を行う事でどれくらいの効率向上が期待できるかを実証実験します。
また、動画4本の並列演算ができるインスタンスの立て方としては、
1) NC24を1つ立てる
2) NC6を4つ立てる
この2パターンがあり、どちらが時間やコストという視点から考えた場合、より効率的なのかを検証します。
検証2-1「NC24を1つ立てる」
- 方法・手順 -
条件
・学習データ: モノクロHD画像3枚 = 1 batch
・正解データ: カラーHD画像3枚
・使用動画数: 4本 (全く同じ動画を4本用意)
・実験 epoch 数: 1000 epoch
・比較対象: オンプレミス、NC6、NC24
手順
1. オンプレミスの環境で各動画を順番に学習させ、所要時間を計測
2. NC6の環境で各動画を順番に学習させ、所要時間を計測
3. NC24の環境で各GPUに学習を割り当て、作業を進めて所要時間を計測
各GPUへの割り当ての方法は、下記のコマンドを学習コマンドの前に付けて学習をさせるだけです。
例) 学習実行のコマンドがpython train.pyの場合:
CUDA_VISIBLE_DEVICES=0 python train.py #GPU1に作業を割り当て
CUDA_VISIBLE_DEVICES=1 python train.py #GPU2に作業を割り当て
CUDA_VISIBLE_DEVICES=2 python train.py #GPU3に作業を割り当て
CUDA_VISIBLE_DEVICES=3 python train.py #GPU4に作業を割り当て
したがって、NC24の場合、0から3までが指定できます。
- 結果 -
動画数
|
epoch 数
|
オンプレミス
|
NC6
|
NC24
|
4本
|
1000 epoch
|
約 8時間
|
約 8時間
|
約 2時間30分
|
|
NC6
(91.80円/時間)
|
NC24
(367.20円/時間)
|
時間
|
約 480分
|
約 150分
|
コスト
|
約 734円
|
約 918円
|
まず、時間の比較では、オンプレミス、NC6、NC24で動画4本の学習を行なった場合、オンプレミスとNC6は約8時間という結果が出ました。
一方、NC24では約2時間30分という結果となりました。これは、1本を学習させた2時間より少し増えた結果となります。
費用面では、オンプレミスが初期費用として約30〜40万円がかかり、NC6が約734円、NC24が918円がかかりました。金額の計算はセットアップ時間を除いた、学習だけの時間となります。
- 考察 -
シングルGPU環境であるオンプレミスとNC6では、1本の動画の学習が終わるまで、メモリ不足などの理由で次の動画の学習に進められません。2本を同時に処理しようとすると、ある程度は進みますが途中でメモリ不足のエラーが発生します。したがって、実験結果も1本の動画に対して学習を行なった時に比べ、4倍の所要時間が必要との、想定通りの結果となりました。
一方、4枚のGPUを搭載しているNC24では、それぞれのGPUに学習を割り当てる事ができ、理論上1本の動画の学習時間で4本もの動画が学習できるはずです。しかし、割り当て学習を行い、少し時間が経つと速度が低下し、1本を学習させた時に比べて、より長い時間がかかることがわかりました。正確な理由はわかりませんが、何らかの干渉があるのではないかと思います。時間があれば、この現象の理由についても調べてみたいと思いますが、今回の記事では省きます。
最後に、費用面では、NC6が約200円程節約できますが、学習時間の差分を考慮すると、個人的にはNC24を使いたいと思います。
検証2-2「NC6を4つ立てる」
- 方法・手順 -
条件
・学習データ: モノクロHD画像3枚 = 1 batch
・正解データ: カラーHD画像3枚
・使用動画数: 4本 (全く同じ動画を4本用意)
・実験 epoch 数: 1000 epoch
・比較対象: オンプレミス、NC6 * 4、NC24
手順
1. NC6のインスタンスを1つ立て、イメージとしてキャプチャ
2. 生成されたイメージから新しいNC6のインスタンスを4つ作成
3. 作成された4つのインスタンスに、それぞれ動画を1本ずつ分配・学習させ、所要時間を計測
4. NC24の環境で各GPUに学習を割り当て、作業を進めて所要時間を計測
- 結果 -
動画数
|
epoch 数
|
オンプレミス
|
NC6 * 4
|
NC24
|
4本
|
1000epoch
|
約 8時間
|
約 2時間
|
約 2時間30分
|
|
NC6 * 4
(91.80円/時間 * 4)
|
NC24
(367.20円/時間)
|
時間
|
約 180分
(セットアップ60分*1、学習120分)
|
約 210分
(セットアップ60分、学習150分)
|
コスト
|
約 826円
|
約 1,285円
|
※注2: ディスクI/Oによる時間・課金は除外
NC6 * 4とNC24との時間の比較では、NC6 * 4が約2時間、NC24が約2時間30分という結果になりました。
費用面では、NC6 * 4が約826円で、NC24が約1,285円となります。ここでは、より正確なコスト対パフォーマンスの比較のため、セットアップ時間60分を含めて計算しました。
また、NC6 * 4のセットアップは、まず1つのVMで環境構築を行いイメージとしてキャプチャした後、そのイメージから4つのVMを立ち上げましたので、セットアップ時間はインスタンス1つ分だけ計算されています。
イメージをキャプチャし立ち上げる過程でも時間はかかりますが、課金対象ではない時間であるため、計算式からは除外しました。
- 考察 -
検証1でも確認できたように、NC24の場合、4枚のGPU全てに作業を割り当てても、学習効率 (時間の短縮)は線型的に4倍増加するわけではないとのことがわかりました。
一方で、NC6を4つ立てると、動画4本に対する作業時間も、1本に対する作業時間に比べ、1/4になります。理由としては、NC6 * 4の場合、それぞれが独立した環境となり、お互いへの干渉が生じないからではないかと推測しています。
よって、NC24で全てのGPUに作業を割り当てた際に、スピードがやや落ちる現象の回避策の1つとして、NC6インスタンスを4つ立てる事も考えられるでしょう。
ただ、この場合は、それぞれのインスタンスに対して環境構築を行う必要があります。
Azureでは、既に作られているVMをイメージとしてキャプチャし、そのイメージからまた新しいVMを立ち上げる事が可能ではありますが、一度イメージとしてキャプチャしたVMはそれ以上使えなくなる為、注意が必要です。
なので、人によってはNC24の単一インスタンスを立てるのを好むかもしれません。
今回の検証でイメージから立ち上げた理由は、各環境で削減できる部分は最大限に削った場合、どれだけ検証対象間の使用金額に差が生じるかを確認したかったためです。例えば、CUDA 8.0とcuDNN 5.1が既に構築されているAzureのDSVMというのを使う方法もありますが、DSVMの環境が本検証で構築した環境と多少違いますし、NC24と掛け合わせた場合、金額も約440円/時間という、多少高めの設定となっているため、今回の検証では使っておりません。
費用面では、NC24の単位時間当たりの費用が、単純に4つのNC6を同時に使うのと同じ金額設定にはなっています。よって、セットアップ時間を除くと、差額が然程大きくはないと思います。しかし、1時間のセットアップ時間を考慮し、NC6を既に環境構築されたイメージから立ち上げるとなると、話は変わります。NC24は、1時間のセットアップの間、367.20円が課金されますが、NC6の場合は91.80円が課金されるので、NC24の1/4の値段で済みます。その結果、上記の表の通りに、およそ400円程度の差分が生じます。
上述したように、シングルGPUのインスタンスを複数立てるのは手間がかかります。一方で、マルチGPUのインスタンスを1つ立てるのはコストが高くなります。手間と費用、どちらを取るかは完全に個人の好みなので、どちらが絶対的に良いとは言えませんが、時間的に余裕がある場合には、個人的にシングルGPUのインスタンスを複数立てると思います。ただ、これはあくまで動画4本を処理する場合に限ることで、数十本~数百本の動画を同時に処理しなければいけない状況だと、それぞれの特性を活かし、効率よく組み合わせることも1つの方法かもしれません。
まとめ
カラー化AIでは、精度をより高めるために、動画毎に専用の素材を用いて学習を行い、各動画に適した重みやハイパーパラメータを用意するので、このような並列演算が学習時間の短縮にとても役立ちます。
並列演算をオンプレミス環境で実現しようとすると、単発性とは言え、かなり巨額の費用がかかります。今回の検証には最大4本の動画が使われたのですが、もし、それ以上の動画を同時に処理したいとなると、個人では環境を用意するのが多少厳しいかもしれません。また、投下費用が大きい分、損益分岐点を超えるのがなかなか難しいので、これもオンプレミスを使う上での1つのハードルになります。
そこで、Azureの良さが発揮できます。Azure上では簡単にインスタンスを増やし、容易く並列演算の環境を構築することができます。即ち、必要に応じて自由にGPUの数を増やしたり減らしたりすることができます。これにより、常にリソースのかかる演算をしない個人ユーザーでも手軽にディープラーニングに手をつけることができるようになります。
開発側の視点からも、頻繁に学習と検証 (バリデーション)を行わなければいけない段階ではなく、開発完了したアルゴリズムを用いて学習を行うだけの場合だと、Azureをフル活用できると思います。
また、もう1点、個人的にAzureを使って嬉しかったのは、手元にマシンがなくても学習環境がすぐ構築できるということでした。既存のやり方だと、普段使っているマシンでないと、ちょっとしたテストでもできないということがとても不便でしたが、Azureを活用すると、ネットさえ繋がっていれば、どのパソコンからも接続ができるところが、以外に嬉しかったです。これも、個人ユーザーがディープラーニングにより気軽にアプローチできるようにする1つの要素になるかと思います。
オンプレミスとAzure環境の特徴をまとめると下記のようになります。
|
オンプレミス
|
NC6
|
NC24
|
初期費用
|
30 ~ 40万円
|
特に無し
|
|
使用費用
|
特に無し
(+電気代)
|
91.80円/時間
(+ディスク使用料)
|
367.20円/時間
(+ディスク使用料)
|
構築の工数
|
≈ Azure
|
> NC24
|
< NC6
|
その他
|
・GPUを増やすには大きな追加費用がかかる
・部品が選べるのでスペックの調整ができる
・SLI環境が構築が比較的に簡単
|
・簡単にインスタンス (GPU)の数が調整でき、
それに伴う追加費用も安い
・コア数の上限がある (上限値変更可能)
・ディスクI/Oによる費用が発生する
・場所の制約がなく、どこでも学習が行える
|
今回の検証を通じて、納期期日が迫っている状況で、複数の動画を処理しなければいけない場合にはAzureを最大限活用できることがわかりました。ただ、これはあくまでHD画質の場合に限り、もし動画の画質が4kや8kなどになると、GPUメモリ12GBのNCインスタンスでは、現状のままだと学習が難しいです。この場合には、SLI環境が比較的簡単に構築できるオンプレミス環境が適しているかもしれません。
現時点の学習データのサイズではAzureを利用し作業効率を向上することができますが、今後より大規模な学習データを処理しなければいけない時期が来た際に、Azure上でSLI機能が活用できると、生産性が一層高まると期待できます。それまでは、用途によってオンプレミスとAzureを適切に使い分けることで、作業の効率を最大化しようと思います。
今回の検証では、データパラレルとモデルパラレルの手法が試せませんでしたが、 パラレル手法は、使いこなせると、 GPUの数が簡単に増やせるクラウド環境の特徴を最大限活かせますので、 今後、コードの修正や違うフレームワークの活用などを通じて、 パラレル手法を使った検証もやってみたいです。 また、より効率の良くクラウドを使うために、dockerイメージを使った環境構築などの方法も試し、 実際どれだけ工数が軽減できるかも検証してみたいと思います。
参考文献
- Azure環境構築
- その他の参考資料