昇腾910上算子溢出问题分析

由于昇腾上部分算子不支持fp32(如 Conv,Pooling),或部分算子虽然支持fp32但性能极差,不得不切换成fp16(如MatMul),导致其必须走fp16,这增大了训练过程中算子溢出的风险,影响网络最终收敛的精度,这里给出算子溢出分析方法。

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"
}
  • 步骤 2:查看溢出算子
  • 在日志中搜索关键字 overflow infos,如果有算子溢出,则日志中会提示算子所在的代码行:
5290 [WARNING] DEVICEC517, ffff1c1b9160,python):2022-12-27-23:50:13.843.123 [mindspore/ccsrc/plugin/device/ascend/hal/device/ascend_kernel_runtime. cc:683]TaskFailCallback] Node run task overflow, node name: Gradients/Default/network-MultiTaskTrainonestepCelL/network-Modulewrapper/detection3d _head-DetHead/det_head-CenterPointHead/head-CenterHead/task_heads-CellList/0-SeparateHead/reg-SequentialCel1/1-_OutputTo32/_op-Conv2d/gradconv2D/Cast-op41878Task overflow infos task_id: 306, streamid: 17, tid:517, device_id: 1, retcode:207003 (aicore over flow
5291 The function call stack:
5292 Corresponding code candidate:
5293  In file /home/ma-user/mindspore/build/package/mindspore/ops/_grad/gradnn_ops.py:106/	dx = input_grad(dout, w, x_shape)/
5294 In file /home/ma-user/mindspore/build/package/mi ndspore/ops/_grad/grad _nn_ops.py: 107/	dw = filter_grad(dout, x, w_shape)/
5295 Corresponding forward node candidate:
5296 - In file /hone/na-user/mindspore/build/package/mi ndspore/nn/layer/ conv.py: 309/	output = self.conv2d(x, self.weight)/
5297 In file /home/na-user/mindspore/bui ld/package/mindspore/train/arp.py:671	return F.cast(self._opCx), mstype. float32)/	
5298 In file /hone/na-user/mindspore/build/package/mi ndspore/nn/layer/container.py:278/	for cell in self.cell_list:/
5299 In file /home/ma-user/rodelarts/user-job-dir/code/tasks/bev_task/uvp_rodule/models/det_ head/centerpoint/centerpoint_head.py:145/	return {'reg':self.reg(x), "height':self.height(x), 'dim':self.dim(x),'rot':self.rot(x), 'vel':self.vel(x),"heatrap':self.heatmap(x)}/
5300 In file /home/ra-user/nodelarts/user-job-dir/code/tasks/bev-task/uvp_module/nodels/det_head/centerpoint/centerpoint_head.py:239/	for task in self.task_heads:/
5301 In file /home/ma-user/nodelarts/user-job-dir/code/tasks/bev_task/uvp_module/models/det_head/centerpoint/centerpoint_ head.py:255/	return multi_apply(self.forward_single,feats)/
5302 In file /hone/ma-user/nodelarts/user- job-dir/code/tasks/bev_task/uvp_module/models/det_head/centerpoint/centerpoint_head.py: 255/	return multi_apply(self.forward_single,feats)/
5303 In file /home/ma-user/nodelarts/user-job-dir/code/tasks/bev_task/uvp_module/models/det_head/centerpoint/centerpoint_head.py:413/	pred_dict = self.head(bev_feat_map)/
5304 In file /home/ma-user/modlelarts/user-job-dir/code/tasks/bev_task/uvp_module/models/det_head/det_head.py:71/	det_output,ret_dict = self.det_headCdata_dict)/
5305 In file /hone/na-user/nodelarts/user-job-dir/code/uvpsandbox-api/uvpsandbox/uvpsandbox/nodule_wrapper. py: 40/	for net, node, inners, node-tasks in zip(self.nets, self.nodes, self.inner_nodes, self.nodes tasks):/
5306 In file /hone/ma-user/modelarts/user- job-dir/ code/uvpsandbox-api /uvpsandbox/uvpsandbox/frarework. py: 583/	net_outputs = self.network(img_data,f"labels":[labels], "img_info":img_info})/	5307 In File /hone/ma-user/mindspore/bui ld/package/mindspore/nn/wrap/loss_scale.py:336/	loss = self.network(*inputs)/
  • 溢出的算子为 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: 提示,找到该算子对应的代码(反向算子需要先找到对应的正向算子)。
  • 步骤3:分析溢出产生的原因
  • 在步骤2中,我们可以找到具体溢出的算子和所在代码,这一步我们需要分析溢出产生的原因。首先需要找出溢出算子所在的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/bevnet/x/ 下的数据,假设该目录下数据如下所示:
