当前位置: 首页 > 网络应用技术

Cann AICPU占用时间消耗分析和优化探索

时间:2023-03-08 17:32:08 网络应用技术

  摘要:本文使用更大等价作为测试操作员。操作员的计算逻辑相对简单(输出= Input1> = Input2)。

  在CAN CAN运算符的实际开发过程中,操作员的功能通常是正常的,但是性能远低于TensorFlow基准测试BID。在对此问题的响应中,本文使用更大等于的测试操作员,这是相对较高的简单地计算逻辑(输出= input1> = input2)。调度是主体。

  该测试平台是配备Ascend910a的OpenLAB提供的Ascend服务器,Cann Toolkit版本编号为5.0.2alpha005。

  自我开发的测试代码是指修改的CAC625F243DFE7B04DBBB2A82059CD0E4349F77D1,该范围进行了修改,可优化广播操作性能。自动设置的平行阈值:广播操作的平行阈值是8K和广播的广播操作,并计算出32k的计算。

  加速。

  测试数据我设置了两批数据,涉及广播操作,而不涉及广播操作。Float32,Float32,Float32,Float32,Float32,Float32,Float32和Float64。,128K,256K,1M,1M,2M,8M,总共14个数据量表梯度。详细的数据量表与形状的相应关系具有相应的关系:如下:

  该部分旨在测试单线处理数据的性能与张量流操作员之间的性能差距。为了避免影响测试结果的结果,该测试数据使用不涉及广播操作的数据批次。

  图1单线程时间消耗率

  可以看出,对于低于2K的数据量的小型数据量表,Cann操作员与TensorFlow相比具有一定的性能优势,但是随着数据量的增加,Cann Operator的性能具有显着的性能,尤其是UINT8TYPES的数据,降解程度非常严重,性能降解高达6.57倍。对于非-C ++标准float16数据类型,两者都使用EIGEN库中的半数据类型来替换它,并且测试结果更接近。

  图2计算1K数据时间消耗

  我还测试了16K-8M数据的CANN和TF单核计算所消耗的时间。

  可以看出,随着数据类型占用空间的增加,TensorFlow的比例比例增加了。杂项,Cann的INT8和UINT8的时间与INT16相似。此功能也反映在INT8和UINT8.16 -bit计算的时间耗尽比率中。CANN在Float32和Float64中的两种数据类型的性能也非常奇怪。随着数据量的增加,它需要大量波动。在矢量化代码和性能分析的分析中,分析和优化了具体情况。

  Canndev的主要仓库更大等于运营商,尝试使用特征图库的广播操作来避免CannDev源代码的广播性能不足的问题,但加速了传入的并行计算。自我开发的香脂使用CannDev Warehouse for Canndev Warehouse类使用Bast Cast类广播以完善和特殊性,是否需要广播情况,并为不同的数据量表设定平行阈值。

  本节测试了涉及无线电操作的两批数据,而不涉及广播操作。它旨在测试CannDev提供的方法以及Eigen提供的广播操作的性能优势以及自我开发的Busatons的性能优势。

  图3没有广播操作的时间比例

  图4广播操作的时间比例

  从结果可以看出,当未打开广播操作时,自我开发的儿子的性能比现有操作员更好。当直接操作小型数据量时,现有运算符与现有运算符不同。对于处理,性能具有一定的优势。由于多线程卷,性能要比现有操作员好得多。

  但是,在打开广播操作之后,由于平行阈值设置为8K,因此小数据的量与单线线程数据相同。可以看出,CANN的当前BCAST性能不如Eigen实施的广播。预测,自我开发的预算绩效远远超过了现有的运营商。

  与Eigen实施实施的BCAST相比,TensorFlow实施的广播操作具有很大的性能优势。由CANNN实施的两家BCAST也是一个单线播放的8-26次,同时领先Cann。

  由于参考操作员是广播优化的运算符,因此我设置了一个对照组,其阈值与较小操作员的阈值相同(包括2K广播操作的计算,以及将广播操作计算为7K)。为了验证其并行阈值值,这是合理的。为了避免影响测试结果的结果,该测试数据使用不涉及广播操作的数据批次。

  测试结果如下:

  图5限制阈值消耗时间的比例阈值较少的操作员和自我开发的Busin阈值

  可以看出,较小操作员的平行阈值设置是不合理的。在8K数据的范围内,大量的时间消耗增加了,耗时的主题是平行的通信,即时间 - 耗费。可以得出结论,临界点在并行中接近1。

  在进行单个线程性能分析时,我注意到了一个非常奇怪的现象。INT8和INT16花了很多时间(见图2),这引起了我的注意。处理数据时,处理器会消耗和处理。数据与固定点的数量或浮点数,数据级别以及处理数据调用的指令有关。当处理相同数量的INT8和INT16数据时,INT16时间高于INT8。请注意TensorFlow,INT8和UINT8的执行时间花费时间小于INT16。

  现代处理器通常支持SIMD(单个指令流式传输大多数数据流)。通过将数据包装在矢量寄存器中,计算一个计算指令中的多个数据以实现DLP(数据并行性)以实现加速数据 - 强度计算计算计算操作。大量运算符的计算过程不包括分支选择结构。简单地重复计算逻辑,并且适用于SIMD加速。

  检查信息并发现Ascend910处理器中的AICPU是16核Taishan Core。通过系统查询,它支持AARCH64指令集,其中还包括NEON指令集。

  我试图将组件代码嵌入C ++实施代码中以实现手动矢量化,并且确实得到了极大的改进。尽管从理论上手动矢量化可以实现最高的矢量化,但由于不同处理器提供的SIMD扩展指令集,是不同的,不同的应用程序也很复杂且可变。移植程度很低,很难继续优化。考虑到未来的运算符代码可能需要迁移到不同体系结构的CPU,例如X86-64,ARM,ARM,ARM,,,,,,,,,,地位。最后选择编译器以自动生成目标处理器SIMD扩展程序的向量程序。自动矢量化程序员无需关心底层提供的SIMD扩展程序的结构和指令集。他们只需要清楚地表达该程序中的并行性,这在很大程度上解决了高绩效代码移植能力的问题。

  查询CannDev的主要仓库代码内容,相关关键字仅在TFPlugin中出现,以优化相关的关键字。检查CMAKELISTS.TXT的编译选项,仅进行O2优化。从编译器编译AICPU代码为GCC之后,通过检查GCC文档,O2中包含的编译选项除了O1优化选项外包含以下选项,但还包括包括以下选项:

  可以看出,表3中不包含编译选项,因此我们可以通过添加-ftree-vectorize(包括-ftree-loop-vectorize)来编译该选项,从自动矢量化,优化结果如下:

  图6单线量化计算1K数据时间消耗时间消耗

  观察图6结果,您可以看到单个线程代码优化的代码性能得到了极大的改进。在同一时间,我们还可以观察到相同符号类型的相同数量的计算时间或浮动计算的计算 -点数正在消耗数据位的比例。数据。

  如图

  尝试将张量中的一半数据转换为float,然后将其保存到临时的浮动阵列中。性能降低了。在元素转换后对数据类型转换分配的间接费用的分析要大于矢量化的性能改善。

  如图

  图9量化的多线程的时间 - 累积比例

  从图9可以看出,在矢量化之后,所有C ++本机数据类型的性能都比TensorFlow运算符更好。

  观察图10。进行矢量化优化后,有效提高了操作员的性能,但是我们可以看到,当数据量为128K时,某些数据类型的性能不如优化。根据数据大小,可以针对不同的数据类型执行更精细的并行阈值设置。

  图10向量或不包含广播操作(需要广播张量的元素数为1)

  在优化矢量化后,我还测试了单位元素的特殊情况。可以看出,由于未调用广播操作,但直接解决了单个元素指针。结果,性能也得到了显着提高。

  但是不幸的是,由于需要执行广播操作时,张量中的元素需要调用Bcast类GetBroidXindex和GetBroidCastyIndex方法来计算广播操作的地址偏移。它包含更复杂的计算。对矢量化的优化,开放临时空间的开销和分配的开销远大于矢量化的性能改善。因此,如何优化此过程尚待研究。

  图11打开-ftree -vectorize

  可以从图11中可以看出,在打开-Free -Free -vectorize编译选项后,编译器不仅执行自动SIMD优化,而且在周期上执行了揭开式操作,这有助于将循环范围降低开销,并提供指令。- 平行线,并优化管道的调度。

  对于Float16的数据类型,通过阅读特征库3.3.9的源代码,您可以看到,当计算设备为CPU时,绝大多数计算(运算符/除外)计算结果将转换为半数据类型。代码片段如下:

  图12一半数据类型运算符> = eigen库中的函数定义

  该实现方法涉及两种数据类型转换,并且由于它不调用ARM本机数据类型,因此SIMD不能优化它,并且不利于回收。实际的计算效率远低于其他本机数据类型。

  图13反映代码,左为gcc11.1,右为clang9.0.0

  通过咨询ARM架构的官方文档,我发现ARMV8.2-A包括半精度的浮点指令,这避免了单个精确浮点之间的转换。因此,生成了更高的性能代码。它还表明AICPU可以调用数据类型__FP16来实现本质上支持的一半精度浮动数 - 点数字。当然,GCC编译器当前支持FP16的支持。目前,它只能优化诸如ADD和指令集之类的操作。<=11.1是转成float再进行比较,而Clang>= 9.0.0可以生成具有相应的SEMI -CRECISION浮动 - 点号的相应的SIMD指令集代码。

  但是,__FP16是ARM C语言扩展。在FP16的X86-64平台上,仅支持原始的耕作储量。计算需要转换为浮点。GCC7.3无法编译。可以编译clang。为了确保代码的可移植性,不建议使用此数据类型。

  是否有高移植和高性能实现计划?当我翻转EIGEN更新日志时,我发现在2021/04/19更新的EIGEN3.4 -RC1版本中,Eigen :: Half通过__FP16实施了。由ARM支撑,并改善了所有后端的所有向量支撑和手臂,并在矩阵计算中设置了霓虹灯指令。

  图14特征更新日志

  图15 eigen3.4.0半。

  图16添加职业代码(左为__fp16,在中间3.4.0版本eigen :: fall,右边是版本3.3.9 eigen :: falm)

  通过观察图16的反映代码,可以看出编译器已成功地称为FP16 SIMD指令集指令。该代码更有效,不仅避免了两种类型的转换,而且还增加了周期中计算数据的量(SIMD一次计算8个FP16数据,并且未启用SIMD指令。计算4个数据,并且订单卷远大于优化版本)。

  由于个人对朋友和商人的源代码的熟悉程度高于TensorFlow,因此选择比较对象作为Pytorch。他们具有部分优化的SIMD。例如,根据目录ATE/SRC/ATE/CPU/VEC,在一定程度上避免使用实现文件中的嵌入式SIMD函数,以导致代码可读性读取。同时,通过一系列环境宏定义,启用目标CPU的CPU体系结构可以启用相应的体系结构SIMD函数,以基于自动矢量化的基础,以进一步多功能。

  如图

  当然,打开方向化是完美的吗?当然不是,矢量化具有某些局限性。

  1.固定SIMD扩展组件的矢量寄存器的长度。如果矢量寄存器的长度太长,并且基本块中同一语句的数量较小,则程序不能为矢量。

  2. SIMD对数据地址是否连续存在很大影响。当访问地址不在对齐边界上时,需要执行其他位移和合并操作,以获取所需矢量的要求。Non -QI访问不仅添加额外的访问,还添加了特殊操作(例如位移和合并操作等)要获取满足SIMD扩展组件要求的向量数据。由于张量的数据逻辑地址是对齐的,因此此问题对元素智能类别没有很大影响。

  3.由于迭代不足,或者在基本块向量中没有足够的句子,因此不足以提供与向量寄存器的足够平行的,因此有必要执行不充分的SIMD矢量化。

  4.通过实现运算符中编译器或编译器提供的内部手写编译代码或内部功能来添加SIMD指令。从理论上讲,手动矢量化可以达到最高程度的矢量化程度。每个收集是不同的,这将导致代码的移植能力显着降低,并且很难继续优化。当前代码的优化具有一定的限制。

  5.周期将导致一定程度的肿胀。

  6. ARM的霓虹灯扩展的浮点数计算并未完全实现符合IEEE 754标准的浮点操作,尤其是非规范值将被视为0.当优化选项时,一些不安全的浮动浮动 - 点计算CCC编译器将会不在自动矢量化中实现,这也进一步限制了ARM SIMD的性能。

  1.根据CANNDEV源代码仓库的当前汇编选项,各种数据类型的性能在4K或更多时具有较大的性能差距,张力量和张力量为4K或更多,而INT8和UINT8则是时间的。它可以根据16bit.Float16的加工CannDev和Tensorflow进行计算。使用了一半的特征库。性能差距是所有数据类型中最小的,但差距比仍然高达1.3倍。

  2.目前,CANNDEV源代码中的更大等价运算符未启用多核,并且在没有广播的情况下不专门。因此,表现远低于自我开发的儿子而没有广播的表演。数据量CANAFTER多核,自我开发的操作员的性能超过了源仓库。

  3.自我开发的计算是指设计源代码中的操作员较少。两个运算符的计算逻辑基本上是相同的,但是较低的运算符的平行阈值设计较低,当8K数据量表以8K数据量表的比例出现时,所有数据类型都会显然出现。峰值,平行阈值后的情况得到改善。

  4.目前,CannDev主仓库的汇编选项尚未启用自动向量。打开自动矢量化后,可以大大改进可以正确定向的代码性能。

  5.从汇编指令的角度来看,探索了操作员代码的矢量化。__FP16 ARM的本机支持未实现Half Data类型的EIGEN <3.4版本,因此无法优化诱人,EIGEN3.4-RC1和后来的ARM。该版本的底层通过__FP16和可以正确调用SIMD指令,并且可以大大提高性能。

  1.优化较小操作员的并行阈值,以使关键数据量加速度比率尽可能接近1。

  2.打开编译器自动矢量化选项-ftree -vectorize,以完全提高时钟周期中CPU的计算效率。

  3.将特征版本升级为3.4和后续版本,在交叉汇编过程中指定相应的ARM架构,并打开FP16支持,例如-march = ARMV8.2+FP16,可以实现FP16对ARM上FP16的本机支持平台。该设备执行SIMD优化和循环,以有效地提高ARM体系结构上的Eigen ::一半的性能。

  4.优化BCAST实现的逻辑。当前版本依赖的操作员是否需要进行广播操作,并提取三个特殊情况以进行手动实施(没有广播,x是元素,y为元素),并且实现了操作员。大量冗余代码。应该通过判断是否进行广播并通过统一界面访问元素的操作来抽象。

  5.优化BCAST的元素索引方法的实现以获得元素索引。目前,仓库中的BCAST性能远低于tensorflow的广播,而Tensorflow的广播却是在Eigen库的广播之后。目前,GetBroidcastXindex方法的实现对编译器不友好。

  本文只是AICPU操作员探索AICPU操作员的时间和优化的简单分析和优化解决方案。分析和优化思想相对粗糙。解决沟通优化计划。