" B/ C4 Q! u4 ^: g" b I 作者:Pieterluitjens
# _; {; P9 j3 u# _# E 参与:一鸣、嘉明、思
: [! A X) V3 \; z% b5 v2 w2 M
你的数据处理影响整个训练速度,如果加上英伟达 DALI 库,处理速度比原生 PyTorch 也能快上四倍。
6 n) o' j* n& A7 C
- Z3 j) l+ O" X
2 `/ K& X0 f2 d: R% i! d
打开凤凰新闻,查看更多高清图片
2 A4 ^1 [ C: j4 o3 V& K
+ \. s2 y. b( f) Y* X! T( z. M! j9 ~
+ H: M0 X1 ]. j$ x2 @: b
深度学习的加速上,除了对训练和推理过程的加速之外,还有对数据加载和预处理阶段的加速。这一阶段也尤为关键,因为数据处理 pipeline 的处理速度也影响着整体的流程效率。
7 G, h; H, w" w6 R- L9 W) y8 Z$ F, B 近日,有开发者介绍了如何使用 NVIDIA Data Loading Library(DALI),以及使用这个库进行数据预处理加速的方法。DALI 和 TensorFlow 自带的 DataLoader 类似,是一个专门用于加速数据预处理过程的库。
# ~ G3 p" x- b& J7 v
在一篇博客中,开发者表示,该库不仅可以进行 GPU 加速,也可以在 CPU 上构建一个完整的数据预处理流程。如果在 Tesla V100 上做测试,PyTorch+DALI 的处理速度能达到 4000 images/s,比原版 PyTorch 要快近 4 倍。
1 K2 i9 n6 u( E# u. Q2 ~# m) @ 支持多个框架,针对预处理
" T/ f) ?- q: ~' m% ?, U 英伟达数据加载库 DALI 是一个便捷式开源库,用于图像或视频的解码及增强,从而加速深度学习应用。通过并行训练和预处理过程,减少了延迟及训练时间,并为当下流行的深度学习框架中的内置数据加载器及数据迭代器提供了一个嵌入式替代器,便于集成或重定向至不同框架。
' ?# v7 Z# a. X. X6 c! f# y
开发人员可以在 GPU 上运行他们的数据处理通道,从而减少训练神经网络的时间。而 DALI 实现了数据处理 pipeline 可移植,因为可以轻松地重定向至 TensorFlow,PyTorch 和 MXNet。
# O& P) e, y1 i& k( N9 x9 N 
) `4 q4 C3 b, ]6 ~- E+ B DALI 设计之初就是用来帮助用户突破数据预处理的瓶颈,使得模型的训练和推理能够达到最高的效率。其主要设计是用于在 GPU 上的预处理,但大多数操作也可在 CPU 上实现。
4 H$ x3 O* s3 C; @ 主要特征
$ ?, A8 M) U' o3 F& T) g- D 易于使用的 Python API
) C) e4 N/ v8 ~( Q7 H$ K6 `
在多个 GPU 之间显式地缩放
7 ^+ I# ^5 a! o9 v% b9 h5 a 加快图像分类(ResNet-50)和目标检测分类(SSD)工作流
% r# r, o0 N9 G
灵活的计算图使得开发人员可创建自定义的数据处理 pipeline
. s+ W$ O. |# {! [8 J 支持多种格式 - LMDB、RecordIO、TFRecord、COCO、JPEG、H.264 以及 HEVC
! h, b/ F) E& a. J2 p* _' `, A J
开发人员可添加自定义的图像或视频处理 operator
' r& o; O K0 M/ A: M" q4 p" ?: m 
4 _. n! r1 b7 c& d$ L# s DALI 在 MXNet 上训练 ResNet50 的性能表现。
5 T) v8 `; x, T! f 使用 DALI 重构数据预处理 pipeline
4 Y- ?) k w3 F
内存占用大是 DALI 在加速数据预处理中面对的一个重要问题。随着批大小的上升,DALI 的内存占用会变得更大。这一问题现在还没有得到修复。
2 ]# c3 Y4 X% v& @' b1 X) L' R

/ @2 c; ^& ^( _ `, B4 d! [ DALI 的内存占用问题。
' M |4 [2 i, a# C! Z 而和其他的数据预处理工具相比,DALI 能够最大处理的批大小相比 TorchVision 少了一半。
, E3 b5 s6 U. s

0 P6 A7 }& q3 O: Y 因此,使用 DALI 加速数据预处理需要重新构建整个 pipeline。在教程中,作者分别介绍了构建 CPU pipeline 和 GPU pipeline 的方法。
5 Q2 P& S" b$ a 构建 CPU pipepline
% Z* Y8 M U! j' V. v" w3 J) v& P
使用 CPU 进行数据预处理的时候,常用的做法是让 CPU 处理解码和 resize 的工作,而 CropMirrorNormalize 这样的工作放到 GPU 上。由于使用 DALI 将输出传入 GPU 中就会占用很大的内存,因此作者构建了一个完全基于 CPU 的 pipeline。
, ~9 x. N( B% Y) w5 V
首先,重新加载并导入 DALI。
4 f- Z* x5 }- b1 H f0 Q, f; a 
) W1 o$ j* L# W) |/ n
然后构建基于 CPU 的 pipeline。
' X* N( A9 H, {% N9 M* H. p 
" r8 L" N1 S$ h: ?1 ]. L' `6 a 在这里设置一下哪些操作应当由 CPU 运行。
+ V$ ]* Z9 ]5 u+ |0 T" x

