ディープラーニング分散学習ハッカソン参加報告
経緯
研究室のお金でディープラーニング分散学習ハッカソンに参加してきました.
東京大学情報基盤センターが主催する、マルチGPUを使った学習のハンズオン。申し込みは締め切られているが、資料が公開されており分散学習の仕組みと課題、そしてChainerMN/TensorFlowで実際に分散学習を行う方法までが解説されている。 https://t.co/ISU1CZIr2b
— piqcy (@icoxfog417) 2019年1月24日
想定する読者
- 深層学習してる人
- 分散深層学習をやってみようと思っている人
イベントの概要
要旨:参加者が持ち寄った深層学習のコードを強いメンターたちに助けられながら分散深層学習のコードに書き換えていく.
共催:
期間:2019/01/24--2019/01/25 の 2 日間
場所:東京大学情報基盤センター
計算機:情報基盤センターの Reedbush-H
フレームワーク:Chainer か Tensorflow
プログラム:
- 主催側からのプレゼン(各組織 20 分ずつ)
- 参加者自己紹介
- 各自作業
- 成果報告
分散深層学習基礎講座
Nvidia さまから 分散学習基礎講座 というタイトルのプレゼンがあったので,その内容を私なりにまとめる.詳細は元スライドを参照のこと.
分散深層学習とは
深層学習を,複数の GPU を使って行うこと.データ並列/モデル並列 や 同期更新/非同期更新,パラメータサーバ方式/P2P方式 などの分類がある.
データ並列とモデル並列
データ並列
モデルをコピーして,パラメータを共有した状態でそれぞれ別のサンプルで訓練する並列化方法.GPU ごとに別々のデータで勾配を計算させるので,モデル更新時にはうまいことパラメータを一致させる必要がある.
同期更新と非同期更新
パラメータの更新方式は同期更新と非同期更新に分けられる.
同期更新 | 全 GPU の勾配計算完了を待ってモデルを更新する.GPU 性能に差がある場合無駄が出る. |
---|---|
非同期更新 | 一部の GPU の勾配計算が終わったらモデルを更新する.後述の Staleness 問題が発生する. |
パラメータサーバ方式と P2P 方式
GPU 間の通信にはパラメータサーバ方式と P2P 方式がある.
パラメータサーバ方式 | パラメータサーバのパラメータを,各 GPU がそれぞれ更新していく. |
---|---|
P2P 方式 | ある GPU での更新を他の GPU に伝播させる. |
モデル並列
一つのモデルを複数の GPU に置く.一つの GPU にはモデルの一部が乗っている状態.各レイヤを GPU に割り当てたり,一つのレイヤを複数の GPU に割り当てたり,いろんな切り方がある.どのような切り方がいいかはモデル依存.
各方式の弱点
データ並列:大規模化に伴う精度低下
一回の重みの更新の時に関わるサンプル数が [バッチサイズ] × [並列数] になるため,並列化しすぎると精度が低下する.
どこまで並列化できるかや,たくさん並列化しても精度を落とさないようにする研究が行われている.
- 「8k 並列までなら精度落ちない」by 顔本
- 「32k まではいける」by PFN
ちなみに SGD 的な最適化を行う場合,学習率を下げることとバッチサイズを大きくすることは等価 であるため,学習が進むにつれて学習率を下げる代わりに並列数を大きくするのもアリかもしれない.簡単には実装できなさそうだけれど.
同期更新:GPU の性能差で無駄が発生
パラメータの更新時に全ての GPU での勾配計算が完了するのを待つため,GPU に大きな性能差がある場合に無駄な時間が発生する.
非同期更新:Staleness 問題
非同期更新では,勾配の計算中に他の GPU がパラメータを更新するので,勾配計算に使っていたパラメータが相対的に古くなってしまう.これを Staleness 問題という.Staleness 問題は収束性の悪化の原因となるらしい.
モデル並列:通信コスト
フォワードプロセスでも GPU 間で通信が必要なので,データ並列に比べ通信コストが高い.
私たちがやったこと
弊研究室 からは K 先輩と私の 2 人で参加した.私たちは Chainer を使った seq2seq 機械翻訳モデルのコードに対して ChainerMN でデータ並列の分散化を施した.
資料 の通りに秒速 MN 化を行ったところ,悲しいことにバグが大量発生したので Chainer の中の人に助けられながらその解消を行っていった.なんとか時間ギリギリでエラーの出ない状態になり,並列化でどれくらい速くなったか測ろうとしたところ時間切れとなってしまった.ログを見る限り並列化しないほうが速かったので,多分まだどこかにバグがあるんだと思う.悲しい.
バグ取りを通して得られた知見
重複するエラーメッセージ数
並列数とエラーメッセージの重複数が同じ場合は GPU ID に関係のないところで出ているエラー,異なる場合は GPU ID によってエラーが出る場合と出ない場合があるエラー.私たちの場合は GPU に ID を割り振る操作をコードの中で複数回呼んでしまっていたことで起きていた.
単一 GPU でも同じエラーが出るかどうか
同じコードでも単一 GPU に設定した場合は動く場合,GPU 間の通信時に起きているエラーの可能性が高い.単一 GPU だと通信が行われないのでエラーが発生しない.
GPU に載せるテンソルは to_gpu とかの後に作る
ChainerMN ではデバイスをセットする操作の前後の行列を混ぜると死ぬ.
参加しての感想
ChainerMN 開発者をメンターに据えて ChainerMN を使ってみるという贅沢な時間でした.開発者ならではのお話が聞けて楽しかったです.
2 日間とも Nvidia さまがお弁当を提供してくれたり,1 ヶ月間 Reedbush を利用できるという特典も付いているのに参加費は無料という超絶お得なイベントでした.参加してよかったです.
分散深層学習を行うのは初めてだったのですが,難しかったです.私の研究では画像もテキストも扱うので,モデルの大きさによってはバッチサイズを小さくしないと動かないということが起こります.そんな時にデータ並列は [バッチサイズ] × [並列数] が実質のバッチサイズになるので魅力だと思いました.頑張ろうかな.頑張れるかな.
修論で忙しいにも関わらず本記事の最終確認をしてくれた T 氏に感謝いたします.