Contenu connexe Similaire à Chainer で Tensor コア (fp16) を使いこなす (20) Plus de NVIDIA Japan (20) Chainer で Tensor コア (fp16) を使いこなす1. Akira Naruse, Senior Developer Technology Engineer, 2018/12/15
Chainer で Tensor コア (fp16) を
使いこなす
4. 4
VOLTA TENSOR コア
FP16/FP32 混合精度行列演算ユニット
Tesla P100 Tesla V100
FP16 20 TFLOPS 125 TFLOPS
(Tensor コア)
FP32 10 TFLOPS 16 TFLOPS
FP16
FP16
× + FP32
FP32
FP16 FP32
5. 5
FP16 で学習して、精度は大丈夫?
• 2 つのテクニック
• ロス スケーリング
• ロス値をスケールアップし、勾配消失を緩和
• ウェイト更新直前に、勾配値をスケールダウン
• FP32 ウェイト更新 (FP16 と FP32 の併用)
• Forward/Backward は FP16 で計算
• Update で FP32 を使用
Mixed Precision Training
https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/
勾配値の分布
(*) FP16 にすると、多くの勾配値がゼロになってしまう
6. 6
ロス スケーリングと FP32 ウェイト更新
勾配勾配勾配勾配勾配勾配勾配
損失
関数
誤差
Backward
Forward
Update
勾配をスケールダウンし (例: 1/10 倍)、
FP32 ウェイト (master) を更新し、
FP16 ウェイトにコピーする
Backward 直前に誤差をスケールアップし
(例: 10 倍)、勾配消失を回避する
7. 7
FP16 で精度を維持する方法
• FP16 で学習しても、FP32 モデルとほぼ同じ精度
• 主要な DL フレームワークで利用可能
• TensorFlow
• PyTorch
• MxNet
• Chainer
Mixed Precision Training
https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/
Better
11. 11
注意事項: その2
モデル記述を fp16 向けに修正
• 入力: fp16 に cast
• Initializer、Batch normalization: dtype に fp16 指定
本当は、fp16 モードをセットするだけで OK なんだけど..
CHAINER_DTYPE=float16
Chainer tips
def forward(self, x, t):
- h = self.bn1(self.conv1(x))
+ h = self.bn1(self.conv1(F.cast(x, np.float16)))
h = F.max_pooling_2d(F.relu(h), 3, stride=2)
self.conv1 = L.Convolution2D(3, 64, 7, 2, 3,
- initialW=initializers.HeNormal())
- self.bn1 = L.BatchNormalization(64)
+ initialW=initializers.HeNormal(dtype=np.float16))
+ self.bn1 = L.BatchNormalization(64, dtype=np.float16)
12. 12
性能比較
良い点:
• BS: 128 以上で、fp32 より速い
• BS: 256で学習可能 (fp32 だと
メモリ不足)
悪い点:
• BS: 64 以下だと、fp32 より遅い
FP32 vs. FP16
0
100
200
300
400
500
600
700
800
900
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16
Better
13. 13
TRAINING ITERATION
CPU の仕事
• IO: 入力画像の前処理 (Decode,
Augmentation)
• Forward/Backward/Update: 計算グラフ管理,
メモリ管理, GPU カーネル投入
IO Forward Backward Update
GPU の仕事
• Forward/Backward/Update: CPU
から投入されたカーネルを実行
14. 14
性能比較
良い点:
• BS: 128以上で、fp32 より速い
• BS: 256で学習可能 (fp32 だと
メモリ不足)
悪い点:
• BS: 64以下だと、fp32 より遅い
FP32 vs. FP16
0
100
200
300
400
500
600
700
800
900
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16
Better
17. 17
NVVP で挙動を確認 (FP16, BS: 64)
GPU稼働率が低い
FWD BWDIO
CPU
FWD BWDGPU
Tensor コア使用で GPU 処理は速くなった。しかし、CPU の処理が間に合わない
19. 19
対策: CPU の負荷を減らす
IO 処理を高速化、別スレッドで実行
• NVIDIA DALI
GPU 操作回数、GPU カーネル数を削減
• Batched weight update、 Fused Bnorm/ReLu、 NHWC format
計算グラフ管理負荷を削減
• Chainer static_graph
21. 21
NVIDIA DALIの効果
良い点:
• BS: 64以上で、fp32 より速い
• BS: 128 はBS: 256 とほぼ同性能
悪い点:
• BS: 32以下だと、fp32 より遅い
0
100
200
300
400
500
600
700
800
900
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16 fp16 (+dali)
Better
22. 22
NVIDIA DALI の効果確認 (FP16, BS: 64)
IO 処理は、他とオーバーラップ
FWD BWD
FWD BWD
IO by DALI (next)
CPU
GPU
依然として、CPU の処理が間に合っていない
23. 23
対策: CPU の負荷を減らす
IO 処理を高速化、別スレッドで実行
• NVIDIA DALI
GPU 操作回数、GPU カーネル数を削減
• Batched weight update、 Fused Bnorm/ReLu、 NHWC format
計算グラフ管理負荷を削減
• Chainer static_graph
24. 24
BATCHED WEIGHT UPDATE
Chainer optimizer は、レイヤー毎(より正確にはパラメータ毎)に、重みを更新
• 多数の GPU カーネル起動 → CPU 負荷大
Single GPU カーネルで、全ての重みを更新 (batched_update)
Chainer #5841
PR中
update
update
CPU
GPU
25. 25
FUSED BNORM/RELU
• cuDNN 7.4 から導入
• Fp16 and NHWC フォーマット
(後述) のときに利用可能
• レイヤーの自動融合は大変。
bnorm_add_relu モジュールを試作。
モデル記述を修正。
GPU カーネル数の削減、メモリアクセス量を削減
試作
26. 26
NHWC FORMAT
• NCHW だと、Convolution 前後
で、合計 3 回の Tensor
Transpose が必要
• NHWC なら、Transpose 不要
→ GPU カーネル数削減
• Chainer は NCHW only
• NHWC 専用の
Convolution/Bnorm モジュール
を試作
cuDNN Convolution for TensorCore: NHWC format で高い性能を発揮
NCHW NHWC
試作
27. 27
BATCHED+FUSED+NHWC の効果
良い点:
• 常に fp32 より速い
• BS: 256 で、1200 imgs/sec
悪い点 (相対的に):
• BS: 32は、BS: 256 の 1/3 の
性能0
200
400
600
800
1000
1200
1400
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16 (+dali) fp16 (+nhwc, fused, batched)
Better
28. 28
効果確認 (FP16, BS: 64)
NHWC+FUSED+BATCHED
FWD BWD
FWD BWD
IO by DALI (next)
CPU
GPU
CPU 負荷を減らしたが、GPU 時間も NHWC+FUSED で短縮 → まだ GPU に空きがある
29. 29
対策: CPU の負荷を減らす
IO 処理を高速化、別スレッドで実行
• NVIDIA DALI
GPU 操作回数、GPU カーネル数を削減
• Batched weight update、 Fused Bnorm/ReLu、 NHWC format
計算グラフ管理負荷を削減
• Chainer static_graph
31. 31
STATIC_GRAPHの効果
良い点:
• BS: 32/64 の性能改善
悪い点:
• BS: 128 以上で実行不可
(メモリ使用量が増える?)
0
200
400
600
800
1000
1200
1400
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16 (+nhwc, fused, batched) fp16 (+static_graph)
Better
32. 32
効果確認 (FP16, BS: 64)
Static_graph
FWD BWD
FWD BWD
IO by DALI (next)
CPU
GPU
やっと、「CPU 処理時間 < GPU 処理時間」、になった
33. 33
ここまでのまとめ
fp32 の3倍の性能を達成 (最大で)
• DALI
• Batched weight update
• Fused Bnorm/ReLu
• NHWC format
• Static_graph
Backend が python でも、ここまで
速くできる
Tensor コア/fp16 を用いた ResNet-50 トレーニング
0
200
400
600
800
1000
1200
1400
bs:32 bs:64 bs:128 bs:256
Images/sec
fp32 fp16 (base) fp16 (best)
Better
ChainerXで
速くなる?
34. 34
何故 “BS: 32” を速くしたいのか
Goal: ImageNet+ResNet50 with 4096 GPUs
Processor DL framework Time
Microsoft Tesla P100 x8 Caffe 29 hours
Facebook Tesla P100 x256 Caffe2 1 hour
Google TPUv2 x256 TensorFlow 30 mins
PFN Tesla P100 x1024 Chainer 15 mins
Tencent Tesla P40 x2048 TensorFlow 6.6 mins
SONY Tesla V100 x2176 NNL 3.7 mins
Google TPUv3 x1024 TensorFlow 2.2 mins
35. 35
LARGE MINI-BATCH PROBLEM
Local BS: 32 でも、4096 GPU だと、
Global BS: 128K
ImageNet + ResNet50だと、Global
BS: 32~64K でも、validation
error < 25% を出せるようになってき
たが..
SGD の限界?
ImageNet, ResNet50, Local BS:32
(*) P. Goyal, et.al., Facebook,
“Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour”
Better
36. 36
SGD 以外の選択肢
Backprop で得られる「勾配ベクトル」の向きは、
それほど正しくない
KFAC: フィッシャー行列を近似計算して勾配補正
• 学習の「向き」が SGD より正しくなる (反復数減)
• 1 反復あたりの計算量が増える
Global BS: 128K でも、75% の validation
accuracy を実証
• BS 16K 以下なら、30~35 epoch で収束
(SGD は90 epoch 必要)
K. Osawa, et.al., “Second-order Optimization Method for Large Mini-batch:
Training ResNet-50 on ImageNet in 35 Epochs”
(*) 東工大 横田研・松岡研との共同研究
ImageNet + ResNet50
Better
Distributed KFAC optimizer
on Chainer