---
title: 子图/算子调优
description: "本节介绍TensorFlow训练场景下，如何进行子图/算子调优，包括调优前须知、配置环境变量、调优命令、查看调优结果、性能验证。"
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/devaids/aoe/aoeep_16_031.html
sourcePath: /source/zh/canncommercial/900/devaids/aoe/aoeep_16_031.html
indexId: 0d252198683c58e9c13049e4716dcdc388d438a2aa575f0d1c14613bd3b2827f59
---
# 子图/算子调优

本节介绍TensorFlow训练场景下，如何进行子图/算子调优，包括调优前须知、配置环境变量、调优命令、查看调优结果、性能验证。

#### 调优前须知

1. 请保证训练脚本在AI处理器上执行成功，功能和精度满足预期。
2. 不建议用户绑定训练进程到指定的CPU，请使用系统默认的CPU调度策略。否则可能会影响调优效果。
3. 为提高调优效率，希望用户尽量控制训练步数。一般情况下，通过一个step能完成一次完整的图执行过程，保证图中所有的算子都能遍历一遍完成调优即可。
4. 目前仅支持静态算子，暂不支持动态算子。
5. AOE不支持不同用户同时使用同一device进行调优。
6. 调优前，请确保关闭Profiling功能，关闭内存静态分配方式（即设置static_memory_policy=0，示例为：custom_op.parameter_map["static_memory_policy"].i = 0），避免影响调优结果。关闭Profiling功能具体操作请参见《性能调优工具(https://www.hiascend.com/document/detail/zh/canncommercial/900/devaids/Profiling/atlasprofiling_16_0144.html)》。
7. 不支持多P场景下的调优。
8. 单P场景下的调优，请确保具备如下条件。

  - 调优用户的家目录下磁盘可用空间>=20G。
  - 可用内存>=训练模型需要的内存*TUNING_PARALLEL_NUM。其中TUNING_PARALLEL_NUM的说明请参考    配置文件
。
  - 算子调优时Host CPU建议>= 训练脚本中的进程数 * (TE_PARALLEL_COMPILER + TUNING_PARALLEL_NUM + min(CPU的核数/2, 8) + 50)。其中TE_PARALLEL_COMPILER和TUNING_PARALLEL_NUM的说明请分别参考    表1
和    配置文件
。
  - 子图调优时Host CPU建议>=训练脚本中的进程数 * （ 2 * TUNING_PARALLEL_NUM + TE_PARALLEL_COMPILER）。其中TE_PARALLEL_COMPILER和TUNING_PARALLEL_NUM的说明请分别参考    表1
和    配置文件
。
  - device核数>=模型中所有算子使用的最大核数。
  - device内存：和模型相关，和模型的内存复用相关。


#### 配置环境变量

发起调优前，需要添加如下环境变量。- CANN软件基础环境变量
  CANN提供进程级环境变量设置脚本，供用户在进程中引用，以自动完成环境变量设置。执行命令参考如下，以下示例均为root或非root用户默认安装路径，请以实际安装路径为准。

```
# 以root用户安装toolkit包后配置环境变量
source /usr/local/Ascend/cann/set_env.sh
# 以非root用户安装toolkit包后配置环境变量
source ${HOME}/Ascend/cann/set_env.sh
```


- AOE工具依赖Python，以Python3.7.5为例，请以运行用户执行如下命令设置Python3.7.5的相关环境变量。

```
#用于设置python3.7.5库文件路径
export LD_LIBRARY_PATH=/usr/local/python3.7.5/lib:$LD_LIBRARY_PATH
#如果用户环境存在多个python3版本，则指定使用python3.7.5版本
export PATH=/usr/local/python3.7.5/bin:$PATH
```


  Python3.7.5安装路径请根据实际情况进行替换，您也可以将以上命令写入~/.bashrc文件中，然后执行source ~/.bashrc命令使其立即生效。

- 配置调优模式：

```
# 1：子图调优，2：算子调优。
export AOE_MODE=2
```


  Atlas A2 训练系列产品 / Atlas A2 推理系列产品 场景下，不支持AOE_MODE=1。 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 场景下，不支持AOE_MODE=1。

- 调优前也可参考如下示例配置其他环境变量，但为可选配置，相关说明请参考  表1
。

```
export ASCEND_DEVICE_ID=0
export TUNE_BANK_PATH=/home/HwHiAiUser/custom_tune_bank
export TE_PARALLEL_COMPILER=8
export REPEAT_TUNE=False
```


- 用户可将设置环境变量的命令写入自定义脚本，方便后续执行。

- 除了通过环境变量方式指定调优模式，还可通过修改训练脚本相应参数指定调优模式，具体请参考  通过修改训练脚本配置调优模式（TensorFlow 1.15）
，考虑到操作复杂度，建议通过设置环境变量方式指定调优模式。


**表1 环境变量说明**

| 环境变量 | 说明 | 可选/必选 |
| --- | --- | --- |
| AOE\_MODE | 调优模式，支持如下取值： 1：子图调优 2：算子调优 | 必选 |
| ASCEND\_DEVICE\_ID | 通过该环境变量指定AI处理器的逻辑ID。 取值范围[0,N\-1]，默认为0。其中N为当前物理机/虚拟机/容器内的设备总数。 | 可选 |
| TUNE\_BANK\_PATH | 可通过此环境变量指定调优后自定义知识库的存储路径。 设置的存储路径必须为绝对路径或相对于执行AOE调优引擎所在路径的相对路径，配置的路径需要为已存在的目录，且执行用户具有读、写、可执行权限。若配置的TUNE\_BANK\_PATH路径不存在或用户无权限，则调优进程会报错并退出。 自定义知识库存放路径的优先级为：TUNE\_BANK\_PATH>ASCEND\_CACHE\_PATH>默认，TUNE\_BANK\_PATH和ASCEND\_CACHE\_PATH详细信息请参考《环境变量参考(https://www.hiascend.com/document/detail/zh/canncommercial/900/maintenref/envvar/envref\_07\_0001.html)》。 子图自定义知识库 若不配置此环境变量，请使用env命令查询ASCEND\_CACHE\_PATH是否存在，若存在，自定义知识库存储在：${ASCEND\_CACHE\_PATH}/aoe\_data；若不存在，自定义知识库默认存储在：${HOME}/Ascend/latest/data/aoe/custom/graph/${soc\_version}。 若配置了此环境变量，自定义知识库存储在该环境变量路径下。 算子自定义知识库 若不配置此环境变量，请使用env命令查询ASCEND\_CACHE\_PATH是否存在，若存在，自定义知识库存储在：${ASCEND\_CACHE\_PATH}/aoe\_data/${soc\_version}；若不存在，自定义知识库默认存储在：${HOME}/Ascend/latest/data/aoe/custom/op/${soc\_version}。 若配置此环境变量，则调优后的最优策略存储在配置路径的${soc\_version}目录。 说明： 在多用户共享知识库场景下，共享知识库的用户需要设置TUNE\_BANK\_PATH为同一路径，并且对配置的路径具有读、写权限。 若调优时自定义了知识库路径，后续进行模型转换时，若想直接使用自定义知识库，也需要配置此环境变量。 | 可选 |
| TE\_PARALLEL\_COMPILER | 算子编译所需环境变量。 网络模型较大时，可通过配置此环境变量，开启算子的并行编译功能。 TE\_PARALLEL\_COMPILER的值代表算子编译进程数（配置为整数），当取值大于1时开启算子的并行编译功能。开启AOE调优场景下：配置不能超过CPU核数\*80%/AI处理器的个数，取值范围：1~32，默认值为8。 由于该环境变量能够加速算子编译，所以可以加快涉及算子编译的相关流程调优。 | 可选 |
| REPEAT\_TUNE | 是否重新发起调优，此环境变量在开启子图调优或算子调优的场景下生效。 如果知识库（内置或者自定义）中已经存在网络模型中的调优case（针对某shape的调优策略），则会跳过此case的调优流程，若想重新发起调优，可设置此环境变量为True。例如某些算子进行了逻辑的变更，如GEMM算子新增了支持ND的输入，该情况下需要设置此环境变量后，重新发起调优。 取值范围：True或者False，默认值为False。 | 可选 |


#### 执行调优

如需进行子图调优或算子调优，直接执行训练脚本，即可按照指定的调优模式自动调优。

- 如需指定调优路径，执行训练前，可以修改训练脚本中的  work_path
或者  aoe_config.work_path
。
- 如需对指定算子进行调优，执行训练前，可以修改训练脚本中的  aoe_config_file
或者  aoe_config.aoe_config_file
。


#### 查看调优结果

查看调优结果。训练过程中，调优的关键日志信息如下，调优后的结果文件请参见算子调优结果文件和子图调优结果文件。```
# TFAdapter开启调优
in tune mode, training graph handled by tools.
# 工具启动调优
Aoe tuning graph.
```


调优完成后，若满足自定义知识库生成条件（请参见图2和图3），则会生成自定义知识库。

自定义知识库存放路径的优先级为：TUNE_BANK_PATH>ASCEND_CACHE_PATH>默认，TUNE_BANK_PATH和ASCEND_CACHE_PATH详细信息请参考《环境变量参考(https://www.hiascend.com/document/detail/zh/canncommercial/900/maintenref/envvar/envref_07_0001.html)》。- 子图自定义知识库
  若未配置TUNE_BANK_PATH和ASCEND_CACHE_PATH（可以使用env命令查询是否配置），自定义知识库默认存储在：${HOME}/Ascend/latest/data/aoe/custom/graph/${soc_version}。

- 算子自定义知识库
  若未配置TUNE_BANK_PATH和ASCEND_CACHE_PATH（可以使用env命令查询是否配置），自定义知识库默认存储在：${HOME}/Ascend/latest/data/aoe/custom/op/${soc_version}。


#### 性能验证

子图调优完成后，请还原代码，使用调优后的自定义知识库（如何使用请参见如何使用调优后的自定义知识库）重新训练，验证性能是否提高。

算子调优完成后，请还原代码，并刷新算子编译缓存，即将op_compiler_cache_mode设置为force（详见《TensorFlow 1.15模型迁移(https://www.hiascend.com/document/detail/zh/TensorFlowCommercial/900/migration/tfmigr1/tfmigr1_000001.html)》），使用调优后的自定义知识库（如何使用请参见如何使用调优后的自定义知识库）重新训练，验证性能是否提高。


#### 算子调优结果文件

算子调优结果文件的存放路径优先级为：ASCEND_WORK_PATH > 默认（执行调优的工作目录），若未配置ASCEND_WORK_PATH（可以使用env命令查询是否配置，ASCEND_WORK_PATH详细信息请参考《环境变量参考(https://www.hiascend.com/document/detail/zh/canncommercial/900/maintenref/envvar/envref_07_0001.html)》），算子调优结果文件存放在默认路径（执行调优的工作目录）。

调优过程中，实时生成的结果文件命名为“aoe_result_opat_${timestamp}_${pidxxx}.json”，记录了调优过程中被调优的算子信息。其中${timestamp}为时间戳，格式为：年月日时分秒毫秒，“${pidxxx}”中的“xxx”为进程ID。

内容格式如下所示，可以包括多个调优任务，各字段含义请参见表2。tid为线程ID。

```
{
"report_${timestamp}_${tid}": [
{
"basic": {
"tuning_name": "调优任务名",
"tuning_time(s)": 44
}
},
{
"OPAT": {
"opat_tuning_result": "tuning successful",
"repo_modified_operators": [
{
"op_name": "bert/encoder/layer_10/attention/self/Softmax_OPAT_0",
"op_type": "SoftmaxV2",
"tune_performance": {
"Format": {
"performance_after_tune(us)": 26.876,
"performance_before_tune(us)": 58.781,
"performance_improvement": "118.71%",
"update_mode": "add"
}
}
},
{
"op_name": "bert/encoder/layer_8/attention/output/dense/MatMulbert/encoder/layer_8/attention/output/add",
"op_type": "MatMulV2",
"tune_performance": {
"Schedule": {
"performance_after_tune(us)": 15.71,
"performance_before_tune(us)": 16.71,
"performance_improvement": "6.37%",
"update_mode": "add"
}
}
}
],
"repo_summary": {
"repo_add_num": 2,
"repo_hit_num": 10,
"repo_reserved_num": 10,
"repo_unsatisfied_num": 1,
"repo_update_num": 0,
"total_num": 13
}
}
}
],
"report_${timestamp}_${tid}": [
........
.....
```

调优失败时（即opat_tuning_result显示为"tuning failed"时），还会显示调优失败的算子的op_name列表。

```
"tuning_failed_operators": [
"res4a_branch1"
]
```


**表2 字段含义**

| 字段名称 | 字段名称 | 字段名称 | 字段名称 | 含义 |
| --- | --- | --- | --- | --- |
| basic | \- | \- | \- | \- |
| \- | tuning\_name | \- | \- | 调优任务名称。 |
| \- | tuning\_time(s) | \- | \- | 调优耗费的时长，单位：s。 调优中断场景下（比如coredump、oom）不记录该字段。 |
| OPAT（没有可调优的算子时，该段信息不存在。） | \- | \- | \- | \- |
| \- | opat\_tuning\_result | \- | \- | 调优结果，成功时显示为"tuning successful",失败时显示为"tuning failed"，调优未完成、异常中断退出时显示为"tuning incomplete"。 |
| \- | repo\_modified\_operators | \- | \- | 调优后，调优策略有增加和更新的算子详细信息。 |
| \- | \- | op\_name | \- | 算子名称。 |
| \- | \- | op\_type | \- | 算子类型。可以有一个，也可以有多个。当有多个的时候，需要使用[]将多个算子类型括起来。 |
| \- | \- | tune\_performance | \- | 算子性能提升具体信息。 |
| \- | \- | Format或者Schedule或者Impl | \- | 算子的调优模式，包括如下取值： Format：当算子调优过程中使能了Format调优功能，且有Format调优的性能提升时，会出现该字段。 Schedule：当算子调优过程中有Schedule调优的性能提升时，会出现该字段。 Impl：当算子调优过程中有Impl调优的性能提升时，会出现该字段。 |
| \- | \- | \- | performance\_after\_tune(us) | 调优后算子执行时间，单位：us。 |
| \- | \- | \- | performance\_before\_tune(us) | 调优前算子执行时间，单位：us。 |
| \- | \- | \- | performance\_improvement | 调优后算子执行时间减少百分比。 |
| \- | \- | \- | update\_mode | 算子调优策略更新模式，取值如下。 add：增加算子调优策略。 update：更新算子调优策略。 |
| \- | repo\_summary | \- | \- | 记录调优任务中不同状态算子的信息。 |
| \- | \- | repo\_add\_num | \- | 调优前调优策略不在知识库中，调优后调优策略追加到知识库中的调优策略个数。 |
| \- | \- | repo\_hit\_num | \- | 调优过程中调优策略在知识库中的调优策略个数。 |
| \- | \- | repo\_reserved\_num | \- | 调优前调优策略在知识库中，调优后知识库中的调优策略无变化的调优策略个数。 |
| \- | \- | repo\_unsatisfied\_num | \- | 调优前调优策略不在知识库，调优后也未写入知识库的调优策略个数。 |
| \- | \- | repo\_update\_num | \- | 调优前调优策略在知识库中，调优后知识库中的调优策略有更新的调优策略个数。 |
| \- | \- | total\_num | \- | 调优任务中被调优的调优策略总数。 repo\_hit\_num=repo\_update\_num+repo\_reserved\_num total\_num=repo\_add\_num+repo\_hit\_num+repo\_unsatisfied\_num |
| \- | tuning\_failed\_operators | \- | \- | 调优失败的算子的op\_name列表。 说明：可选，当opat\_tuning\_result显示"tuning failed"时才记录该字段。 |


针对每个调优策略有新增或者更新的算子，都会包括如上op_name~update_mode的信息。


#### 子图调优结果文件

子图调优结果文件的存放路径优先级为：ASCEND_WORK_PATH > 默认（执行调优的工作目录），若未配置ASCEND_WORK_PATH（可以使用env命令查询是否配置，ASCEND_WORK_PATH详细信息请参考《环境变量参考(https://www.hiascend.com/document/detail/zh/canncommercial/900/maintenref/envvar/envref_07_0001.html)》），子图调优结果文件存放在默认路径（执行调优的工作目录）。

调优过程中，实时生成的结果文件命名为“aoe_result_sgat_${timestamp}_${pidxxx}.json”，记录了调优过程中被调优的子图信息。其中${timestamp}为时间戳，格式为：年月日时分秒毫秒，“${pidxxx}”中的“xxx”为进程ID。

内容格式如下所示，可以包括多个调优任务，各字段含义请参见表3。tid为线程ID。

```
"report_${timestamp}_${tid}": [
{
"basic": {
"tuning_name": "调优任务名",
"tuning_time(s)": 19
}
},
{
"SGAT": {
"model_baseline_performance(ms)": 5.600486,
"model_performance_improvement": "55.11%",
"model_result_performance(ms)": 3.610442,
"repo_modified_subgraphs": {
"add_repo_subgraphs": [
{
"performance_after_tune(ms)": 3.573203,
"performance_before_tune(ms)": 5.58434,
"performance_improvement": "56.28%",
"repo_key": "1024942313106047484"
}
]
"update_repo_subgraphs": [
{
"performance_after_tune(ms)": 2.573203,
"performance_before_tune(ms)": 4.58434,
"performance_improvement": "78.15%",
"repo_key": "1024942313106057586"
}
]
},
"repo_summary": {
"repo_add_num": 1,
"repo_hit_num": 1,
"repo_reserved_num": 0,
"repo_unsatisfied_num": 120,
"repo_update_num": 1,
"total_num": 121
}
}
}
],
"report_${timestamp}_${tid}": [
.......
.......
```


**表3 字段含义**

| 字段名称 | 字段名称 | 字段名称 | 字段名称 | 含义 |
| --- | --- | --- | --- | --- |
| basic | \- | \- | \- | \- |
| \- | tuning\_name | \- | \- | 调优任务名称。 |
| \- | tuning\_time(s) | \- | \- | 调优耗费的时长，单位：s。 |
| SGAT（子图调优失败时，该段信息不存在。） | \- | \- | \- | \- |
| \- | model\_baseline\_performance(ms) | \- | \- | 调优前模型执行时间，单位: ms。 |
| \- | model\_performance\_improvement | \- | \- | 调优后模型执行时间减少百分比。 |
| \- | model\_result\_performance(ms) | \- | \- | 调优后模型执行时间，单位: ms。 |
| \- | repo\_modified\_subgraphs | \- | \- | 调优后，调优策略有增加和更新的子图详细信息。 |
| \- | \- | add\_repo\_subgraphs | \- | 调优后调优策略有增加的子图，可以没有，也可以有多个。 |
| \- | \- | \- | performance\_before\_tune(ms) | 调优前子图执行时间，单位: ms。 |
| \- | \- | \- | performance\_after\_tune(ms) | 调优后子图执行时间，单位:ms。 |
| \- | \- | \- | performance\_improvement | 调优后子图执行时间减少百分比。 |
| \- | \- | \- | repo\_key | 调优后子图的key值，用于调优知识库查询。 |
| \- | \- | update\_repo\_subgraphs | \- | 调优后调优策略有更新的子图，可以没有，也可以有多个。 |
| \- | \- | \- | performance\_before\_tune(ms) | 调优前子图执行时间，单位: ms。 |
| \- | \- | \- | performance\_after\_tune(ms) | 调优后子图执行时间，单位:ms。 |
| \- | \- | \- | performance\_improvement | 调优后子图执行时间减少百分比。 |
| \- | \- | \- | repo\_key | 调优后子图的key值，用于调优知识库查询。 |
| \- | repo\_summary | \- | \- | 记录调优过程中不同状态子图的个数。 |
| \- | \- | repo\_add\_num | \- | 调优前调优策略不在知识库中，调优后调优策略追加到知识库中的子图的个数。 |
| \- | \- | repo\_hit\_num | \- | 调优过程中调优策略在知识库中的子图的个数。 |
| \- | \- | repo\_reserved\_num | \- | 调优前调优策略在知识库中，调优后知识库中的调优策略无变化的子图的个数。 |
| \- | \- | repo\_unsatisfied\_num | \- | 调优前调优策略不在知识库，调优后也未写入知识库的子图个数。 |
| \- | \- | repo\_update\_num | \- | 调优前调优策略在知识库中，调优后知识库中的调优策略有更新的子图个数。 |
| \- | \- | total\_num | \- | 调优任务中调优的子图总数。 repo\_hit\_num=repo\_update\_num+repo\_reserved\_num total\_num=repo\_add\_num+repo\_hit\_num+repo\_unsatisfied\_num |
