# PyTorch 场景的在线精度预检

## 1 简介

为了应对大模型场景下，通过离线预检方式 dump API 输入输出数据导致的存储资源紧张问题，提供在线精度预检功能。本功能实现在执行 NPU 训练操作的过程中，通过 TCP/IP 协议在 NPU
Host 与 GPU Host 设备间建立连接，将 NPU 上对应 API 的输入数据在 GPU 设备上运行，将两份输出数据进行比对，得到预检比对结果，从而减少数据 dump 的步骤，降低存储资源的占用。针对偏差较大的算子，两方比对（NPU vs. GPU）的方法缺少裁判进行裁定。 参考离线预检，在线预检场景同时支持两方比对和三方比对方式，按照 api 的精度标准要求，选择比对两方比对和三方比对。

## 2 在线精度预检流程

在线精度预检当前支持**局域网场景**和**共享存储场景**，请根据不同的场景选择对应的配置。

在线精度预检操作流程如下：

1. 准备 GPU 和 NPU 可正常运行的训练环境，PyTorch 版本大于等于2.0，并保证两台 Host 在同一局域网内可正常通信或能通过共享存储进行通信。
2. GPU 和 NPU Host 设备上同时安装msprobe工具，详见[ msprobe 安装](./01.installation.md)章节，其中在线预检要安装 twisted、pyOpenSSL，这些包为 Python 模块。
3. 分别配置 GPU 侧、NPU 侧的 config.json 文件。
4. 在 GPU 侧运行 `msprobe -f pytorch run_ut -config ./config.json`。
5. 在 NPU 侧配置训练脚本。
6. 在 NPU 侧执行训练。

## 3 在线精度预检操作指导

### 3.1 配置 config.json 文件

预检工具安装完成后，需要在 GPU 和 NPU 环境下分别配置 config.json。其中需要重点关注文件中的 is_online、is_benchmark_device、host 和 port 参数的配置，保障在线预检时 GPU 和 NPU 两台设备间的通信正常。

#### 3.1.1 GPU 侧在线预检配置说明

| 参数名称            | 说明           | 是否必选 |
|-----------------|--------------|------|
| task            | 任务名称，str 类型，配置为 run_ut 表示预检任务。通过其他字段 is_online 判断离线预检、在线预检任务。          | 是    |
| white_list      | 预检的 API 白名单，list[str] 类型。<br/>**配置示例**：white_list=["conv1d", "conv2d"]。默认未配置白名单，即预检全量 API 数据。       | 否    |
| black_list      | 预检的 API 黑名单，list[str] 类型。<br/>**配置示例**：white_list=["conv1d", "conv2d"]。默认未配置黑名单，即预检全量 API 数据。         | 否    |
| error_data_path | 配置保存精度未达标的 API 输入输出数据路径，str 类型。在线预检模式下该参数不生效。         | 否    |
| is_online       | 在线预检模式开关，bool 类型，可取值 True（开启）、False（关闭），默认关闭。              | 是    |
| nfs_path        | 在线预检模式共享存储目录路径，str 类型，用于 GPU 设备和 NPU 设备间进行通信。配置该参数后 host、port 和 tls_path 不生效。   | 否    |
| host            | 在线预检模式局域网场景信息接收端 IP，str 类型，用于 GPU 设备和 NPU 设备间进行通信，GPU 侧配置为本机地址 127.0.0.1 或本机局域网 IP。局域网场景时，不能配置 nfs_path 参数，否则局域网场景不生效。            | 否    |
| port            | 在线预检模式局域网场景信息接收端端口号，int 类型，用于 GPU 设备和 NPU 设备间进行通信，GPU 侧配置为本机可用端口。局域网场景时，不能配置 nfs_path 参数，否则局域网场景不生效。        | 否    |
| rank_list       | 指定在线预检的 Rank ID，默认值为 [0]，list[int] 类型，应配置为大于等于 0 的整数，且须根据实际卡的 Rank ID 配置，若所配置的值大于实际训练所运行的卡的 Rank ID，则在线预检输出数据为空。GPU 和 NPU 须配置一致。 | 是    |
| tls_path        | 在线预检模式局域网场景 SSL 证书路径，该路径下包含私钥文件 server.key 和公钥文件 server.crt，str 类型，未配置该参数时默认取值当前路径。tls_path配置为空字符串时，采用TCP协议明文传输api数据；当配置为路径时，采用TLS1.2协议加密传输数据，加密传输时安全性较高，传输速率较低。 | 否    |