1 J9 k- j0 X+ K( p% P. T0 V
然后开始相应的操作。如解码:
% E! k8 \% c0 |; C1 ~

& |. l9 L# h3 P9 e4 c6 z 以及 resize:
/ ~; F1 I* |( ? 
: k; U3 b+ I6 U0 ? CropMirrorNormalize 的操作由 GPU 进行。
) ~# g2 V; Q1 e( _' `( @1 [; O7 m

( d8 x& V3 F% N9 m5 Y; _& o
当然,还需要从 CPU 到 GPU 的转移过程,这一过程使用 PyTorch 进行,作者在教程中也给出了相应的代码。
$ A; G9 T, I1 P' {2 H, I& d( p 构建基于 GPU 的 pipeline
: t8 D+ q1 e; s8 L3 N. W
当模型较大(如使用 ResNet50)的时候,基于 CPU 的 pipepline 效果较好,而在类似于 AlexNet 或 ResNet18 这样的小模型上,CPU 的处理还是跟不上 GPU 的数据处理速度。其主要原因在于,GPU pipeline 会降低近一半的批大小。
& c6 ^" L4 y9 K+ }* d7 G! y$ P
为了解决这个问题,作者建议将验证 pipepline 从 GPU 中关掉,直到每个 epoch 的最后需要的时候再开启。
# l* }; e0 d7 M- j$ Z. @$ l4 I 效果评价
3 D0 S) m' Q5 P# m; U 以下是作者在 ResNet18 中使用的最大批量大小:
# ^$ T( ]; F0 N/ o& B: U0 _4 g- \% V

C% ?3 u( P$ _5 M% B( m6 F
因此通过合理应用这一系列修改,DALI 可以使得最大批量大小在 CPU 或 GPU 模式下提升 50%
: B, h: q2 _# v
而在 Shufflenet V2 0.5 上,如果批大小为 512,则 DALI GPU 和 CPU 能够处理的批大小如下:
' z) T5 a: O3 e9 m& @% W; Z; B' |! y 
/ B/ Y9 w' Z3 B3 Z1 B5 f5 [
可以看到,即使是 CPU,其处理速度也达到了每秒 1800 张图像,速度超过了 TorchVision。
4 O+ I, d) o' m, T% G' |/ ?4 @ 所有的测试都在 Google Cloud V100 实例下运行:包含 12 个 vCPU(6 个物理内核),78GB 内存,以及使用 ApexFP16 进行训练。
1 k* V1 l1 A. C! U: G- F1 X
因此,通过 DALI,一个 Tesla V100 GPU 就可以达到将近每秒 4000 张图像。接近英伟达有 8 个 V100 GPU 的 DGX-1 的性能,尽管使用的是小模型。
: [- `$ [" c0 h3 G) D1 I" b
https://towardsdatascience.com/nvidia-dali-speeding-up-pytorch-876c80182440
* u; l& T* p) Q( y
加入机器之心(全职记者 / 实习生):hr@jiqizhixin.com
/ M- T2 ^6 n1 t$ n, [0 V, I1 { 投稿或寻求报道:content @jiqizhixin.com
7 d/ z2 x; t K; P6 o! S
广告 & 商务合作:bd@jiqizhixin.com
+ ?; z" q3 {( }; {' A, G