# MindSpore 场景的精度比对

## 1 简介

msprobe精度比对工具主要用于如下场景：

- MindSpore框架内比对
  - 通过对同一个网络模型，在两个不同版本的MindSpore静态图环境下，输入相同的训练数据，在分别得到API dump数据后，对这两个API dump数据进行全量自动比对，从而快速定位不同版本之间的精度问题。
  - 通过对同一个网络模型，在两个不同版本的MindSpore静态图环境下，输入相同的训练数据，在分别得到kernel dump数据后，对这两个kernel dump数据进行全量自动比对，从而快速定位不同版本之间的精度问题。
  - 通过对同一个网络模型，在两个不同版本的MindSpore动态图环境下，输入相同的训练数据，在分别得到cell dump数据后，对这两个cell模块进行全量自动比对，从而快速定位不同版本之间的精度问题。
- MindSpore与PyTorch跨框架比对
  - 通过对同一个网络模型，在整网环境下分别在MindSpore动态图和PyTorch环境下获得API dump数据，以PyTorch数据作为标杆，进行自动比对，从而实现跨框架的精度对比。
  - 通过对同一个网络模型，在整网环境下分别在MindSpore动态图和PyTorch环境下获得cell dump数据，由用户指定可以比对的cell list，以PyTorch数据作为标杆，进行自动比对，从而实现跨框架的精度对比。
  - 通过对同一个网络模型，在整网环境下分别在MindSpore动态图和PyTorch环境下获得API或模块dump数据，由用户指定可以比对的API或模块，以PyTorch数据作为标杆，进行自动比对，从而实现跨框架的精度对比。
  - 通过对同一个网络模型，在整网环境下分别在MindSpore动态图和PyTorch环境下获得API或模块dump数据，由用户指定可以比对的模型代码中的Layer层，以PyTorch数据作为标杆，进行自动比对，从而实现跨框架的精度对比。

执行精度比对操作需要安装msprobe工具。详见《[MindStudio精度调试工具](../README.md)》的“工具安装”章节。

## 2 命令行比对

精度比对工具目前使用方式为命令行形式。

### 2.1 比对命令说明

命令示例如下：

```shell
msprobe -f mindspore compare -i ./compare.json -o ./output -s
```

**完整参数说明**

