
# msprobe精度分析工具使用指导
msprobe是MindStudio Training Tools工具链下精度调试部分的工具包，其通过采集和对比标杆（GPU/CPU）环境和昇腾环境上运行训练时的差异点来判断问题所在，主要包括精度预检、精度比对和梯度监控等功能。更多内容请参考[msprobe工具介绍](https://gitee.com/ascend/mstt/tree/master/debug/accuracy_tools/msprobe)。
一般场景的训练模型都是包括随机种子、数据集Shuffle、网络结构Dropout等操作的，目的是在网络阶段引入一定的随机性使得训练结果更加具有鲁棒性。然而在精度对齐阶段，这些随机性会导致训练运行结果每次表现不一致，无法进行和标杆的比对。因此在训练模型复现问题时，需要固定存在随机性的步骤，保证实验可重复性。存在随机性的步骤包括模型参数初始化，数据Batch加载顺序，Dropout层等。部分算子的计算结果也存在不确定性，需要固定。
当前固定随机性操作可分为**工具固定** 和**人工固定**两种。
1. 工具固定Seed 对于网络中随机性的固定，msprobe提供了固定Seed的方式，只需要在config.json文件中添加对应seed配置即可。
   msprobe工具提供了seed_all接口用于固定网络中的随机数。如果客户使用了工具但取用了其他随机种子，则必须使用客户的随机种子固定随机性。
   **函数原型**
   ```
   from msprobe.pytorch.common import seed_all
   seed_all(seed=1234, mode=False)
   ```
   表1**参数说明** 
   | 参数名  | 说明                                                                                                                                                                                                                                                                                                                                                                                                        | 是否必选 |
   |:---|:---|:---|
   | seed | 随机数种子。参数示例：seed=1000。默认值：1234。                                                                                                                                                                                                                                                                                                                                                                            | 否    |
   | mode | 确定性计算模式。可配置True或False。参数示例：mode=True。默认值：False。 即使在相同的硬件和输入下，API多次执行的结果也可能不同，开启确定性计算是为了保证在相同的硬件和输入下，API多次执行的结果相同。 确定性计算会导致API执行性能降低，通常不需要在精度问题刚开始定位时就开启，而是建议在发现模型多次执行结果不同的情况下时再开启。 rnn类算子、ReduceSum、ReduceMean等算子可能与确定性计算存在冲突，如果开启确定性计算后多次执行的结果不相同，则考虑存在这些算子。 | 否    |
      
   **函数示例**
   seed_all函数的随机数种子，取默认值即可，无须配置；第二个参数默认关闭，不开启确定性计算时也无须配置。
   确定性计算是NPU的一套机制，用于保证算子的计算确定性。之所以要有这个机制，是为了在Debug过程中，让所有的算子计算结果前后完全一致可复现，这是大多数精度问题分析的重要前提。因此，在精度问题定位过程中，确定性计算**不是目的，而是手段**。很多场景下需要在确定性计算使能的情况下，进行下一步的精度问题分析定位。Cuda对部分算子实现了确定性计算，但仍有部分算子无法固定。通常需要依赖确定性计算的场景是长稳问题，因为长稳问题需要通过多次长跑来分析Loss情况，这时候如果NPU本身计算结果不确定，就难以支撑和GPU结果的多次对比。
   示例1：仅固定随机数，不开启确定性计算。
   ```
   seed_all()
   ```
   示例2：固定随机数，开启确定性计算。
   ```
   seed_all(mode=True)
   ```
   在多卡训练场景下由于通信算子计算累加计算顺序不确定，需要添加以下环境变量，固定通信算子计算的确定性：
   ```
   export HCCL_DETERMINISTIC=TRUE
   ```
   **固定随机数范围**
   seed_all函数可固定随机数的范围如下表所示。
   
   | API                                        | 固定随机数              |
   |:---|:---|
   | os.environ\['PYTHONHASHSEED'\] = str(seed) | 禁止Python中的hash随机化。 |
   | random.seed(seed)                          | 设置random随机生成器的种子。  |
   | np.random.seed(seed)                       | 设置numpy中随机生成器的种子。  |
   | torch.manual_seed(seed)                    | 设置当前CPU的随机种子。      |
   | torch.cuda.manual_seed(seed)               | 设置当前GPU的随机种子。      |
   | torch.cuda.manual_seed_all(seed)           | 设置所有GPU的随机种子。      |
   | torch_npu.npu.manual_seed(seed)            | 设置当前NPU的随机种子。      |
   | torch_npu.npu.manual_seed_all(seed)        | 设置所有NPU的随机种子。      |
   | torch.backends.cudnn.enable=False          | 关闭cuDNN。           |
   | torch.backends.cudnn.benchmark=False       | cuDNN确定性地选择算法。     |
   | torch.backends.cudnn.deterministic=True    | cuDNN仅使用确定性的卷积算法。  |
      
   
2. 工具固定（Dropout） Dropout的实质是以一定概率使得输入网络的数据某些位置元素的数值变为0，这样可以使得模型训练更加有效。但在精度问题的定位过程之中，需要避免产生这种问题，因此需要关闭Dropout。
   在导入PrecisionDebugger后，工具会自动将如下接口参数p（丢弃概率）置为0。
   ```
   torch.nn.functional.dropout
   torch.nn.functional.dropout2d
   torch.nn.functional.dropout3d
   torch.nn.Dropout
   torch.nn.Dropout2d
   torch.nn.Dropout3d
   ```
   
3. 人工固定（硬件随机差异） 工具内部对于随机的控制，是通过设定统一的随机种子进行随机性固定的。但是由于硬件的差异，会导致同样的随机种子在不同硬件上生成的随机数不同。具体示例如下：
   ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000002017360952.png "点击放大")
   ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000002053521401.png "点击放大")
   由上图可见，torch.randn在GPU和NPU上固定随机种子后，仍然生成不同的随机张量。
   对于上述场景，用户需要将网络中的randn在CPU上完成后再转到对应device。例如，StableDiffusion中需要在forward过程中逐步生成随机噪声。
   ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000002017202744.png "点击放大")
   ![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000002053440433.png "点击放大")
   这样在Host侧生成的随机张量能够保证一样，搬移到NPU或者GPU设备上仍然一样。
   固定随机性完成后，可以使用缩小的模型在单机环境进行问题复现。复现后使用[msprobe工具](https://support.huaweicloud.com/bestpractice-modelarts/modelarts_10_2523.html)进行问题定位。需要注意的是，部分模型算法本身存在固有的随机性，在使用上述方法固定随机性后，如果使用工具也未能找到出问题的API，需要分析是否由算法本身的随机性导致。
   
 