-rw-r--r--    1 root root	630912 Dec 28 10:00 Cast. Cast-op41877.309.17.1672156213076552. input.0.NCHW. npy
-rw-r--r--    1 root root	315520 Dec 28 10:00 Cast. Cast-op41877.309.17.1672156213076552.output.0.NCHW.npy
-rw-r--r--    1 root root	630912 Dec 28 10:00 Cast.Cast-op41878.306.17.1672156213045891. input.0.NCHW.npy
-rw-r--r--    1 root root	315520 Dec 28 10:00 Cast.Cast-op41878.306.17.1672156213045891.output.0.NCHW. npy
-rw-r--r--    1 root root           1577088 Dec 28 10:00 Cast. Cast-op41879.63.18.1672156213413591. input.0.NCHW.npy
-rw-r--r--    1 root root	788608 Dec 28 10:00 Cast.Cast-op41879.63.18.1672156213413591.output.0.NCHW.npy
-rw-r--r--    1 root root                2432 Dec 28 10:00 Conv2DBackpropInput. Conv2DBackpropInput-op26836.331.17.1672156213185043.input.0.NCHW.npy
-rw-r--r--    1 root root            315520 Dec 28 10:00 Conv2DBackpropInput. Conv2DBackpropInput-op26836.331.17.1672156213185043.input.1.NCHW.npy
-rw-r--r--    1 root root        10092672 Dec 28 10:00 Conv2DBackpropInput.Conv20BackoropInput-op26836.331.17.1672156213185043.output-0.NCHW.nDy
  • 可以看到,Cast-op41878 的溢出数据被dump了出来,读取其中的数据,可以发现该算子的输入 104856.29 在cast之后变成了 65500.0 ,算子发生了溢出。
Python 3.8.6 (default,0ct 6 2020, 03:22:36)
[GCC 7.5.0] on linux
Tyре "help", "сopyright" , "credits" or "1icense" for more information.
>>> inport nunpy as np
>>> np.1oad("cast.Cast-op41878.306.17.1672156213045891. input.0.NCHW.npy").maxO
104856.29
>>> np.load("cast.Cast-op41878.306.17.1672156213045891.output.0.NCHW. npy").maxO)
65500.0
  • 由于初始时 loss scale 的值比较大,导致初始梯度比较大,这里的溢出也是正常的,可以尝试调小初始loss scale 解决。

溢出常见解决方法:

  1. 对于发生在训练开始,在后期迭代不再出现的溢出,可以忽略或者调小初始loss scale。这是因为前期梯度较大,训练不稳定,如果配置了 LossScaleManager,这些溢出的step会被自动忽略,一般对最终的收敛影响不大。
  2. 如果溢出的算子输入数据正常,正常计算时不应该引发溢出,此时请保留算子输入输出数据,需要与具体的算子开发负责人确认,该算子可能存在溢出误报的问题。
  3. 对于MatMulBatchMatMulReduceSumReduceMean 等容易引发溢出的算子,可以尝试在算子输入之前对数据进行缩放(缩小x倍),在算子计算后的某个合适位置进行复原(放大回x倍),这样在保证整个计算数学等价的情况下,避免溢出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值