算子溢出定位
由于昇腾上部分算子不支持fp32(如 Conv,Pooling),或部分算子虽然支持fp32但性能极差,不得不切换成fp16(如MatMul),或者用户脚本中设置了混合精度,这些原因导致其必须走fp16格式,这增大了训练过程中算子溢出的风险,影响网络最终收敛的精度,这里给出算子溢出分析方法。
开启溢出检测
在MindSpore官网如上所示搜索 dump ,找到 异步dump 指导。
对于溢出检测,需要注意以下配置:
dump_mode:设置为0,检测到所有算子
path:推荐设置到/home/ma-user/modelarts/outputs/output_url_0/ 目录下,DI训练时该目录会自动回传数据到obs,方便后续进行溢出检测分析
iteration:设置为all,检测所有迭代
op_debug_mode:设置为3,开启全部溢出检测
一个典型的溢出检测 data_dump.json 配置为:
{
"common_dump_settings": {
"dump_mode": 0,
"path": "/home/ma-user/modelarts/outputs/output_url_0/bev/dump/",
"net_name": "bevnet",
"iteration": "all",
"saved_data": "tensor",
"input_output": 0,
"kernels": [],
"support_device": [0,1,2,3,4,5,6,7],
"op_debug_mode": 3,
"file_format": "npy"
}
复制
查看溢出算子
在日志中搜索关键字 overflow infos,如果有算子溢出,则日志中会提示算子所在的代码行:
如上图所示,溢出的算子为 Cast-op41878 该算子为 Cast 算子,scope 名为 Gradients/Default/network-MultiTaskTrainOneStepCell/network-ModuleWrapper/detection3d_head-DetHead/det_head-CenterPointHead/head-CenterHead/task_heads-CellList/0-SeparateHead/reg-SequentialCell/1-_OutputTo32/_op-Conv2d/gradConv2D/Cast-op41878(如果scope的名字以Gradients 开头,说明该算子是反向产生的算子)。根据 The function call stack: 提示,找到该算子对应的代码(反向算子需要先找到对应的正向算子)。
分析溢出产生原因
在上一步骤中,我们可以找到具体溢出的算子和所在代码,这一步我们需要分析溢出产生的原因。首先需要找出溢出算子所在的rank,下载该rank 下的dump数据,一个标准的dump数据结构如下所示:
rank_xx
|-- bevnet # 根目录,根据 data_dump.json 配置生成
| |-- 0 # 每个step产生的dump文件,序号代表step数
| |-- 1
| |-- 17
| |-- 2
| `-- constants # 网络中的常量,数据不随step数改变
|-- execution_order # 网络中算子的执行顺序(如果有多个图,则产生多个文件)
| |-- ms_execution_order_graph_0.csv
| |-- ms_execution_order_graph_1.csv
| |-- ms_execution_order_graph_17.csv
| |-- ms_execution_order_graph_18.csv
| |-- ms_execution_order_graph_19.csv
| |-- ms_execution_order_graph_2.csv
| `-- ms_global_execution_order_graph_17.csv
`-- graphs # 网络中算子的图结构(如果有多个图,则产生多个文件)
|-- ms_output_trace_code_graph_0.ir
|-- ms_output_trace_code_graph_0.pb
|-- ms_output_trace_code_graph_1.ir
|-- ms_output_trace_code_graph_1.pb
|-- ms_output_trace_code_graph_17.ir
|-- ms_output_trace_code_graph_17.pb
|-- ms_output_trace_code_graph_18.ir
|-- ms_output_trace_code_graph_18.pb
|-- ms_output_trace_code_graph_19.ir
|-- ms_output_trace_code_graph_19.pb
|-- ms_output_trace_code_graph_2.ir
`-- ms_output_trace_code_graph_2.pb
8 directories, 21 files
复制
一般我们只关注 rank_xx/xxx/x/ 下的数据,假设该目录下数据如下所示:
可以看到,Cast-op41878 的溢出数据被dump了出来,读取其中的数据,可以发现该算子的输入 104856.29 在cast之后变成了 65500.0 ,算子发生了溢出。(因为FP16格式下最大能表达的值为65504)
这里的溢出是正常的,原因详细参考下一章节
判断溢出是否合理
如果出现了溢出,第一件事就是需要判断该溢出是否合理,一般合理的溢出无需关注,溢出出现的step会被忽略,然后网络会调整LossScale 的值,后续训练仍会正常更新。如果溢出不合理,则需要定位原因,不合理的溢出可能一直影响网络训练,导致最终精度无法收敛的合理的值。
首先需要判断溢出算子出现在正向还是反向,判断的根据是scope名字,如果算子的scope名字以 "Default/xx" 开头,则该算子出现在正向;如果算子的scope名字以 "Gradient" 开头,则算子出现在反向。
步骤1:判断算子是否确实存在计算溢出
仅分析该算子的输入输出,此时输入输出是否真的达到了触发溢出的条件,触发条件一般为:输入/输出的绝对值大于 65504、输入输出数据中存在nan或inf、算子存在除0的操作、算子存在对负数开偶数次方等;
如果以上情况不存在,该溢出不合理;
步骤2:判断溢出场景的存在是否合理
如果是网络迁移场景,请和原脚本相同位置的值进行比较,同样的输入和网络,该溢出位置的输入输出是否和原脚本一致;如果是新开发脚本,请认真检查该值出现的合理性;
如果该溢出场景实际并不合理,则该算子的溢出也不合理;
步骤3:判断反向算子的LossScale 是否过大
对于溢出算子是反向算子,除了按照步骤1和步骤2的判断外,还需要考虑混合精度场景下LossScale的影响。在混合精度场景中,反向算子的值都会被扩大LossScale倍,此时很容易发生溢出,此时可以将算子的输入梯度除以LossScale,再观察是否会触发溢出;
如果该溢出是由于LossScale的值过大导致,则该算子的溢出是合理的,如果不是LossScale的值过大引起,则连续发生溢出,则该算子的溢出不合理;
溢出问题解决方法
- 算子计算不涉及溢出
如果算子计算不存在溢出,则算子存在误溢出;误溢出一般是算子本身的bug导致,可能是算子内部实现时脏数据的处理误触发了溢出,此时直接联系相关支撑人员解决;
- 溢出场景不存在
如果溢出的场景本身不应该存在,此时应进行逐层与原迁移脚本的比对或检查,很可能是网络脚本写错而引入了溢出场景;
如果网络脚本排查后没有问题,也可能是网络代码中存在框架bug或算子bug,导致运行到该处发生了溢出;如果迁移前后的脚本是数学上等价,但计算结果不同,此时需要联系相关支撑人员解决;
- 反向梯度过大导致溢出
在上一节判断溢出是否合理的第三步中, 我们首先需要判断梯度溢出是否由于LossScale过大引起,如果是,则无需关注,随着训练中每个step的溢出,LossScale会逐渐调整合适的值,直到不再溢出;
注意,LossScale的最小值默认为1,当LossScale 的值降低为1仍持续发生溢出,此时表明网络中是存在问题的。
这时存在问题的原因有两个:
一是由于网络设计的原因,在迭代前期需要的梯度特别大,导致不使用LossScale缩放时的实际梯度值都要大于FP16的表达范围,因此,当LossScale降低为1时,仍会发生溢出。针对该问题,建议重新设计网络,或者将网络的Loss值乘以一个小于1的数进行缩小,从而缩小梯度保证正常的更新;
二是反向存在框架或算在bug,此时可以与对标脚本或框架比对结果,如果无法定位或确实发现有框架/算子的问题,可以在MindSpore论坛进行提问会有专人帮忙支撑处理:https://www.hiascend.com/forum/forum-0106101385921175002-1.html。
混合精度调优经验分享(一):https://www.hiascend.com/forum/thread-0236124525404545023-1-1.html
混合精度调优经验分享(二):https://www.hiascend.com/forum/thread-0239124525600150026-1-1.html
混合精度调优经验分享(三):https://www.hiascend.com/forum/thread-0216124525871858017-1-1.html