当前位置: 首页 > 后端技术 > Python

技术解读倚天ECS实例——Arm芯片Python-AI算力优化

时间:2023-03-25 19:23:56 Python

深度学习技术已广泛应用于图像识别、搜索推荐等领域。近年来,各大CPU厂商也逐渐将AI算力纳入重点发展方向。通过《Arm 芯片 Python-AI 算力优化》,我们将看到龙蜥社区的ArmArchitectureSIG(SpecialInterestGroup)使用最新的Arm指令集来优化Python-AI推理工作负载的性能。表现。倚天ECS实例AI推理软件优化阿里云推出的倚天ArmECS实例,具备AI场景推理加速能力。我们将学习加速的原理和相关的软件生态适配。卷积神经网络(CNN)广泛应用于图像和语音领域,神经网络算法比传统算法消耗更多的计算能力。为了探索计算的优化,我们进一步观察AlexNet模型(一个CNN)推理过程中每一层的计算资源消耗比例。可以看出名为conv[1-5]的5个卷积层消耗了90%的计算资源,所以优化CNN推理的关键是优化卷积层的计算。让我们仔细看看如何将卷积核应用于图像:1.使用im2col将图像根据卷积核的大小转换成几个patch2.将多个卷积核扩展成几个向量3.对组成图像块的矩阵和由多个卷积核组成的矩阵使用矩阵乘法。上一页的计算使用矩阵乘法。为什么我们不使用更直接的迭代计算方法,而是使用需要额外内存的矩阵乘法呢?这里有两个关键因素:深度学习的卷积是计算密集型的,一个典型的计算需要涉及5000万次乘加运算,所以计算的优化非常重要。计算机科学家对矩阵乘法运算进行了深入探索,矩阵乘法运算可以优化得非常快。在Fortran世界中,GEMM(通用矩阵乘法)已成为一种通用运算:通过重新排列数据,精心设计计算过程,并使用多线程和向量指令,运算速度可以比普通运算快十倍以上自己实现的简单版本。因此,使用矩阵运算的好处值得额外的开销。由于AI推理广泛使用矩阵乘法,现在很多硬件加速矩阵运算:NVIDIAVolta架构引入tensorcores,可以通过systolicarrays在硬件层面高效处理混合精度IntelAMX(AdvancedMatrixExtensions)的矩阵乘法支持矩阵乘法ARMSME(ScalableMatrixExtension)支持向量外积运算,加速矩阵乘法虽然GPU在AI算力方面远高于CPU,但CPU易于部署,不需要在主机和设备之间复制内存。人工智能推理场景有它们的位置。目前还没有支持AMX或者SME的硬件可以大规模使用。现阶段,我们应该如何优化CPU上的AI推理能力?我们首先需要了解BF16数据类型。BF16(BrainFloat16)是由GoogleBrain开发设计的16位浮点格式。BF16与传统的IEEE16位浮点数相比,取值范围与IEEE单精度浮点数(FP32)相同,但精度较差。研究人员发现,在AI训练和推理中,使用BF16可以节省一半的内存,并获得接近单精度浮点数的准确率。根据右图,BF16索引的位数与FP32相同,所以BF16和FP32相互转换只需要截去尾数即可。左下图是tensorflow源码中的转换实现。引入BF16的巨大价值在于,当今许多硬件计算的瓶颈是寄存器宽度或访问内存的速度。更紧凑的内存表示通常可以实现更高的计算吞吐量。在理想情况下,BF16可以提高一倍的吞吐量(FLOPS)。虽然我们今天不能大规模使用支持AMX/SME的硬件,但是Armv8.6-A提供了bf16扩展,使用有限的128bit向量寄存器,通过BFMMLA指令进行矩阵乘法:输入A:大小为2*4BF16矩阵,按行存储输入B:BF16矩阵,大小为4*2,按列存储输出C:FP32矩阵,大小为2*2该指令执行16次浮点数乘法,单次执行16次执行浮点数加法运算,计算吞吐量非常高。阿里巴巴向OpenBLAS项目贡献了sbgemm(s表示返回单精度,b表示输入bf16)的硬件加速实现。从GEMM吞吐量来看,BF16比FP32GEMM吞吐量提升100%以上。倚天ECS实例是目前市场上为数不多的支持bf16指令扩展的ARM服务器之一。目前已经支持Tensorflow和Pytorch的AI推理。在Tensorflow下,可以通过OneDNN+ACL(ArmComputeLibrary)来使用BFMMLA。Pytorch已经支持OneDNN+ACL,但目前还处于实验状态,表现不佳。.但Pytorch也支持OpenBLAS作为其计算后端,因此您可以通过OpenBLAS享受ARMbf16扩展带来的性能优势。可以看到,与默认的eigen实现相比,启用OneDNN+ACL后,perf获取的计算热点由fmla(Vectormultiplicationandaddition)转换为bfmmla,计算能力明显提升。从工作负载评估的角度,上图比较了两个模型:g7:IntelIceLake实例g8m:YitianARM服务器左侧条形图中的蓝色柱表示计算能力的比较,橙色柱表示使用考虑性价比后的倚天处理器。可以看出,在Resnet50和BERT-Large模型的推理场景下,经过软件优化的倚天处理器可以获得大约两倍的性价比收益。在上面我们已经看到,想要使用倚天处理器获得更高的收益,软件版本的选择非常重要。随意选择tensorflow或pytorch包可能会遇到:arm架构不适配,安装失败,软件未适配bf16扩展或环境参数不对,无法发挥硬件的全部计算能力,以及性能折扣需要谨慎选择计算后端,比如目前的pytorchOpenBLAS速度更快,所以我们提供了一个Docker镜像来帮助云端用户充分利用倚天ECS实例的AI推理性能:accc-registry。cn-hangzhou.cr.aliyuncs.com/tensorflow/tensorflowaccc-registry.cn-hangzhou.cr.aliyuncs.com/pytorch/pytorch通过serverless能力充分释放算力除了启用更多的硬件指令外,另一种充分释放硬件的方式计算能力是通过无服务器架构来提高CPU利用率。Python作为一种动态语言,其模块是动态导入的,所以启动速度不是Python的强项,这也制约了Pythonworkload在serverless场景中的普及。启动Python应用程序的主要耗时过程是模块导入。导入Python模块的步骤是:找到模块所在文件,获取代码对象code_object,执行代码对象。第二步,在第一次加载模块时编译.py文件,得到code_object,为了减少以后加载的开销,Python解释器会将code_object序列化缓存到.pyc文件中。即使通过缓存机制优化了模块导入过程,读取和反序列化.pyc文件仍然很耗时。这里我们使用OpenJDK的AppCDS的思路:将堆上的code_object复制到内存映射文件(mmap)中。下次加载模块时,直接使用mmap中的code_object。这个框架有两个难点:Python的code_object是散布在整个堆上的,不连续,所以mmap复制整个堆是不可行的。我们采用的方法是以code_object为根,遍历对象图,将感兴趣的内容拷贝并紧凑排列,Python的code_object会引用.data段中的变量。地址每次运行随机变化,因此mmap中的指针无效。我们的方案是遍历所有对象,对.data段的指针进行偏移修复。由于本项目共享python的code_object,所以名称为code-data-share-for-python,简称pycds。我们测试了bota3、numpy、flask等常用Python工具,平均可以节省20%的模块导入时间。对于已有的python应用,无需修改任何代码即可轻松使用pycds:#安装pycdspipinstallcode-data-share#安装pycds#生成模块列表PYCDSMODE=TRACEPYCDSLIST=mod.lstpython-c'importnumpy'#生成archivepython-c'导入cds.dump;cds.dump.run_dump("mod.lst","mod.img")'#使用归档时间PYCDSMODE=SHAREPYCDSARCHIVE=mod.imgpython-c'importnumpy'real0m0.090suser0m0.180ssys0m0.339s#比较基线时间python-c'importnumpy'real0m0.105suser0m0.216ssys0m0.476s我们只需要安装PyPI,修改环境变量运行,使用cdsAPIdump到现有应用启动速度加快。code-data-share-for-python是一个新项目,需要大家的参与和反馈。欢迎通过以下链接了解和使用:https://github.com/alibaba/code-data-share-for-pythonhttps://pypi.org/project/code-data-share-for-pythonARM架构SIG链接地址:https://openanolis.cn/sig/ARM_ARCH_SIG原文链接本文为阿里云原创内容,未经允许不得转载。