#### 3.1.2 NPU 侧在线预检配置说明

| 参数名称             | 说明           | 是否必选 |
|------------------|-------------|------|
| task             | 任务名称，str 类型，配置为 tensor 表示 dump API 统计信息和完全复刻整网的 API 运行情况的真实数据。通过字段 online_run_ut 判断是否使用在线预检功能。      | 是    |
| dump_path        | dump 路径，str 类型，配置为合法路径即可，兼容 tensor 任务静态检查。       | 是    |
| level            | dump 级别，str 类型，在线预检时配置为 L1，表示 dump API 级精度数据。在线预检可不配置，默认取值 L1。                                               | 是    |
| rank             | 指定对某张卡上的数据进行 dump，list[int] 类型，默认未配置(表示 dump所有卡的数据)，需要与 GPU 侧配置项 rank_list 保持一致。   | 否    |
| step             | 指定 dump 某个 step 的数据，list[int] 类型，默认未配置，表示 dump 所有 step 的数据。dump 特定 step 时，须指定为训练脚本中存在的 step。   | 否    |
| scope            | dump 范围，list[str] 类型，默认未配置（list 也未配置时表示 dump 所有 api 的数据），配置方式参考 [config.json 配置介绍](./02.config_introduction.md)。    | 否    |
| list             | dump 范围，list[str] 类型，默认未配置（scope 也未配置时表示 dump 所有 api 的数据），配置方式参考 [config.json 配置介绍](./02.config_introduction.md)。 | 否    |
| online_run_ut    | 在线预检模式开关，bool 类型，可取值 True（开启）、False（关闭），默认关闭。        | 是    |
| nfs_path         | 在线预检模式共享存储目录路径，str 类型，用于 GPU 设备和 NPU 设备间进行通信。配置该参数后 host 和 port 不生效。     | 否    |
| host             | 在线预检模式局域网场景信息接收端 IP，str 类型，用于 GPU 设备和 NPU 设备间进行通信，NPU 侧须配置为 GPU 侧的局域网 IP 地址。局域网场景时，不能配置 nfs_path 参数，否则局域网场景不生效。     | 否    |
| port             | 在线预检模式局域网场景信息接收端端口号，int 类型，用于 GPU 设备和 NPU 设备间进行通信，NPU 侧须配置为 GPU 侧的端口号。局域网场景时，不能配置 nfs_path 参数，否则局域网场景不生效。        | 否    |
| tls_path         | 在线预检模式局域网场景 SSL 证书路径，该路径下包含私钥文件 client.key 和公钥文件 client.crt，str 类型，未配置该参数时默认取值当前路径。tls_path配置为空字符串时，采用TCP协议明文传输api数据；当配置为路径时，采用TLS1.2协议加密传输数据，加密传输时安全性较高，传输速率较低。 | 否    |
| online_run_ut_recompute | 模型训练是否使用重计算机制，bool类型，默认为False，表示模型没有使用重计算。在线预检暂不支持重计算机制下反向算子的预检，当模型训练使用重计算时，跳过反向算子预检，默认模型关闭重计算。 | 否    |

#### 3.1.3 局域网场景配置示例

若采用 TLS1.2 协议加密传输 api 数据，需配置 SSL 证书，可参考如下生成自签名证书方法，仅供调试使用，生产环境请申请正式证书。
```shell
# 创建私钥文件server.key
openssl genrsa -out server.key 2048

# 创建签名请求文件server.csr
openssl req -new -key server.key -out server.csr

# 自签名, 生成1年期公钥文件server.crt
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```

注意：配置TLS协议时，传输性能受机器环境和网络质量的影响，可能触发NPU超时中断模型训练，为避免训练和预检中断，丢弃长时间未传输的api数据，同时NPU侧配置HCCL环境变量，配置方式如下：

