
# 性能调优
 #### 性能测试
benchmark工具也可用于性能测试，其主要的测试指标为模型单次前向推理的耗时。在性能测试任务中，与精度测试不同，并不需要用户指定对应的输入（inDataFile）和输出的标杆数据（benchmarkDataFile），benchmark工具会随机生成一个输入进行推理，并统计推理时间。执行的示例命令行如下。
```
# shell
benchmark --modelFile=resnet50.mindir --device=Ascend
```
为了简化用户使用，ModelArts提供了Tailor工具便于用户进行Benchmark性能测试，具体使用方式参考[Tailor指导文档](https://support.huaweicloud.com/bestpractice-modelarts/modelarts_10_0166.html)。
在某些推理场景中，模型输入的shape可能是不固定的，因此需要支持用户指定模型的动态shape，并能够在推理中接收多种shape的输入。在CPU上进行模型转换时无需考虑动态shape问题，因为CPU算子支持动态shape；而在昇腾场景上，算子需要指定具体的shape信息，并且在模型转换的编译阶段完成对应shape的编译任务，从而能够在推理时支持多种shape的输入。
绝大多数情况下，昇腾芯片推理性能相比于CPU会好很多，但是也可能会遇到和CPU推理性能并无太大差别甚至出现劣化的情况。造成这种情况的原因可能有如下几种：
1. 模型中存在大量的类似于Pad或者Strided_Slice等算子，其在CPU和Ascend上的实现方法存在差异（硬件结构不同），后者在运算此类算子时涉及到数组的重排，性能较差；
2. 模型的部分算子在昇腾上不支持，或者存在Transpose操作，会导致模型切分为多个子图，整体的推理耗时随着子图数量的增多而增长；
3. 模型没有真正的调用昇腾后端，而是自动切换到了CPU上执行，这种情况可以通过输出日志来进行判断。
 
#### 自助性能调优三板斧
基于上一步完成的性能测试，为了最大化模型推理性能，首先确保当前使用的CANN版本是最新版本（最新版本请见[此处](https://www.hiascend.com/zh/document)），每个迭代的CANN版本都有一定的性能收益。在此基础上，可以进行三板斧自助工具式性能调优。这些调优过程由大量的项目交付经验总结，帮助您获得模型最佳推理性能，重复[性能测试]章节可以验证对应的收益情况。
自助性能调优三板斧分别为：[通过固定shape获取更好的常量折叠]、[AOE性能自动调优]、[自动高性能算子生成工具]。
- **通过固定shape获取更好的常量折叠**
  在MindIR格式转换时（即执行converter_lite命令时），通过指定具体的静态shape，并且打开--optimize参数指定"ascend_oriented"能够获得更好的常量折叠优化效果。inputShape查看方法请见[转换关键参数准备](https://support.huaweicloud.com/bestpractice-modelarts/modelarts_10_1159.html#ZH-CN_TOPIC_0000001701527768__li2293111519485)。
  ```
  Ascend Optimization Engine
  converter_lite --modelFile=resnet50.onnx --fmk=ONNX --outputFile=resnet50 --saveType=MINDIR --inputShape="input.1:1,3,224,224" --optimize=ascend_oriented
  ```
  常量折叠是编译器优化中的通用技术之一，在编译节点简化常量表达。通过多数的现代编译器不会真的产生两个乘法的指令再将结果存储下来，取而代之的是会识别出语句的结构，并在编译时期将数值计算出来而不是运行时去计算（在本例子，结果为2,048,000）。
  ```
  i = 320 * 200 * 32;
  ```
  AI编译器中，常量折叠是将计算图中预先可以确定输出值的节点替换成常量，并对计算图进行一些结构简化的操作，例如ADDN操作，以及在推理过程中的batch normalization操作等。
  以BN折叠为例，如下表示折叠后获得的性能收益。
  图1BN折叠下前向运算性能收益   
  ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000001749527097.png "点击放大") 
- **AOE性能自动调优**
  自动性能调优工具AOE(Ascend Optimization Engine)，可以对于模型的图和算子运行通过内置的知识库进行自动优化，以提升模型的运行效率。开启AOE调优后，模型转换时会自动进行性能调优操作，该过程耗时较长，可能需要数小时。
  AOE性能自动优化在模型转换阶段进行配置（即执行converter_lite命令时），通过--configFile参数指定配置文件aoe_config.ini，配置文件通过aoe_mode参数指定调优模式。可选值有：
  - "subgraph tuning"：子图调优。
  
  - "operator tuning"：算子调优。
  
  - "subgraph tuning, operator tuning"：先进行子图调优，再进行算子调优。
  
  
  推荐先进行子图调优，再进行算子调优，因为先进行子图调优会生成图的切分方式，子图调优后算子已经被切分成最终的shape了，再进行算子调优时，会基于这个最终shape去做算子调优。如果优先算子调优，这时调优的算子shape不是最终切分后的算子shape，不符合实际使用场景。
  本例同时指定了子图调优和算子调优，工具会先进行子图调优，再进行算子调优。
  ```
  # aoe_config.ini
  [ascend_context]
  aoe_mode="subgraph tuning, operator tuning"
  ```
  指定--configFile=aoe_config.ini即可自动进行性能优化。
  ```
  #shell
  converter_lite --modelFile=resnet50.onnx --fmk=ONNX --device=Ascend --outputFile=resnet50_aoe --saveType=MINDIR --configFile=aoe_config.ini
  ```
  命令执行成功后，性能自动优化前后的性能对比会打印到控制台上，同时会生成更为详细的json格式调优报告。
  图2自动调优输出文件   
  ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000001701527780.png "点击放大")
  需要注意的是，并不是所有的模型使用性能自动调优都是有收益的。在本例中，ResNet50模型自动调优收益甚微（模型转换时已经做了部分针对性优化），在有些比较复杂的模型场景下可能会有较好的收益。例如VAE_ENCODER模型使用算子调优收益为11.15%。
  图3VAE_ENCODER模型使用AOE自动调优在屏幕上显示日志   
  ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000001749407277.png "点击放大")
  图4AOE自动调优的输出样例   
  ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000001749527093.png "点击放大")
  其中：
  - model_baseline_performance表示调优前模型执行时间，单位为ms。
  
  - model_performance_improvement表示调优后模型执行时间减少百分比。
  
  - model_result_performance表示调优后模型执行时间。
  
  - repo_summary中的信息表示调优过程中使用到的知识库算子个数或者追加到知识库的算子个数。
  
  
  AOE自动调优更多介绍可参考[Ascend转换工具功能说明](https://www.mindspore.cn/lite/docs/zh-CN/r2.3.1/use/cloud_infer/converter_tool_ascend.html)。
  
- **自动高性能算子生成工具**
  自动高性能算子生成工具AKG（Auto Kernel Generator），可以对深度神经网络模型中的算子进行优化，并提供特定模式下的算子自动融合功能，可提升在昇腾硬件后端上运行模型的性能。
  AKG的配置也是在模型转换阶段进行配置（即执行converter_lite命令时），通过指定对应的配置文件akg.cfg，设置对应的akg优化级别，并且在模型转换时参考样例进行对应的配置。
  ```
  # akg.cfg
  [graph_kernel_param]
  opt_level=2
  ```
  执行命令：
  ```
  # shell
  converter_lite --fmk=ONNX --modelFile=model.onnx --outputFile=model --configFile=akg.cfg --optimize=ascend_oriented
  ```
  自动高性能算子生成工具AKG更多介绍可参考[图算融合配置说明](https://www.mindspore.cn/lite/docs/zh-CN/r2.3.1/use/cloud_infer/converter_tool_graph_kernel.html)和[MindSpore AKG](https://gitee.com/mindspore/akg#AKG简述)。
  
 
