• ResNet50性能调优分享


    网络训练跑通了,精度OK了,对很多人来说可能已经万事大吉了,但如果网络需要在生产环境跑,还有一个点不得不去关注,那就是性能。对于大的网络,训练一次可能需要上月的时间,这时候就真正的体会到时间就是金钱了。提高网络的性能,缩短训练的时间,可能会节省上百万的金钱。 下面给大家介绍下之前对ResNet50网络的性能调优案例,希望能帮助到大家。调优过程中用到了MindSpore中的调试调优工具:MindInsight,不仅可以调试性能,还可以调试精度,感兴趣的同学可以到官网了解下:MindInsight文档 — MindSpore master 文档

    现象

    我们将ResNet50网络batch size设置为32(代码可参考MindSpore ModelZoo中的ResNet50网络,当前代码已经是调优后的。本次主要给大家介绍下调优的经历),跑网络训练后发现单step时间约为90ms,性能很差。通常batch size为32时,单step耗时应在20ms以内。

    原因分析

    分析过程中,我们主要用到了MindInsight中的Profiler模块。如何跑Profiler收集性能数据大家可以到官网上查看教程,此次不再赘述。 将性能数据用UI页面可视化后,我们开始了此次的性能调优过程。 首先我们先看页面里的迭代轨迹部分。迭代轨迹将训练过程分为了3部分:迭代间隙表示前一个迭代结束到后一个迭代开始的时间,该段时间可以认为是后一个迭代等待数据的时间;前反向时间表示的是真正的前反向计算的时间;迭代拖尾表示的是反向完成后进行梯度更新的时间。从下图中我们看到迭代间隙的时间占了整个迭代的很大部分,因此我们需要重点关注数据处理的性能。

    第二步,我们到数据准备详情页面,确认数据处理是否是性能瓶颈点。查看数据准备详情页面中的迭代间隙标签页,我们观察到,数据队列在前期有较多的数据,后期数据的个数变为0,分析原因是前期在图编译阶段已经开始了数据集的加载和增强,队列中随即缓存了多条数据;而后期正常训练开始后,队列中的数据被消费的速度要快于被生产的速度,因此数据队列逐渐变为空,说明此时数据变成了瓶颈。观察主机队列也是同样的情况。综合分析,正常训练过程中,数据处理为性能瓶颈点。

    第三步,我们到数据准备详情页面中的数据处理标签页来查看具体问题。通过观察数据处理标签页的算子间队列关系,我们发现,Queue_3及其之后的队列使用率较低,即MapOp_3作为生产者生产数据的速度较慢,因此可以判定MapOp_3的性能还有优化空间,需要对该算子进行性能优化。

    ResNet50性能调优分享

    网络

    应用性能调优

    发表于 2021-10-30 12:02:484964查看

    网络训练跑通了,精度OK了,对很多人来说可能已经万事大吉了,但如果网络需要在生产环境跑,还有一个点不得不去关注,那就是性能。对于大的网络,训练一次可能需要上月的时间,这时候就真正的体会到时间就是金钱了。提高网络的性能,缩短训练的时间,可能会节省上百万的金钱。 下面给大家介绍下之前对ResNet50网络的性能调优案例,希望能帮助到大家。调优过程中用到了MindSpore中的调试调优工具:MindInsight,不仅可以调试性能,还可以调试精度,感兴趣的同学可以到官网了解下:MindInsight文档 — MindSpore master 文档

    现象

    我们将ResNet50网络batch size设置为32(代码可参考MindSpore ModelZoo中的ResNet50网络,当前代码已经是调优后的。本次主要给大家介绍下调优的经历),跑网络训练后发现单step时间约为90ms,性能很差。通常batch size为32时,单step耗时应在20ms以内。

    原因分析

    分析过程中,我们主要用到了MindInsight中的Profiler模块。如何跑Profiler收集性能数据大家可以到官网上查看教程,此次不再赘述。 将性能数据用UI页面可视化后,我们开始了此次的性能调优过程。 首先我们先看页面里的迭代轨迹部分。迭代轨迹将训练过程分为了3部分:迭代间隙表示前一个迭代结束到后一个迭代开始的时间,该段时间可以认为是后一个迭代等待数据的时间;前反向时间表示的是真正的前反向计算的时间;迭代拖尾表示的是反向完成后进行梯度更新的时间。从下图中我们看到迭代间隙的时间占了整个迭代的很大部分,因此我们需要重点关注数据处理的性能。

    第二步,我们到数据准备详情页面,确认数据处理是否是性能瓶颈点。查看数据准备详情页面中的迭代间隙标签页,我们观察到,数据队列在前期有较多的数据,后期数据的个数变为0,分析原因是前期在图编译阶段已经开始了数据集的加载和增强,队列中随即缓存了多条数据;而后期正常训练开始后,队列中的数据被消费的速度要快于被生产的速度,因此数据队列逐渐变为空,说明此时数据变成了瓶颈。观察主机队列也是同样的情况。综合分析,正常训练过程中,数据处理为性能瓶颈点。

    第三步,我们到数据准备详情页面中的数据处理标签页来查看具体问题。通过观察数据处理标签页的算子间队列关系,我们发现,Queue_3及其之后的队列使用率较低,即MapOp_3作为生产者生产数据的速度较慢,因此可以判定MapOp_3的性能还有优化空间,需要对该算子进行性能优化。

    我们查看了数据处理的代码,发现map算子的num_parallel_workers参数没有设置,而该参数的默认为1,代码如下:

    1. if do_train:
    2. trans = [
    3. C.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
    4. C.RandomHorizontalFlip(prob=0.5),
    5. C.Normalize(mean=mean, std=std),
    6. C.HWC2CHW()
    7. ]
    8. else:
    9. trans = [
    10. C.Decode(),
    11. C.Resize(256),
    12. C.CenterCrop(image_size),
    13. C.Normalize(mean=mean, std=std),
    14. C.HWC2CHW()
    15. ]
    16. data_set = data_set.map(operations=trans, input_columns="image")
    复制

    因此我们分析可以尝试提高该算子的并发数来提高网络的性能。

    效果验证

    我们将num_parallel_workers参数调整为12后,再次运行训练脚本,优化参考代码如下: data_set = data_set.map(operations=trans, input_columns="image", num_parallel_workers=12) 通过MindInsight性能分析页面观察迭代轨迹,可以看到迭代间隙时长由72.8ms缩短到0.25ms,单step时长由90ms缩短到18.07ms。

    ResNet50性能调优分享

    网络

    应用性能调优

    发表于 2021-10-30 12:02:484964查看

    网络训练跑通了,精度OK了,对很多人来说可能已经万事大吉了,但如果网络需要在生产环境跑,还有一个点不得不去关注,那就是性能。对于大的网络,训练一次可能需要上月的时间,这时候就真正的体会到时间就是金钱了。提高网络的性能,缩短训练的时间,可能会节省上百万的金钱。 下面给大家介绍下之前对ResNet50网络的性能调优案例,希望能帮助到大家。调优过程中用到了MindSpore中的调试调优工具:MindInsight,不仅可以调试性能,还可以调试精度,感兴趣的同学可以到官网了解下:MindInsight文档 — MindSpore master 文档

    现象

    我们将ResNet50网络batch size设置为32(代码可参考MindSpore ModelZoo中的ResNet50网络,当前代码已经是调优后的。本次主要给大家介绍下调优的经历),跑网络训练后发现单step时间约为90ms,性能很差。通常batch size为32时,单step耗时应在20ms以内。

    原因分析

    分析过程中,我们主要用到了MindInsight中的Profiler模块。如何跑Profiler收集性能数据大家可以到官网上查看教程,此次不再赘述。 将性能数据用UI页面可视化后,我们开始了此次的性能调优过程。 首先我们先看页面里的迭代轨迹部分。迭代轨迹将训练过程分为了3部分:迭代间隙表示前一个迭代结束到后一个迭代开始的时间,该段时间可以认为是后一个迭代等待数据的时间;前反向时间表示的是真正的前反向计算的时间;迭代拖尾表示的是反向完成后进行梯度更新的时间。从下图中我们看到迭代间隙的时间占了整个迭代的很大部分,因此我们需要重点关注数据处理的性能。

    第二步,我们到数据准备详情页面,确认数据处理是否是性能瓶颈点。查看数据准备详情页面中的迭代间隙标签页,我们观察到,数据队列在前期有较多的数据,后期数据的个数变为0,分析原因是前期在图编译阶段已经开始了数据集的加载和增强,队列中随即缓存了多条数据;而后期正常训练开始后,队列中的数据被消费的速度要快于被生产的速度,因此数据队列逐渐变为空,说明此时数据变成了瓶颈。观察主机队列也是同样的情况。综合分析,正常训练过程中,数据处理为性能瓶颈点。

    第三步,我们到数据准备详情页面中的数据处理标签页来查看具体问题。通过观察数据处理标签页的算子间队列关系,我们发现,Queue_3及其之后的队列使用率较低,即MapOp_3作为生产者生产数据的速度较慢,因此可以判定MapOp_3的性能还有优化空间,需要对该算子进行性能优化。

    我们查看了数据处理的代码,发现map算子的num_parallel_workers参数没有设置,而该参数的默认为1,代码如下:

    1. if do_train:
    2. trans = [
    3. C.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
    4. C.RandomHorizontalFlip(prob=0.5),
    5. C.Normalize(mean=mean, std=std),
    6. C.HWC2CHW()
    7. ]
    8. else:
    9. trans = [
    10. C.Decode(),
    11. C.Resize(256),
    12. C.CenterCrop(image_size),
    13. C.Normalize(mean=mean, std=std),
    14. C.HWC2CHW()
    15. ]
    16. data_set = data_set.map(operations=trans, input_columns="image")

    因此我们分析可以尝试提高该算子的并发数来提高网络的性能。

    效果验证

    我们将num_parallel_workers参数调整为12后,再次运行训练脚本,优化参考代码如下: data_set = data_set.map(operations=trans, input_columns="image", num_parallel_workers=12) 通过MindInsight性能分析页面观察迭代轨迹,可以看到迭代间隙时长由72.8ms缩短到0.25ms,单step时长由90ms缩短到18.07ms。

    至此,我们完成了ResNet50网络的性能调优工作。

    总结

    MindInsight调优工具对性能调优和精度调优提供了大量的数据,并形成了一套完整的方法论,需要的同学可以参考奥。

  • 相关阅读:
    每日一题 —— LC. 805 数组的均值分割
    LeetCode-141. 环形链表【哈希表,快慢指针】
    OpenCV图像变换
    .gitignore文件不起作用
    PMP每日一练 | 考试不迷路-8.20(包含敏捷+多选)
    数组实现单链表 Java详细讲解
    推荐系统实战2——EasyRec 推荐框架环境配置
    『无为则无心』Python面向对象 — 54、重写和super()函数
    牛客网刷题 | BC62 统计数据正负个数
    在Springboot项目中使用Redis提供给Lua的脚本
  • 原文地址:https://blog.csdn.net/Kenji_Shinji/article/details/126747167