diff --git a/debug/accuracy_tools/msprobe/docs/28.debugger_save_instruction.md b/debug/accuracy_tools/msprobe/docs/28.debugger_save_instruction.md index 7f00aab045565b9df7f3de9add60cb85fb16a4f2..107b458b18604457de32e60e06cb4ff17a61c761 100644 --- a/debug/accuracy_tools/msprobe/docs/28.debugger_save_instruction.md +++ b/debug/accuracy_tools/msprobe/docs/28.debugger_save_instruction.md @@ -1,7 +1,9 @@ # 单点保存工具 ## 简介 + L0, L1, mix级别的dump能力存在盲区,网络中的非API或module的输入输出不会被批量dump下来。单点保存提供类似np.save和print的功能和使用体验,可以保存指定的变量。同时针对大模型场景进行了增强,具备以下特性: + - 可保存变量的反向梯度结果。 - 能直接保存嵌套结构数据(如 list、dict),无需手动遍历。 - 自动分 Rank 保存。 @@ -14,25 +16,26 @@ L0, L1, mix级别的dump能力存在盲区,网络中的非API或module的输 ## 动态图场景(Pytorch&MindSpore) -### 使能方式 +### 使能方式 #### 配置文件说明 通用配置 (细节详见[通用配置说明](./02.config_introduction.md#11-通用配置) ): -| 参数 | 解释 | 是否必选 | -| -------- |-------------------------------------------| -------- | -| task | dump 的任务类型,str 类型。 单点保存场景仅支持传入"statistics", "tensor"。 | 是 | -| level | dump 级别,str 类型,根据不同级别采集不同数据。单点保存场景传入"debug"。 | 是 | -| dump_path | 设置 dump 数据目录路径,str 类型。 | 是 | -| rank | 指定对某张卡上的数据进行采集,list[Union[int, str]] 类型。 | 否 | -| step | 指定采集某个 Step 的数据,list[Union[int, str]] 类型。 | 否 | -| async_dump | 异步 dump 开关,bool 类型。该模式下,summary_mode 不支持 md5 值,也不支持复数类型 tensor 的统计量计算。 | 否 | +| 参数 | 解释 | 是否必选 | +| ---------- | ------------------------------------------------------------------------------------------------------- | -------- | +| task | dump 的任务类型,str 类型。 单点保存场景仅支持传入"statistics", "tensor"。 | 是 | +| level | dump 级别,str 类型,根据不同级别采集不同数据。单点保存场景传入"debug"。 | 是 | +| dump_path | 设置 dump 数据目录路径,str 类型。 | 是 | +| rank | 指定对某张卡上的数据进行采集,list[Union[int, str]] 类型。 | 否 | +| step | 指定采集某个 Step 的数据,list[Union[int, str]] 类型。 | 否 | +| async_dump | 异步 dump 开关,bool 类型。该模式下,summary_mode 不支持 md5 值,也不支持复数类型 tensor 的统计量计算。 | 否 | "statistics" 任务子配置项: -| 参数 | 解释 | 是否必选 | -| -------- |-------------------------------------------| -------- | -| summary_mode | 控制 dump 文件输出的模式,str 类型。支持传入"statistics", "md5"。 细节详见[statistics任务子配置项说明](./02.config_introduction.md#12-task-配置为-statistics) | 否 | + +| 参数 | 解释 | 是否必选 | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| summary_mode | 控制 dump 文件输出的模式,str 类型。支持传入"statistics", "md5"。 细节详见[statistics任务子配置项说明](./02.config_introduction.md#12-task-配置为-statistics) | 否 | "tensor" 任务无子配置项。 @@ -41,8 +44,10 @@ L0, L1, mix级别的dump能力存在盲区,网络中的非API或module的输 调用PrecisionDebugger.save,传入需要保存的变量,指定变量名称以及是否需要保存反向数据。接口入参说明详见[PyTorch单点保存接口](./05.data_dump_PyTorch.md#19-save),[MindSpore单点保存接口](./06.data_dump_MindSpore.md#615-save) #### 实例 + (以PyTorch场景为例,MindSpore场景只需要从msprobe.mindspore模块导包即可) 配置文件 + ```json { "task": "statistics", @@ -58,6 +63,7 @@ L0, L1, mix级别的dump能力存在盲区,网络中的非API或module的输 ``` 初始化 + ```python # 训练启动py脚本 from msprobe.pytorch import PrecisionDebugger @@ -69,6 +75,7 @@ for data, label in data_loader: ``` 初始化(无配置文件) + ```python # 训练启动py脚本 from msprobe.pytorch import PrecisionDebugger @@ -80,6 +87,7 @@ for data, label in data_loader: ``` 调用保存接口示例(以PyTorch代码为例,MindSpore使用方法相同) + ```python import torch import torch.nn as nn @@ -113,6 +121,7 @@ if __name__ == "__main__": ``` 分step保存数据(以PyTorch代码为例,MindSpore使用方法相同) + ```python import torch import torch.nn as nn @@ -152,94 +161,126 @@ if __name__ == "__main__": ### 使能方式 -#### 接口调用说明 -工具提供两个对外接口`save`和`save_grad`,分别用于保存训练中的tensor以及tensor对应的反向数据 -| 接口名称 | 入参 | device | MindSpore版本 |备注 | -| ------- | ------ | -------------- | --------------|--------------------------------------------------- | -| save | save_dir name, data | Ascend | >= 2.6.0 | (主流场景)图模式下只支持Ascend,pynative下支持Ascend/GPU/CPU。 | -| save_grad | save_dir, name, data | Ascend | >= 2.6.0 | (主流场景)图模式下只支持Ascend,pynative下支持Ascend/GPU/CPU。 | - - ----- -> 函数原型: -`save(save_dir:str, name:str, data)` -- save_dir:表示要保存的目录。 -- name :表示要保存的文件标志名称。 -- data :表示数据入参,可以是`mindspore.Tensor`或者是`List`,`Tuple`,`Dict`等嵌套结构。 - -> 函数原型: -`save_grad(save_dir:str, name:str, data)` -- save_dir:表示要保存的目录。 -- name :表示要保存的文件标志名称。 -- data :表示数据入参,**只能**是`mindspore.Tensor`。 +### 接口说明 -#### 实例 +工具提供三个对外接口用于保存训练过程中的数据: -- save接口使用: +| 接口名称 | 功能描述 | 支持设备 | MindSpore版本 | 使用场景说明 | +| --------- | ------------------------ | -------------- | ------------- | ---------------------------------------------- | +| save | 保存正向传播的tensor数据 | Ascend/GPU/CPU | >= 2.6.0 | 图模式下仅支持Ascend,PyNative模式下支持全平台 | +| save_grad | 保存反向传播的梯度数据 | Ascend/GPU/CPU | >= 2.6.0 | 图模式下仅支持Ascend,PyNative模式下支持全平台 | +| step | 更新训练步数 | Ascend/GPU/CPU | >= 2.6.0 | 控制数据保存的step目录 | + +### 详细接口定义 + +#### 1. save 接口 ```python -# save api usage -# **first import** -from msprobe.mindspore import save +save(save_dir: str, name: str, data: Union[Tensor, List, Tuple, Dict]) +``` + +**参数说明**: + +- `save_dir`: 数据保存目录路径 +- `name`: 数据标识名称(将作为文件名前缀) +- `data`: 支持多种数据类型: + - `mindspore.Tensor` 单个张量 + - `List/Tuple/Dict` 嵌套结构(会自动展开保存) +**使用示例**: + +```python +from msprobe.mindspore import save class Net(nn.Cell): - def construct(self, x, y, z): - # **use save api** - save("./test_dump", 'x', x) - return x * y * z - -x = Tensor([1, 2], ms.float32) -y = Tensor([-2, 3], ms.float32) -z = Tensor([0, 3], ms.float32) -net = Net() -output = grad(net, grad_position=(1, 2))(x, y, z) -time.sleep(1) - -# then will generate **./test_dump/step0/rank0/x_float32_0.npy** + def construct(self, x): + save("./dump_data", 'input', x) # 保存输入数据 + return x * 2 +``` + +#### 2. save_grad 接口 + +```python +save_grad(save_dir: str, name: str, data: Tensor) -> Tensor ``` -- save_grad接口使用: +**参数说明**: + +- `save_dir`: 梯度保存目录路径 +- `name`: 梯度标识名称(将作为文件名前缀) +- `data`: 必须是 `mindspore.Tensor`类型 + +**特别注意**: + +- 必须接收返回值并传回原计算图 +- 此操作不会影响计算精度 + +**使用示例**: ```python -# save_grad usage -# **first import** from msprobe.mindspore import save_grad + class Net(nn.Cell): - def construct(self, x, y, z): - # **use save api** the return value of save_grad must be received by origin - z = save_grad("./test_dump", 'z', z) - return x * y * z - -x = Tensor([1, 2], ms.float32) -y = Tensor([-2, 3], ms.float32) -z = Tensor([0, 3], ms.float32) -net = Net() -output = grad(net, grad_position=(1, 2))(x, y, z) -time.sleep(1) - -# then will generate **./test_dump/step0/rank0/z_grad_float32_0.npy** + def construct(self, x): + x = save_grad("./dump_data", 'grad', x) # 保存梯度数据 + return x * 2 +``` + +#### 3. step 接口 + +```python +step() +``` + +**功能说明**: + +- 递增训练步数计数器 +- 控制数据保存到不同的step目录(如step0/, step1/等) +- 如果不调用,所有数据会保存到同一个step目录 + +**使用示例**: + +```python +from msprobe.mindspore import save, step + +# 训练循环中 +for epoch in range(epochs): + train_one_epoch() + step() # 每个epoch后更新step ``` -**注意**save_grad需要将返回值回传给原tensor,此操作不会有精度影响,只会传递原值。 ## 输出结果 + ### 动态图场景(Pytorch&MindSpore) - * **"task" 配置为 "statistics" 场景** :在 dump 目录下会生成包含变量统计值信息的 `debug.json` 文件。 + +* **"task" 配置为 "statistics" 场景** :在 dump 目录下会生成包含变量统计值信息的 `debug.json` 文件。 `debug.json` 中统计值的key命名格式为 `{variable_name}{grad_flag}.{count}.debug`。 - * **"task" 配置为 "tensor" 场景** :除了在 dump 目录下生成包含变量统计值信息的 `debug.json` 文件外,还会在 dump 子目录 `dump_tensor_data` 中保存张量二进制文件,文件名称格式为 `{variable_name}{grad_flag}.{count}.debug.{indexes}.{file_suffix}`。 +* **"task" 配置为 "tensor" 场景** :除了在 dump 目录下生成包含变量统计值信息的 `debug.json` 文件外,还会在 dump 子目录 `dump_tensor_data` 中保存张量二进制文件,文件名称格式为 `{variable_name}{grad_flag}.{count}.debug.{indexes}.{file_suffix}`。 - - variable_name: 传入save接口的变量名称。 - - grad_flag: 反向数据标识,反向数据为"_grad",正向数据为""。 - - count: 调用计数,多次以相同变量名称调用时的计数。 - - indexes: 索引,在保存嵌套结构数据时的索引。例如:嵌套结构为`{"key1": "value1", "key2": ["value2", "value3"]}`,"value2"的索引为"key2.0"。 - - file_suffix:文件后缀,PyTorch场景为"pt",MindSpore场景为"npy"。 + - variable_name: 传入save接口的变量名称。 + - grad_flag: 反向数据标识,反向数据为"_grad",正向数据为""。 + - count: 调用计数,多次以相同变量名称调用时的计数。 + - indexes: 索引,在保存嵌套结构数据时的索引。例如:嵌套结构为 `{"key1": "value1", "key2": ["value2", "value3"]}`,"value2"的索引为"key2.0"。 + - file_suffix:文件后缀,PyTorch场景为"pt",MindSpore场景为"npy"。 ### 静态图场景(MindSpore) -在指定目录`save_dir`下生成`{step}/{rank}`目录,目录下生成指定`{name}`的npy文件,如果是save_grad接口调用,则会生成`{name}_grad`的npy文件。 -如`save("./test_dump", 'x', x)` -> `./test_dump/step0/rank0/x_float32_0.npy`。 +在指定目录 `save_dir`下生成 `{step}/{rank}`目录,目录下生成指定 `{name}`的npy文件,如果是save_grad接口调用,则会生成 `{name}_grad`的npy文件。 + +如 `save("./test_dump", 'x', x)` -> `./test_dump/step0/rank0/x_float32_0.npy`。 -或如`z = save_grad("./test_dump", 'z', z)` -> `./test_dump/step0/rank0/z_grad_float32_0.npy`。 +或如 `z = save_grad("./test_dump", 'z', z)` -> `./test_dump/step0/rank0/z_grad_float32_0.npy`。 +结构如下: +``` +./save_dir/ + ├── step0/ + │ ├── rank0/ + │ │ ├── x_float32_0.npy # save保存的正向数据 + │ │ └── z_grad_float32_0.npy # save_grad保存的梯度数据 + ├── step1/ + │ ├── rank0/ + │ │ ├── ... +```