秒速☆ChainerMN
CHAINER UG /
PREFERRED NETWORKS, INC.
福⽥圭祐
秒速☆ChainerMN ⽬次
1. 分散する前に動作確認しましょう
2. 分散深層学習の概要を把握しよう
3. MPIを必要最低限理解しよう
4. MPIが正しく動いているかどうかチェックしよう
5. ⾃分のプログラムの修正が必要な箇所を特定しよう
6. 最低限の変更 + 動作確認
7. 発展
2
分散化する前に動作確認しましょう
• 必要な module、Pythonパッケージが⼊っているかどう
かチェック
• 「利⽤の⼿引き」を参照して、1 GPUジョブを投げてみ
て動作確認しましょう
(数⼗ iteration〜1 Epoch程度でOK)
• かならず「バッチジョブ」でもテストしましょう
3
4
ABCI
$ module load cuda/9.2
$ module load cudnn/7.1
$ module load openmpi/2.1.5
$ module load nccl/2.3
$ module load python/3.6
$ module load singularity # optional
$ pip install --user cupy-cuda92==5.2.0 
chainer==5.2.0 
mpi4py
5
分散学習とは何かを理解しよう:NVIDIA様の資料を10回読む
MPIを必要最低限理解しよう
• ChainerMNは、MPIという通信ライブラリの上に構築されています
(MPI=並列計算で標準的に使われる通信ライブラリ)
• 要点
– mpiexecというコマンドで起動する
→ SSHを使って、⾃動的にプロセスを起動/管理してくれる
– 基本的に、サーバー/クライアントという概念はない
(全プロセスが互いに対等)
– 個々のプロセスはRankというプロセス番号を持つ(0〜N-1)
– すべてのプロセスが同じプログラムを実⾏する
(ただし、Rankによって条件分岐することが可能)6
MPIを必要最低限理解しよう ‘cont
• 注意点:インストールが⾯倒
• OK:
– ○ChainerMNドキュメントを読んで⼊れた
– ○詳しい⼈が(ChainerMNドキュメントを読んで)⼊れてくれた
– ○スパコンに元から⼊っているものを使う
• NG:
– ×OSのパッケージマネージャで⼊れた
– ×なんかよくわからないけど、⾯倒だからドキュメント読まずに
とりあえず⼊れた 7
MPIが正しく動いているかどうかチェックしよう
$ mpiexec -n 4 
--host gpcl-gpu131:slots=2,gpcl-gpu132:slots=2 
--map-by ppr:2:node 
python mpi_check.py
8
import chainermn
from mpi4py import MPI
comm = chainermn.create_communicator('pure_nccl')
for i in range(comm.size):
if i == comm.rank:
print("{} {}".format(comm.rank, comm.intra_rank))
MPI.COMM_WORLD.Barrier()
MPIが正しく動いているかどうかチェックしよう
9
import chainermn
from mpi4py import MPI
comm = chainermn.create_communicator('pure_nccl')
for i in range(comm.size):
if i == comm.rank:
print("{} {}".format(comm.rank, comm.intra_rank))
MPI.COMM_WORLD.Barrier()
MPIが正しく動いているかどうかチェックしよう
10
$ vi job.sh
#!/bin/sh
#$-cwd
#$-j y
source /etc/profile.d/modules.sh
module load cuda/9.2
module load cudnn/7.1
module load openmpi/2.1.5
module load nccl/2.3module load python/3.6
module load singularity
mpiexec -n 8 --map-by ppr:4:node python mpi_check.py
$ qsub -l rt_F=2 -g gaa00000 -l h_rt=01:00:00 job.sh
MPIが正しく動いているかどうかチェックしよう
0 0
1 1
2 2
3 3
4 0
5 1
6 2
7 3
11
期待される出⼒(8プロセスの例):
intra_rank: 物理計算ノード内でのRank
rank: 全体でのRank
ChainerMNの動作の概要
• 同期型、データ並列が基本
• 最低限のMN化のために必要なこと:
1. ChainerMNが使うオブジェクトを作成する
2. 勾配を交換(平均)するためのOptimizerを作成
3. ログ出⼒などの細かいところをマルチプロセス仕様にする
12
device = …
chainer.cuda.get_device_from_id(device).use()
…
optimizer = chainer.optimizers.Adam()
import chainermn
…
comm = chainermn.create_communicator('pure_nccl')
device = comm.intra_rank
chainer.cuda.get_device_from_id(device).use()
…
optimizer = chainermn.create_multi_node_optimizer(
chainer.optimizers.Adam(), comm)
…
if comm.rank == 0: # LogReportなどを代表一人だけが出力するようにする
trainer.extend( … )
13
これだけの変更で(最⼩限の)MN化!
1. ChaierMNが使うオブジェクトを作成する
2. 勾配を交換するためのOptimizerを作成
3.ログ出⼒などの細かいところをマルチプロセス仕様にする
• まずは秒速MN化したうえで、動作確認をしましょう
• その後やること:
– scatter_dataset
(プロセス間で学習データに重複が無いように分割)
– evaluatorの並列化
(現在はrank 0だけのevaluationの結果が記録される)
– バッチサイズ増加に伴うパラメーターチュニング
• 発展編
– Multi node BN (inter-GPU BN)
– モデル並列
秒速MN化のその後
14
scatter_dataset
データ全体をプロセスごとに分解する
15
scatter_dataset使⽤前
scatter_dataset
データ全体をプロセスごとに分解する
16
scatter_dataset使⽤後
精度への影響:
• (未知数)
• データの重複がなくなる分 ↑ ?
• プロセスごとの
データ多様性が減る分 ↓ ?
速度への影響:
• 向上する
(メモリキャッシュに乗りやすくなる)
evaluatorの並列化
• ChainerMNは、Evaluatorの並列化もサポートしています
• …が
– サポートしているのは、Evaluationの並列化+スコアを
平均するという機能の MultinodeEvaluator
– 平均では不⼗分な場合は困難→無理して並列化する必
要なし
17
さらに発展
Even more advanced topics…
• Hyperparameter tuning
– Learning Rate
– Using Optuna
• Multinode Batch Normalization
• Model parallelism
• Double Buffering (ABCIでは不要)
• チューターにお尋ねください
18
19

秒速ChainerMN