a) 调整HCCL环境变量，关闭看门狗，避免WorkHCCL超时中断模型训练:
```shell
export HCCL_DESYNC_DEBUG=0
export HCCL_ASYNC_ERROR_HANDLING=0
```
b) 调整通信算子超时设置（以1800s举例）：
```shell
export HCCL_CONNECT_TIMEOUT=1800
export HCCL_EXEC_TIMEOUT=1800
```

GPU 侧：

```json
{
  "task": "run_ut",
  "run_ut": {
    "white_list": [],
    "black_list": [],
    "error_data_path": "./",
    "is_online": true,
    "nfs_path": "",
    "host": "127.0.0.1",
    "port": 59208,
    "rank_list": [0],
    "tls_path": ""
  }
}
```

NPU 侧：

```json
{
  "task": "tensor",
  "dump_path": "./dump_path",
  "rank": [0],
  "step": [0],
  "level": "L1",
  "tensor": {
    "scope": [],
    "list": [],
    "online_run_ut": true,
    "nfs_path": "",
    "host": "xx.xx.xx.x",
    "port": 59208,
    "tls_path": ""
  }
}
```

#### 3.1.4 共享存储场景配置示例

GPU 侧：

```json
{
  "task": "run_ut",
  "run_ut": {
    "white_list": [],
    "black_list": [],
    "error_data_path": "./",
    "is_online": true,
    "nfs_path": "/nfs/xxx/data",
    "host": "",
    "port": -1,
    "rank_list": [0],
    "tls_path": ""
  }
}
```

NPU 侧：

```json
{
  "task": "tensor",
  "dump_path": "./dump_path",
  "rank": [0],
  "step": [0],
  "level": "L1",
  "tensor": {
    "scope": [],
    "list": [],
    "online_run_ut": true,
    "nfs_path": "/nfs/xxx/data",
    "host": "",
    "port": -1,
    "tls_path": ""
  }
}
```

### 3.2 在 GPU 侧运行 run_ut

由于 GPU 侧为通信接收端，需先于 NPU 侧执行 run_ut 操作，命令如下：

```bash
msprobe -f pytorch run_ut -config ./config.json
```

GPU 侧配置好 config.json 文件后执行 run_ut 命令，此时 GPU 处于预检等待状态：

- 局域网场景：当 NPU 侧启动训练后将预检的 API 输入和输出数据发送到 GPU 侧时，GPU 启动预检操作。
- 共享存储场景：当 NPU 侧启动训练后将预检的 API 输入和输出数据发送到共享存储时，GPU 启动预检操作。

### 3.3 在 NPU 侧配置训练脚本

在 NPU 训练脚本中添加如下代码以获取 run_ut 操作的预检 API 输入和输出数据：

```python
from msprobe.pytorch import PrecisionDebugger

debugger = PrecisionDebugger("config.json")
...

debugger.start()

...

debugger.stop()
debugger.step()
```

### 3.4 在 NPU 侧执行训练脚本

配置完 NPU 侧训练脚本后即可执行训练脚本，命令示例如下：

```bash
bash train.sh
```

训练脚本执行完毕后，在GPU侧dump_path目录下生成比对结果文件，`accuracy_checking_result_{timestamp}_rank{rank_id}.csv`和`accuracy_checking_details_{timestamp}_rank{rank_id}.csv`记录两方比对结果，`api_precision_compare_result_{timestamp}_rank{rank_id}.csv`和`api_precision_compare_details_{timestamp}_rank{rank_id}.csv`记录三方比对结果。详细介绍请参见[离线精度预检中的 **4 预检结果**](./07.accuracy_checker_PyTorch.md#4-预检结果)。

## 4 支持的融合算子列表

预检工具当前支持的融合算子如下：

- npu_apply_adam_w

- npu_confusion_transpose

- fast_gelu

- npu_layer_norm_eval

- npu_linear

- npu_fusion_attention（该算子在 GPU 上预检时，需要额外安装 flash_attn，请用户自行安装。）

- npu_rms_norm

- npu_rotary_mul

- npu_scaled_masked_softmax

- npu_swiglu
