DPとDDP
分散学習には大きく2つのアプローチ方法がある。
データ並列(Data Parallel):ミニバッチを複数の計算機に分散する方法
モデル並列(Model Parallel):一つのモデルを複数の計算機に分散する方法
DPとDDPの共通事項
DPにしても、DDPにしても分散学習を実現するためにはノード間でのメッセージのやり取りが必要。
例えばノードで学習が終了したことを通知したり、勾配データの同期を取る時など。
ノード間でメッセージをやり取りする技術
MPI(Message Passing Interface)
NCLL(NVIDIA Collective Communications Library)
GPUで動作する場合は高速。
Gloo
DP
Data Parallel データ並列化のこと。
計算を複数の計算機に分割する。
異なるGPUが異なるデータの一部で訓練を行う。
GPU同士を同期する場合、各訓練のstep後に勾配を集約する。
各GPUは同じモデルのコピーを持ち、勾配は中央に集められる。
バッチを分割して各GPUに送信する。
modelに対してmodel = nn.DataParallel(model)といった形で適用する。
DDP
Distributed Data Parallel マルチプロセスのデータ並列化のこと。
各GPUにあらかじめデータ重複が無いようにDataloaderを用意する。
各GPUでのLossを計算して、モデルの各パラメータの勾配を計算して各GPUに
modelに対してmodel = DDP(model, device_ids=[rank])といった形で適用。
DDPは、1プロセスにつき一つgpuを割り当てている。そのためrankがdeviceをあらわす。
必ず、dist.init_process_group()で初期化する必要がある。
総合的にはDDPの方が良い
速度はDDP > DP。各々のGPU通信が少なくて済むのが理由。
ただし、マルチプロセスなのでメモリ消費が多くなるデメリットもある。
なぜDDPの方が良いかというと、DDPの方が通信回数が少ないからである。
DPはDataloaderをGPU:0でのみ所有して毎回分割を行い、ステップ毎に全部のGPUの勾配の結果をGPU:0に送信する必要があり、モデルのパラメータ更新はGPU:0で行なわれることになる。
DDPは初めからDataloaderを各GPUで所有(この時点でDatasetを分割済)しているため、モデルのパラメタ共有は初回のみ行われ、モデルのパラメータ更新は各GPU間で勾配を送信し合って、集計後の勾配値を見て、それにより各GPUで更新する
実装面で言うと、DPはnn.DataParallel()でモデルを包んであげるだけで実現できる。
DDPはソースの変更点が多くてコーディングの難易度が上がる。DDPの意味を理解してからコードを構成しよう!
しかし、PyTorchLightningに限って言えばDDPの方が変更量が少ない。PLすごい。
DDPの実装方法
マルチGPUはここ1年くらいでライブラリが整備され始めたばかりであり、まだまだ破壊的な変更が多い箇所でもある。
Tensorflowではtf.distribute.Strategy
学習のフレームワーク間で同様のコード変更で分散学習を実現するフレームワークHoeovodもある nvlinkの使用ができるか
モデルをDDPで包む。
エポックが始まる前に全部のGPUで同期をとる
PLのコードは1行も変更せず手元のローカル環境からクラウドへ学習をスケールできる
Grid.ai
参考資料