| 参数名               | 说明                                                         | 是否必选 |
| -------------------- | ------------------------------------------------------------ | -------- |
| -i或--input_path     | 指定比对文件。比对文件内容及示例请参见[比对文件](#31-比对文件)或[比对文件（kernel）](#32-比对文件kernel)（比对文件（kernel）仅[不同版本下的全量kernel比对](#23-不同版本下的全量kernel比对)场景支持）。 | 是       |
| -o或--output_path    | 配置比对结果文件存盘目录，默认会在当前目录创建output目录。文件名称基于时间戳自动生成，格式为：<br>        `compare_result_{timestamp}.xlsx`<br/>        `compare_result_{rank_id}_{step_id}_{timestamp}.xlsx`（仅[不同版本下的全量kernel比对](#23-不同版本下的全量kernel比对)场景支持）。 | 否       |
| -s或--stack_mode     | 比对结果展示调用栈信息（NPU_Stack_Info）的开关，bool 类型。单卡场景开启时，需要使用[比对文件](#31-比对文件)的单卡场景配置stack_path指定stack.json文件，才能生成详细调用栈信息，否则在比对时会报错；暂不支持多卡场景。通过直接配置该参数开启，默认未配置，表示关闭。 | 否       |
| -c或--compare_only   | 仅比对开关，bool 类型。该参数默认未配置，会启用自动精度分析，工具自动针对比对结果进行分析，识别到第一个精度可能不达标节点（在比对结果文件中的 Accuracy Reached or Not 列显示为 No），并给出问题可能产生的原因（打屏展示并生成 `advisor_{timestamp}.txt` 文件）。通过配置该参数取消自动精度分析，仅输出比对结果表格。 | 否       |
| -f或--fuzzy_match    | 模糊匹配。开启后，对于网络中同一层级且命名仅调用次数不同的API，可匹配并进行比对。通过直接配置该参数开启，默认未配置，表示关闭。 | 否       |
| -am或--api_mapping   | 跨框架比对。配置该参数时表示开启跨框架API比对功能，可以指定自定义映射文件*.yaml，不指定映射文件时按照msprobe定义的默认映射关系进行比对。自定义映射文件的格式请参见[自定义映射文件（API）](#33-自定义映射文件api)。仅[跨框架的API比对](#25-跨框架的api比对)场景需要配置。 | 否       |
| -cm或--cell_mapping  | 跨框架比对。配置该参数时表示开启跨框架cell模块比对功能，可以指定自定义映射文件*.yaml，不指定映射文件时按照msprobe定义的默认映射关系进行比对。自定义映射文件的格式请参见[自定义映射文件（cell）](#34-自定义映射文件cell)。仅[跨框架的cell模块比对](#26-跨框架的cell模块比对)场景需要配置。 | 否       |
| -dm或--data_mapping  | 跨框架比对。配置该参数时表示开启跨框架API或模块的比对功能，需要指定自定义映射文件*.yaml。自定义映射文件的格式请参见[自定义映射文件（API和模块）](#35-自定义映射文件api和模块)。仅[跨框架的API或模块比对](#27-跨框架的api或模块比对)场景需要配置。 | 否       |
| -lm或--layer_mapping | 跨框架比对。配置该参数时表示开启跨框架Layer层的比对功能，指定模型代码中的Layer层后，可以识别对应dump数据中的模块或API。需要指定自定义映射文件*.yaml。自定义映射文件的格式请参见[自定义映射文件（Layer）](#36-自定义映射文件layer)。仅[跨框架的Layer层比对](#28-跨框架的layer层比对)场景需要配置。 | 否       |

动态图模式没有填写任何mapping时，按照同框架比对的方式进行比对，比对数据和标杆数据的Cell或Api名称需要完全相同才能匹配得上。

### 2.2 不同版本下的全量API比对

1. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》完成不同环境下MindSpore静态图精度数据的采集，得到不同框架版本的API dump数据。

2. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

3. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s
   ```

4. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.3 不同版本下的全量kernel比对

1. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》完成不同环境下MindSpore静态图精度数据的采集，得到不同框架版本的kernel dump数据。

2. 创建比对文件，文件内容及示例请参见[比对文件（kernel）](#32-比对文件kernel)。

3. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output
   ```

   该场景仅支持compare的-i和-o参数。

4. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.4 不同版本下的cell模块比对

1. 配置[config.json](../config.json)文件level配置为L0、task配置为tensor或statistics并指定需要dump的cell模块名。

2. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》完成不同环境下MindSpore动态图精度数据的采集，得到不同框架版本的cell模块dump数据。

3. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

4. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s
   ```

5. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.5 跨框架的API比对

1. 配置[config.json](../config.json)文件level配置为L1、task配置为tensor或statistics。

2. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》完成不同环境下API精度数据的采集，得到两个框架的API dump数据。

3. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

4. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -am
   ```

   或

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -am api_mapping.yaml
   ```

   api_mapping.yaml文件配置请参见[自定义映射文件（API）](#33-自定义映射文件api)。
   不传入api_mapping.yaml的情况下将按照内置的api映射进行匹配；传入api_mapping.yaml的情况下优先按照api_mapping.yaml的内容进行匹配，api_mapping.yaml中没有涉及的按照内置的api映射进行匹配。

5. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.6 跨框架的cell模块比对

1. 配置[config.json](../config.json)文件level配置为L0、task配置为tensor或statistics并指定需要dump的cell模块名。

2. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》完成不同环境下cell模块精度数据的采集，得到两个框架的cell模块dump数据。

3. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

4. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -cm
   ```

   或

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -cm cell_mapping.yaml
   ```

   cell_mapping.yaml文件配置请参见[自定义映射文件（cell）](#34-自定义映射文件cell)。
   不传入cell_mapping.yaml的情况下仅将Cell改成Module后进行匹配；传入cell_mapping.yaml的情况下将按照cell_mapping.yaml的内容进行匹配。

5. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.7 跨框架的API或模块比对

该场景可用于在“**跨框架的API比对**”和“**跨框架的cell模块比对**”场景均无法完全覆盖模型中的API和模块时，通过手动指定映射关系来补全未被比对的API或模块。

1. 配置[config.json](../config.json)文件level配置为L0或L1、task配置为tensor或statistics并指定需要dump的API或模块名。

2. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》完成不同环境下API或模块精度数据的采集，得到两个框架的API或模块dump数据。

3. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

4. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -dm data_mapping.yaml
   ```

   data_mapping.yaml文件配置请参见[自定义映射文件（all）](#35-自定义映射文件api和模块)。

5. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

### 2.8 跨框架的Layer层比对

该场景可简化API或模块场景的配置，从Layer层识别整网的API和模块。

1. 配置[config.json](../config.json)文件level配置为L0或mix、task配置为tensor或statistics并指定需要dump的API或模块名。

2. 参见《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》完成不同环境下API或模块精度数据的采集，得到两个框架的API或模块dump数据。

3. 创建比对文件，文件内容及示例请参见[比对文件](#31-比对文件)。

4. 执行如下示例命令进行比对：

   ```shell
   msprobe -f mindspore compare -i ./compare.json -o ./output -s -lm layer_mapping.yaml
   ```

   layer_mapping.yaml文件配置请参见[自定义映射文件（Layer）](#36-自定义映射文件layer)。

5. 查看比对结果，请详见PyTorch目录下的《[PyTorch 场景的精度比对-精度比对结果分析](./10.accuracy_compare_PyTorch.md#3-精度比对结果分析)》章节。

## 3 附录

### 3.1 比对文件

以在当前目录创建./compare.json为例，单卡场景示例如下：


  ```json
{
"npu_path": "./npu_dump/dump.json",
"bench_path": "./bench_dump/dump.json",
"stack_path": "./npu_dump/stack.json",
"is_print_compare_log": true
}
  ```

多卡场景示例如下：
```json
{
"npu_path": "./npu_dump/step0", # 需填写到step层级（rank的上一层级）
"bench_path": "./bench_dump/step0", # 需填写到step层级（rank的上一层级）
"is_print_compare_log": true
}
```

**参数说明**

| 参数名               | 说明                                                         | 是否必选 |
| -------------------- | ------------------------------------------------------------ | -------- |
| npu_path             | 配置NPU环境下的dump.json文件（单卡场景）。跨框架场景指定为MindSpore的json文件。数据类型：str。 | 是       |
| bench_path           | 配置CPU、GPU或NPU环境下的dump.json文件（单卡场景）。 跨框架场景指定为PyTorch的json文件。数据类型：str。 | 是       |
| stack_path           | 配置NPU dump目录下的stack.json文件。数据类型：str。          | 是       |
| is_print_compare_log | 配置是否开启单个算子的日志打屏。可取值true或false，默认为true。关闭后则只输出常规日志。数据类型：bool | 否       |

### 3.2 比对文件（kernel）

仅[不同版本下的全量kernel比对](#23-不同版本下的全量kernel比对)场景支持。

以在当前目录创建./compare.json为例，示例如下：

- 单卡场景：

  ```json
  {
  "npu_path": "./npu_dump",
  "bench_path": "./bench_dump",
  "rank_id": [1],
  "step_id": []
  }
  ```

- 多卡场景：

  ```json
  {
  "npu_path": "./npu_dump",
  "bench_path": "./bench_dump",
  "rank_id": [],
  "step_id": []
  }
  ```


**参数说明**

| 参数名     | 说明                                                         | 是否必选 |
| ---------- | ------------------------------------------------------------ | -------- |
| npu_path   | 配置NPU环境下的真实数据目录。数据类型：str。                 | 是       |
| bench_path | 配置NPU环境下的真实数据目录。数据类型：str。                 | 是       |
| rank_id    | 配置比对的Rank ID。npu_path和bench_path目录下的dump文件需要存在对应Rank的数据。默认为空，表示比对所有Rank。可配置一个或多个Rank，多个Rank ID用逗号隔开，例如："rank_id": [1,2,3]。数据类型：list[int]。 | 否       |
| step_id    | 配置比对的Step ID。npu_path和bench_path目录下的dump文件需要存在对应Step的数据。默认为空，表示比对所有Step。可配置一个或多个Step，多个Step ID用逗号隔开，例如："step_id": [1,2,3]。数据类型：list[int]。 | 否       |

### 3.3 自定义映射文件（API）

文件名格式：\*.yaml，*为文件名，可自定义。

文件内容格式：

```yaml
ms_api: {ms_api_name}
pt_api: {pt_api_name}
ms_args:
- {index1}
- {index2}
...
- {indexN}
pt_args:
- {index1}
- {index2}
...
- {indexN}
ms_outputs:
- {index1}
- {index2}
...
- {indexN}
pt_outputs:
- {index1}
- {index2}
...
- {indexN}
```

- ms_api/pt_api：分别为MindSpore和PyTorch框架的API名称，配置格式为{api_type}.{api_name}。API名称请分别从《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》中的dump.json文件获取。
- ms_args/pt_args：分别为ms_api/pt_api对应的MindSpore和PyTorch框架API的入参的序号。
- ms_outputs/pt_outputs：分别为ms_api/pt_api对应的MindSpore和PyTorch框架API的输出的序号。

**说明**：

- MindSpore和PyTorch框架的API映射关系可以从《[PyTorch与MindSpore API映射表](https://www.mindspore.cn/docs/zh-CN/r2.3.0rc2/note/api_mapping/pytorch_api_mapping.html)》获取，其中PyTorch与MindSpore API名称前缀的映射关系如下：

  | PyTorch             | PyTorch在dump文件中的名称 | MindSpore        | MindSpore在dump文件中的名称 |
  | ------------------- | ------------------------- | ---------------- | --------------------------- |
  | torch.nn.functional | Functional                | mindspore.ops    | Functional                  |
  | torch.Tensor        | Tensor                    | mindspore.Tensor | Tensor                      |
  | torch               | Torch                     | mindspore.ops    | Functional                  |

  实际配置自定义映射文件（API）时需要使用dump文件中的名称。

- 自定义映射文件（API）需要满足ms_args/pt_args列表中的元素个数一致，ms_outputs/pt_outputs相同。

- 须确保列表自定义映射文件（API）配置元素的合法性，比如ms_args/pt_args的API用到的参数只有3个参数，那么用户实际指定的参数序号只能包含0、1、2；另外参数序号列表中的值不能重复。

文件内容示例：

```yaml
ms_api: Functional.abs
pt_api: Torch.abs
ms_args:
- 0
- 1
pt_args:
- 0
- 1
ms_outputs:
- 0
- 1
pt_outputs:
- 0
- 1
# ms_args/pt_args和ms_outputs/pt_outputs参数的配置需要根据ms_api/pt_api的API入参和输出的顺序，例如Functional.abs API的入参为（a b c），那对应的ms_args为0 1 2，可根据实际需要选择，而Torch.abs的入参如果是（a b c），那么ms_args和pt_args配置一致即可，但如果Torch.abs的入参如果是（a c）或其他与Functional.abs不完全映射的值，那么ms_args和pt_args配置的序号需要与入参对应，Torch.abs（a c）的序号为0 1，Functional.abs（a b c）为0 1 2，只有a和c参数可以映射，那么ms_args配置为0 2，pt_args配置为0 1。ms_outputs/pt_outputs同理。
```

### 3.4 自定义映射文件（cell）

文件名格式：\*.yaml，*为文件名，可自定义。

文件内容格式：

```yaml
{cell_name}.{class_name}: {module_name}.{class_name}
```

冒号左侧为MindSpore框架cell模块的{cell_name}.{class_name}，冒号右侧为PyTorch框架module模块的{module_name}.{class_name}。

{cell_name}.{class_name}从dump cell模块级.npy文件名获取，命名格式为：`{Cell}.{cell_name}.{class_name}.{前向反向}.{index}.{input/output}.{参数序号}`

文件内容示例：

```yaml
fc2.Dense: fc2.Linear
conv1.Conv2d: conv3.Conv2d
```

### 3.5 自定义映射文件（API和模块）

文件名格式：\*.yaml，*为文件名，可自定义。

文件内容格式：

```yaml
# API
{api_type}.{api_name}.{API调用次数}.{前向反向}.{input/output}.{参数序号}: {api_type}.{api_name}.{API调用次数}.{前向反向}.{input/output}.{参数序号}
# 模块
{Cell}.{cell_name}.{class_name}.{前向反向}.{index}.{input/output}.{参数序号}: {Module}.{module_name}.{前向反向}.{index}.{input/output}.{参数序号}
```

冒号左侧为MindSpore框架API的名称和Cell模块的名称，冒号右侧为PyTorch框架API的名称和module模块名称。

API和模块名称请分别从《[MindSpore 场景的精度数据采集](./06.data_dump_MindSpore.md)》和《[PyTorch 场景的精度数据采集](./05.data_dump_PyTorch.md)》中的dump.json文件获取。

文件内容示例：

```yaml
# API
Functional.flash_attention_score.4.forward.input.0: NPU.npu_fusion_attention.4.forward.input.0
# 模块
Cell.relu.ReLU.forward.0.input.0: Module.module.language_model.embedding.word_embedding.VocabParallelEmbedding.forward.0.input.0
```

API和模块名称在dump.json文件中的“data_name”字段展示，如下图红框处所示：

- MindSpore dump

  ![ms_dump](./img/ms_dump.png)

- PyTorch dump

  ![pt_dump](./img/pt_dump.png)

### 3.6 自定义映射文件（Layer）

文件名格式：\*.yaml，*为文件名，可自定义。

文件内容示例：

```yaml
ParallelAttention:                 # Layer层名称
  qkv_proj: query_key_value        # 冒号左侧为MindSpore框架模型代码中嵌套的Layer层名称，冒号右侧为PyTorch框架模型代码中嵌套的Layer层名称
  out_proj: dense

ParallelTransformerLayer:
  attention: self_attention

Embedding:
  dropout: embedding_dropout

ParallelMLP:
  mapping: dense_h_to_4h
  projection: dense_4h_to_h

PipelineCell:
  model: module

Cell:
  network_with_loss: module

layers:                           # 手动映射MindSpore与PyTorch模型代码中的Layer层序号
  '5': '0'
  '6': '1'
  '7': '2'
  '8': '3'
  '9': '4'
```

Layer层名称需要从模型代码中获取。

yaml文件中只需配置MindSpore与PyTorch模型代码中功能一致但名称不同的Layer层，名称相同的Layer层会被自动识别并映射。

模型代码示例：

![ms_dump](./img/ms_layer.png)