Paddle/DeepSpeech2 数据读入上的一些问题
Created by: lispc
问题描述
在这个 repo 的 DeepSpeech2 代码中,应用层的 _padding_batch 函数,框架层的 feeder 和 gradient_machine.forwardBackward 是在一个线程顺序做的。这种方案在速度上,不是最优的。因为前两者耗时较大(都是需要0.3s量级的事情),而且本来可以 pipeline 地并行做掉。
我的方案
方案概述
Step 1: 把 DataFeeder 拆成两部分,第一部分是 list of ndarrays to one big ndarray,第二部分是 the final ndarray to paddle.argument Step 2: 把 instance 的 reading 和 processing, batch 的 padding, 和刚才拆出来的 DataFeeder 第一部分(list of ndarrays to one big ndarray)放在第一个进程中,把生成的 ndarray 训练数据通过 pipe 传递到第二个进程,第二个进程从 pipe 读数据,然后做训练。
设计原因
我的方案几个设计上的考虑:
- 分进程的原因:担心 GIL
- 拆 Feeder 的原因:ndarray 可以从 pipe 用 pickle 传递,但是 paddle.argument 不能跨进程传递
操作方式
把框架层的代码(trainer.py, data_feeder.py, dataprovider_converter.py)拷贝到应用层,然后做了很多修改。
实验结果
我测试我的这份加速代码的结果:单batch平均(第10个到第20个)从2.5s下降到1.8s(很接近forwardbackward时间了),其中 reader + feeder 时间 从 0.65s 降低到 0.15s。端到端加速1/3,效果明显。
汇总观点
- 现在 Paddle DataFeeder 的设计可能是有问题的,在框架层面限制一块挺大的计算量必须在 forward/backward 前完成,对速度影响较大。
- 现在 DS2 batch_reader 里面的 padding 也是在 forward/backward 线程做的,这个倒是可以在应用层而不是框架层直接改掉。
可以一起讨论一下观点~