华为云AI开发平台ModelArts性能调优五板斧_云淘科技

性能调优相对来说门槛较高,对PyTorch以及昇腾AI处理器的理解越深刻,越能发挥昇腾AI处理器的计算能力,从而提高训练性能。一般情况下,通过对PyTorch代码做profiling,从而基于数据分析,调整代码,尽可能发挥硬件能力,但在做profiling数据分析前,通常可简单地基于性能优化五板斧先尝试做性能调优:

NPU亲和API以及亲和优化器替换
算子二进制调优
AOE自动性能调优
多进程绑核
优化数据处理

NPU亲和API以及亲和优化器替换

可对训练代码中的部分API替换成NPU亲和API、亲和优化器或者NPU自定义算子,往往能够提升训练性能,但需要注意的是,在一些场景下,替换后的算子可能会对模型精度有影响,所以适配后,需要验证精度,如果确认有影响,需要在精度和性能之间做取舍。

NPU亲和API替换

可使用pytorch_analyse.sh工具扫描训练代码中的NPU亲和API,NPU亲和API适配昇腾AI处理器,性能更优。具体用法详见此处。示例如下:

./pytorch_analyse.sh -i $HOME/chatglm-6b/ -o $HOME/result/ -v 1.11.0 -m affinity_apis

当前适配的NPU亲和API请见此处。
“/usr/local/Ascend/ascend-toolkit/latest/tools/ms_fmk_transplt/pytorch_analyse.sh”为默认路径。
pytorch_analyse.sh只能扫描指定目录下的.py文件,所以如果代码中引入了其他目录或者第三方库的代码,需要对其他目录或者第三方库的代码也做同样的扫描,并基于扫描结果对相应代码做API替换。

NPU亲和优化器替换

PyTorch原生优化器在训练过程中,往往需要下发多个NPU算子完成梯度和参数的更新计算,过多的算子下发,可能造成NPU空等。可将PyTorch优化器替换成NPU亲和优化器提高训练性能,详情请见此处。

NPU亲和API替换

NPU亲和API替换优化相对较难,需要对正在训练的模型架构有比较深入的理解,在此基础上,可尝试对代码中的部分操作通过NPU自定义算子做等价替换,NPU自定义算子列表详见这里。NPU自定义算子对一些常见的算子组合基于NPU进行了算子融合,训练迁移过程中可有意识地对训练代码中的实现用这些自定义算子替换。

例如激活函数gelu的常见实现如下:

def gelu_impl(x):
    return 0.5 * x * (1.0 + torch.tanh(0.7978845608028654 * x *(1.0 + 0.044715 * x * x)))

可通过NPU自定义算子torch_npu.fast_gelu替换提高训练性能。

算子二进制调优

PyTorch Adaptor框架提供与算子编译相关的二进制配置参数,可设置模型编译时是否优先在线编译,以此优化模型训练性能。在main函数训练逻辑开始前通过以下函数设置(True为启动优先在线编译、False为取消优先在线编译)。

torch_npu.npu.set_compile_mode(jit_compile=False)

对于固定shape场景和动态shape场景,是否优先在线编译对训练性能带来不同的效果:

固定shape场景:固定shape是指在模型计算过程中,模型的输入和输出的shape是固定的。如果优先在线编译,可根据当前获得的算子信息,进行融合和优化,在线编译出运行性能更优的算子。反之,则编译优化少,性能降低。
动态shape场景:动态shape是指在模型计算过程中,模型的输入和输出存在多种shape。如果对动态shape的算子优先编译,会导致编译时间长训练性能差。如果取消优先编译,会优先查找当前编译好的算子二进制配置文件,若存在则不在线编译算子;若不存在,再进行在线编译。此时虽然编译优化少,但是没有编译时间,模型训练性能大概率比配置为优先编译高。

总结:

如果模型中无动态shape,启动优先在线编译,可提高训练性能。
如果模型中只有动态shape(该情况较少),关闭优先在线编译,模型训练性能大概率会更高。
既有动态shape也有固定shape,启动优先在线编译对训练性能是否提升无法确定,因此可以在调整训练代码后,分别尝试开关优先在线编译后根据训练性能的优劣再设置。

Snt9B芯片默认关闭了优先在线编译,可通过以下命令获取当前模式。若返回为False,代表已启动优先在线编译。

print(torch.npu.is_jit_compile_false())

算子会根据该开关走不同的代码逻辑,如出现jit_compile切换后,代码运行失败的情况,需要联系昇腾技术支持获取帮助。

AOE自动性能调优

AOE(Ascend Optimization Engine)是一款自动调优工具,当训练模型全部为固定shape时,可选择AOE调优,具体操作参见此处。该优化会进行算子融合,将融合得到的图进行算子粒度切分,针对每一个融合算子子图生成不同的算子调优策略,从而实现最优的算子性能,并将得到的最优策略保存在算子知识库。性能调优期间只要做了代码修改后,可尝试运行AOE自动性能调优。

多进程绑核

相比于x86服务器,ARM服务器通常CPU核数更多,但单核性能更弱,因此更容易触发内核的负载均衡策略,该策略是通过启用进程迁移来降低繁忙的处理器压力。进程迁移会导致进程上下文切换、降低Cache命中率和跨numa内存访问等,从而影响训练性能。

如果使用docker容器作为训练环境,启动容器的时候,通过cpuset-cpus参数指定当前容器绑定的cpu核(如绑定16个cpu核60~75,命令示例为“docker run -d –cpuset-cpus=60-75 myimage bash”),这样容器中的进程只能在指定的CPU核上运行,达到绑核的效果。

优化数据处理

训练性能依赖训练数据是否及时准备好让NPU进行计算,因此需要尽量减少NPU等待数据准备的概率,主要优化方法包括:使用高性能图像预处理工具如opencv、加速数据下沉到NPU设备、数据预取与数据计算并行、减少NPU与CPU数据交互等。

父主题: PyTorch迁移性能调优

同意关联代理商云淘科技,购买华为云产品更优惠(QQ 78315851)

内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家