昇思MindSpore进阶教程--数据处理性能优化(下)

大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。
技术上主攻前端开发、鸿蒙开发和AI算法研究。
努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧

操作系统性能优化

由于MindSpore的数据处理主要在Host端进行,运行环境的配置也会对处理性能产生影响,主要体现在存储设备、NUMA架构和CPU计算资源等方面。

  1. 存储设备

数据的加载过程涉及频繁的磁盘操作,磁盘读写的性能直接影响了数据加载的速度。当数据集较大时,推荐使用固态硬盘进行数据存储,固态硬盘的读写速度普遍较普通磁盘高,能够减少I/O操作对数据处理性能的影响。

一般地,加载后的数据将会被缓存到操作系统的页面缓存中,在一定程度上降低了后续读取的开销,加速了后续Epoch的数据加载速度。用户也可以通过MindSpore提供的单节点缓存技术,手动缓存加载增强后的数据,避免了重复的数据加载和数据增强。

  1. NUMA架构

NUMA的全称为Non-Uniform Memory Access,即非一致性内存访问,是为了解决传统的对称多处理器(SMP)架构中的可扩展性问题而诞生的一种内存架构。在传统架构中,多个处理器共用一条内存总线,容易产生带宽不足、内存冲突等问题。

而在NUMA架构中,处理器和内存被划分为多个组,每个组称为一个节点(Node),各个节点拥有独立的集成内存控制器(IMC)总线,用于节点内通信,不同节点间则通过快速路径互连(QPI)进行通信。对于某一节点来说,处在同节点内的内存被称为本地内存,处在其他节点的内存被称为外部内存,访问本地内存的延迟会小于访问外部内存的延迟。

在数据处理过程中,可以通过将进程与节点绑定,来减小内存访问的延迟。一般我们可以使用以下命令进行进程与node节点的绑定,或者可以通过配置环境变量export DATASET_ENABLE_NUMA=True使得每个训练进程绑定至不同的numa节点。

numactl --cpubind=0 --membind=0 python train.py

  1. CPU计算资源

尽管可以通过多线程并行技术加快数据处理的速度,但是实际运行时并不能保证CPU计算资源完全被利用起来。如果能够人为地事先完成计算资源配置的设定,将能在一定程度上提高CPU计算资源的利用率。

  • 计算资源的分配

在分布式训练中,同一设备上可能开启多个训练进程。默认情况下,各个进程的资源分配与抢占将会遵循操作系统本身的策略进行,当进程较多时,频繁的资源竞争可能会导致数据处理性能的下降。如果能够事先设定各个进程的计算资源分配,就能避免这种资源竞争带来的开销。

numactl --cpubind=0 python train.py

  • CPU频率设置

出于节约能效的考虑,操作系统会根据需要适时调整CPU的运行频率,但更低的功耗意味着计算性能的下降,会减慢数据处理的速度。要想充分发挥CPU的最大算力,需要手动设置CPU的运行频率。如果发现操作系统的CPU运行模式为平衡模式或者节能模式,可以通过将其调整为性能模式,提升数据处理的性能。

cpupower frequency-set -g performance

  • 多线程竞争

如果用户在数据处理阶段使用了cv2,numpy,numba三方库,且使用top命令查看CPU时,出现sy占用高,而us占用低,说明出现了线程竞争,那么通过如下方式解决:
如果数据处理阶段有 opencv 的 cv2 操作,那么通过 cv2.setNumThreads(2) 设置 cv2 全局线程数减少线程竞争;
如果数据处理阶段有 numpy 操作,那么通过 export OPENBLAS_NUM_THREADS=1 设置OPENBLAS线程数减少线程竞争;
如果数据处理阶段有 numba 操作,那么通过 numba.set_num_threads(1) 设置并行度来减少线程竞争。

  • CPU/内存占用率高
  • 因为MindSpore Dataset主要是使用Host侧CPU和内存做数据处理,在一些资源(CPU和Memory)比较紧张的环境,在进行数据预处理时会出现CPU占用过高,或者内存占用高的情况。那么可以通过如下方法降低CPU及内存占用率,但同时也会损失一些性能。更详细的使用指导可参考:https://blog.csdn.net/guozhijian521/article/details/123552540

在定义数据集 **Dataset 对象前,设置Dataset数据处理预取的大小,ds.config.set_prefetch_size(2);

在定义 **Dataset 对象时,设置其参数 num_parallel_workers 为1;

如果对 **Dataset 对象进一步使用了 .map(…) 操作,可以设置 .map(…) 的参数 num_parallel_workers 为1;

如果对 **Dataset 对象进一步使用了 .batch(…) 操作,可以设置 .batch(…) 的参数 num_parallel_workers 为1;

如果对 **Dataset 对象进一步使用了 .shuffle(…) 操作,可以把参数 buffer_size 设置减少;

如果有多个 .map(…) 操作,可以将多个 .map(…) 操作合并为一个。

单卡训练 VS 多卡训练并行度优化建议

在使用MindSpore进行单卡或多卡训练时,num_parallel_workers参数的设置应遵循以下原则:

  • 各数据加载和处理操作所设置的num_parallel_workers参数之和应不大于CPU所支持的最大线程数,否则将造成各个操作间的资源竞争。

  • 在设置num_parallel_workers参数之前,建议先使用MindSpore的Profiler(性能分析)工具分析训练中各个操作的性能情况,将更多的资源分配给性能较差的操作,即设置更大的num_parallel_workers,使得各个操作之间的吞吐达到平衡,避免不必要的等待。

  • 在单卡训练场景中,提高num_parallel_workers参数往往能直接提高处理性能,但在多卡场景下,由于CPU竞争加剧,一味地提高num_parallel_workers可能会导致性能劣化,需要在实际训练中尝试使用折中数值。

自动数据加速

MindSpore提供了一种自动数据调优的工具——Dataset AutoTune,用于在训练过程中根据环境资源的情况自动调整数据处理管道的并行度,最大化利用系统资源加速数据处理管道的处理速度。详细用法请参考自动数据加速。

数据异构加速

MindSpore提供了一种运算负载均衡的技术,可以将MindSpore的Tensor运算分配到不同的异构硬件上,一方面均衡不同硬件之间的运算开销,另一方面利用异构硬件的优势对运算进行加速。详细用法请参考数据异构加速。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明志刘明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值