Created by: chenwhql
2020 Q1对动态图DataLoader进行了第二阶段优化:
- 原理:主要是通过共享内存和序列化LoDTensor进一步减少主进程附属读取线程的开销,将更多工作移到子进程中执行
- 效果:通过此项优化,大多数情况下,主进程中读取下一批数据的时间降到0.0001 s左右,读取数据几乎不再引入负担(数据读取及预处理负担较重时,建议结合fluid.io.xmap_reader使用进一步提升速度)
- PR:https://github.com/PaddlePaddle/Paddle/pull/22541
目前该PR已经Merge到develop中,现基于(Paddle v1.7分支)以及(develop分支)进行优化效果对比测试与整体测试。
一. 测试项点:
1. 性能测试
- DataLoader数据传输前后的一致性(上次天宇测试过,复用即可,这里不介绍此项)
- 使用本次优化后多进程DataLoader,相比使用上次优化后的多进程DataLoader的整体训练速度提升
- 使用本次优化后多进程DataLoader,相比使用普通reader或单进程DataLoader的整体训练速度提升
- 使用本次优化后多进程DataLoader,动态图与静态图在相同模型(mobilenet v1)上的训练速度对比
2. 稳定性测试(在性能测试时同步确认即可)
- 测试过程中不会意外崩溃,不会hang
- 测试结束后,
/dev/shm
目录下无残留文件
补充:以上仅为示例性测试,期待QA同学补充更专业、更完备的测试
二. 测试前准备:
- 拉取models repo,checkout到97808bc9,然后拉取本PR所在分支至当前models repo(用最新的也可以,但有冲突需要自行解决)
- 对于mobilenet,transformer和ptb_lm几个模型需要提前准备好测试用的数据集,按照readme说明准备即可,或者线下沟通
- 注意如果用docker进行测试,需要先扩大共享存储空间,docker默认的共享存储
/dev/shm
空间为64M,本次优化加入了共享内存机制,训练过程中会产生内存映射文件,/dev/shm
的空间需要大于(DataLoader数目DataLoader队列长度一个Batch数据大小),设置指令为docker run --name [Name of container] -it --shm-size=20g -v $PWD:/paddle <imagename> /bin/bash
。如果空间不足,会报BusError。如果用开发机直接训练,则无需关注此问题。
三. 测试概要
- 基于models/dygraph下面mnist, resnet, se_resnet, ptb_lm, mobilenet,transformer共6个模型进行测试
- 测试过程中上述模型均仅执行一个epoch,其他模型参数保持models repo默认设置不变
- 在上述所有模型中加入记录train部分时间的测试代码,累计在末尾打印
- 对于mnist, resnet, se_resnet, ptb_lm 4个模型,分别测试使用普通reader,DataLoader单进程,DataLoader多进程(视情况+xmap_reader)的训练时间,对于XX.py, XX_sp.py, XX_mp.py三个文件,此外还通过载入fake data的方式(每个step都载入固定数据,读数据无开销)测试了优化上限,对应文件为XX_base.py。此外对于ResNet,使用xmap_reader进行外部多线程加速,能够进一步提高速度,对应文件为XX_mp_xmap.py
- 对于mobilenet和transformer,由于这两个模型已经改为默认使用DataLoader单进程模式训练,并且使用完整的公开数据集,故仅测试DataLoader单进程,DataLoader多进程的训练时间,增加了arg进行控制(transformer经验证在单进程时,读取数据的代价已经是ms甚至us级了,数据见附录,本次优化不会带来显著提升,且训练时间过长,后面略过相关速度对比)
- 对上述模型,示例性质的4个模型mnist, resnet, se_resnet, ptb_lm,仅测试单卡数据(这几个模型单epoch训练时间本身就很短,最长不超过3分钟,本次实验认为,多卡测试必要性不大),对于使用公开数据集进行完整训练的2个模型mobilenet和transformer,分别进行单卡和多卡的训练测试,日志存储到本地
- 静态图Mobilenet v1测试,执行PaddleCV/image_classification/MobileNetV1.sh即可
四. 各项点测试方法
1 & 2. 动态图整体训练速度提升测试
第一步:基于Paddle v1.7的测试
- 拉取paddle repo,checkout至release/1.7分支,分布式编译并安装
cmake .. -DPY_VERSION=3.5 -DCMAKE_BUILD_TYPE=Release -DWITH_GPU=ON -DCUDA_ARCH_NAME=Auto -DWITH_TESTING=ON -DWITH_DISTRIBUTE=ON
- 返回dygraph目录下,执行dataloader_test_v1.7.sh,等待测试结果,测试模型较多,时间较长
- 执行parse_dataloader_test_result.py,将结果输出至终端,保存待后续分析
第二步:基于本次优化[+xmap_reader]的测试
- 拉取paddle repo,checkout至develop分支,分布式编译并安装
- 返回dygraph目录下,执行dataloader_test.sh,等待测试结果,测试模型较多,时间较长
- 执行parse_dataloader_test_result.py,将结果输出至终端,保存待后续分析
第三步:综合前两步的数据,可以得出测试项点1&2的结论,注意如下
- 确保测试期间,测试所用机器不被其他任务占用,CPU负载对测试的影响比较明显
- 前两步测试完后,除多进程(mp)的测试数据,其他几项(base,sp等)的耗时应该是接近的,如果相差较大,说明测试时机器环境有差别,用作对比并不严谨(故测试请保留前两步测试的数据)
- transformer一个epoch训练时间较长,建议和其他的分开测试
3. 动静态图训练速度对比测试
- 该实验仅在mobilenet v1上进行测试
- 贾晓同学之前对于mobilenet在静态图和动态图训练至收敛的时间进行了测试,如果条件允许,建议使用DataLoader多进程对mobilenet重新进行完整测试,和之前静态图训练的时间进行再次对比
五. 自测数据及说明
- 开发机:yq01-gpu-255-137-12-00,8卡P40。单核CPU 26个
- GCC版本:5.4.0
- 时间数据:单位s,均为models/dygraph下模型单epoch的训练速度
5.1 本次优化整体训练速度提升(单卡)
5.1.1 小模型测试数据(使用示例数据集flower)(单位s)
模型 | 多进程DataLoader 1.7 | 多进程DataLoader 新 | 多进程DataLoader新+xmap_reader |
---|---|---|---|
resnet | 62.04 | 53.75 (+15.4%) | 45.19 (+37.3%) |
5.1.2 完整模型测试数据(使用ImageNet完成数据集,300G)(单位s)
模型 | 卡数 | 多进程DataLoader 1.7 | 多进程DataLoader 新 |
---|---|---|---|
mobilenet v1 | 单卡 | 6614.68 | 3249.51 (+103.6%) |
mobilenet v1 | 4卡 | 1627.00 | 931.98 (+74.6%) |
补充说明:
- mobilenet加速效果比较明显是由于之前的多进程DataLoader在mobilenet上并未按预期机制进行加速,反而带来负担,此次优化后,加速效果一次性释放导致提升明显,理论上本次优化提升应该与ResNet相近
- mnist, se_resnet, ptb和transformer在上次优化后读取数据已经几乎无代价了,所以本次优化也没有明显提升,两次采集数据又有一定误差,所以不适合在这里对比,测试数据在后续附件中提供
- fluid.io.xmap_reader()是paddle中模型训练会用到的一个外部多线程数据读取加速器,能够进一步提高速度
- mobilenet默认使用fluid.io.xmap_reader(),所以未做区分
5.2 优化至今整体训练速度提升(当前状态)
5.2.1 相对reader的速度提升
单卡测试数据(单位s)
模型 | Reader | 单进程DataLoader | 多进程DataLoader | +xmap_reader | FakeData |
---|---|---|---|---|---|
mnist | 10.85 | 10.16 | 6.44 (+68.5%) | - | 6.04 |
resnet | 94.36 | 83.56 | 53.75 (+75.6%) | 45.19 (+108.8%) | 44.04 |
se_resnet | 177.24 | 131.20 | 124.49 (+42.4%) | - | 123.10 |
ptb_lm | 120.33 | 108.56 | 108.27 (+11.1%) | - | 107.43 |
- 如上所示,使用优化后DataLoader训练速度已经接近使用Fake数据,已经接近优化极限,数据读取基本没有代价了
- 除ResNet外,其他几个示例模型,不需要xmap加速也能够接近极限
5.2.2 大模型上多进程相比单进程提升
单卡测试数据 (单位s)
模型 | 单进程DataLoader | 多进程DataLoader |
---|---|---|
mobilenet v1 | 5041.77 | 3249.51 (+55.2%) |
多卡测试数据 (单位s)
模型 | 单进程DataLoader | 多进程DataLoader |
---|---|---|
mobilenet v1 4卡 | 1169.64 | 931.98 (+25.5%) |
- transformer数据读取开销在1.7上就已经接近没有了,训练所需时间太长,此处不再对比
- 在paddle v1.7(单进程DataLoader)上测试日志如下,最后一列为数据读取耗时:
2020-02-29 13:38:58,806-INFO: step_idx: 36500, epoch: 0, batch: 36500, avg loss: 3.289963, normalized loss: 1.914222, ppl: 26.841858, speed: 2.35 step/s, read_t: 0.000104 s
2020-02-29 13:39:42,517-INFO: step_idx: 36600, epoch: 0, batch: 36600, avg loss: 3.538529, normalized loss: 2.162789, ppl: 34.416260, speed: 2.29 step/s, read_t: 0.000076 s
2020-02-29 13:40:24,988-INFO: step_idx: 36700, epoch: 0, batch: 36700, avg loss: 3.930707, normalized loss: 2.554967, ppl: 50.942993, speed: 2.35 step/s, read_t: 0.000068 s
2020-02-29 13:41:06,989-INFO: step_idx: 36800, epoch: 0, batch: 36800, avg loss: 3.469208, normalized loss: 2.093467, ppl: 32.111286, speed: 2.38 step/s, read_t: 0.000069 s
2020-02-29 13:41:50,941-INFO: step_idx: 36900, epoch: 0, batch: 36900, avg loss: 3.771409, normalized loss: 2.395669, ppl: 43.441223, speed: 2.28 step/s, read_t: 0.000101 s
2020-02-29 13:42:33,598-INFO: step_idx: 37000, epoch: 0, batch: 37000, avg loss: 3.790491, normalized loss: 2.414751, ppl: 44.278130, speed: 2.34 step/s, read_t: 0.000087 s
2020-02-29 13:43:15,805-INFO: step_idx: 37100, epoch: 0, batch: 37100, avg loss: 3.694344, normalized loss: 2.318604, ppl: 40.219173, speed: 2.37 step/s, read_t: 0.000075 s
total train time: 15999.807209730148 s
5.3 动静态图训练速度对比测试(mobilenet v1)
- 单卡,1 epoch, batch size 256, 数据集ImageNet(单位s)
模型 | 静态图 | 动态图 | 差距 |
---|---|---|---|
mobilenet v1 | 3091.73 | 3249.51 | 慢5.1% |
附录1 - 与竞品PyTorch的现状对比
- 以下测试数据来自于忠朴(benchmark相关工作)
- 从数据来看,目前使用本次优化的DataLoader,paddle动态图数据读取的开销占比,在数据预处理开销不是很重的情况下,已能够基本与PyTorch持平,且整体训练速度也并不逊色于PyTorch
- 以下PyTorch测试数据是使用多个数据读取子进程(num_workers=15)加速得到的结果,但paddle的数据是仅使用单个子进程达到的结果,在子进程加速效率上,目前paddle优于pytorch(可以在同等条件下,将pytorch DataLoader num_workers设为1进行对比)
- paddle多子进程加速也已经正在评审中,后续会进一步完善
- 数据集,ImageNet100
- 单元格内数据:整体训练时间 (前方向时间占比),剩下部分即为数据读取占比
- 时间单位s
- batch size 128
模型 | ResNet50 | Mobilenet V1 | Mobilenet V2 |
---|---|---|---|
Paddle | 637.79 (99.30%) | 230.07 (95.78%) | 275.30(97.53%) |
PyTorch | 660.61 (99.68%) | 260.20 (99.06%) | 312.48 (98.63%) |
附录2 - 原始测试结果日志
paddle v1.7
- 动态图
./dataloader_test_log_v1.7/mnist_base - total train time: 5.36728048324585 s
./dataloader_test_log_v1.7/resnet_base - total train time: 44.04554986953735 s
./dataloader_test_log_v1.7/se_resnet_base - total train time: 126.03753447532654 s
./dataloader_test_log_v1.7/ptb_base - total train time: 120.04909157752991 s
./dataloader_test_log_v1.7/mnist - total train time: 10.986091136932373 s
./dataloader_test_log_v1.7/resnet - total train time: 94.45858144760132 s
./dataloader_test_log_v1.7/se_resnet - total train time: 180.60072875022888 s
./dataloader_test_log_v1.7/ptb - total train time: 109.37627410888672 s
./dataloader_test_log_v1.7/mnist_sp - total train time: 10.393652439117432 s
./dataloader_test_log_v1.7/resnet_sp - total train time: 81.51971364021301 s
./dataloader_test_log_v1.7/se_resnet_sp - total train time: 133.56749939918518 s
./dataloader_test_log_v1.7/ptb_sp - total train time: 115.9285204410553 s
./dataloader_test_log_v1.7/mnist_mp - total train time: 6.618200302124023 s
./dataloader_test_log_v1.7/resnet_mp - total train time: 62.04571604728699 s
./dataloader_test_log_v1.7/se_resnet_mp - total train time: 128.6871235370636 s
./dataloader_test_log_v1.7/ptb_mp - total train time: 112.6711585521698 s
./dataloader_test_log_v1.7/mobilenet_v1_sp - total train time: 4722.7984828948975 s
./dataloader_test_log_v1.7/mobilenet_v1_mp - total train time: 6614.678883552551 s
./dataloader_test_log_v1.7/transformer_sp - total train time: 15999.807209730148 s
./dataloader_test_log_v1.7/transformer_mp - total train time: 16001.910835266113 s
./dataloader_test_log_v1.7/mobilenet_4_sp.v1/workerlog.0 - total train time: 1162.7970054149628 s
./dataloader_test_log_v1.7/mobilenet_4_mp.v1/workerlog.0 - total train time: 1627.0009558200836 s
./dataloader_test_log_v1.7/transformer_8_sp/workerlog.0 - total train time: 2845.75257897377 s
./dataloader_test_log_v1.7/transformer_8_mp/workerlog.0 - total train time: 2848.07351398468 s
paddle develop [2e9e8c0]
- 动态图
./dataloader_test_log/mnist_base - total train time: 6.0436460971832275 s
./dataloader_test_log/resnet_base - total train time: 44.04603886604309 s
./dataloader_test_log/se_resnet_base - total train time: 123.10595202445984 s
./dataloader_test_log/mnist - total train time: 10.85465383529663 s
./dataloader_test_log/resnet - total train time: 94.36293935775757 s
./dataloader_test_log/se_resnet - total train time: 177.24715065956116 s
./dataloader_test_log/mnist_sp - total train time: 10.158140420913696 s
./dataloader_test_log/resnet_sp - total train time: 83.56420588493347 s
./dataloader_test_log/se_resnet_sp - total train time: 131.19789123535156 s
./dataloader_test_log/mnist_mp - total train time: 6.44164252281189 s
./dataloader_test_log/resnet_mp - total train time: 53.75628590583801 s
./dataloader_test_log/se_resnet_mp - total train time: 124.4934389591217 s
./dataloader_test_log/mobilenet_v1_sp - total train time: 5041.7729778289795 s
./dataloader_test_log/mobilenet_v1_mp - total train time: 3249.5140879154205 s
./dataloader_test_log/resnet_mp_xmap - total train time: 45.19542956352234 s
./dataloader_test_log/ptb - total train time: 120.32730889320374 s
./dataloader_test_log/ptb_mp - total train time: 108.27302289009094 s
./dataloader_test_log/ptb_sp - total train time: 108.55681037902832 s
./dataloader_test_log/ptb_base - total train time: 107.42545175552368 s
./dataloader_test_log/mobilenet_4_sp.v1/workerlog.0 - total train time: 1169.6357305049896 s
./dataloader_test_log/mobilenet_4_mp.v1/workerlog.0 - total train time: 931.982990026474 s
- 静态图 mobilenet v1
total train time: 3091.728137731552 s