在模型运行时遇到日志报错“MemCopySync:drvMemcpy failed.”

报错信息

问题分析

样例脚本如下:
    import torch
    import torch_npu

    def test_sum():
        xs_shape = [22400, 8]
        ys_shape = [22400, 8]
        gt_bboxes_shape = [22400, 8,4]
        xs = torch.rand(xs_shape).npu()
        ys = torch.rand(ys_shape).npu()
        gt_bboxes = torch.rand(gt_bboxes_shape).npu().half()
        left = xs - gt_bboxes[..., 0]
        right = gt_bboxes[..., 2] - xs
        top = ys - gt_bboxes[..., 1]
        bottom = gt_bboxes[..., 3] - ys
        # stream = torch_npu.npu.current_stream()
        # stream.synchronize()
        # left, top 结果是fp32,  right, bottom 结果是fp16,
        # print(left.dtype, top.dtype, right.dtype, bottom.dtype)
        bbox_targets = torch.stack((left, top, right, bottom), -1)  #报错位置在这里
        # stream.synchronize()

        bbox_targets = torch.sum(bbox_targets)

根据shell和日志报错信息,两者报错信息不匹配。shell报错是在同步操作中和AI CPU错误,而日志报错信息却是在min算子(内部调用ArgMinWithValue_tvmbin),二者报错信息不对应。一般这类问题出现的原因是由于日志生成的报错信息滞后。报错信息滞后可能是由于AI CPU算子的异步执行,导致报错信息滞后。

处理方法

对于该报错需要根据实际的错误来定位,可参考如下步骤进行处理:

  1. 通过关闭多任务算子下发后,发现结果不变,推断在shell脚本报错位置和日志报错算子之前就已出现错误。
  2. 根据报错加上stream同步操作,缩小错误范围,定位错误算子。stream同步操作的作用在于其要求代码所运行到的位置之前的所有计算必须为完成状态,从而定位错误位置。
  3. 通过在代码中加上stream同步操作,确定报错算子为stack。
  4. 打印stack所有参数的shape、dtype、npu_format,通过构造单算子用例复现问题。定位到问题原因为减法计算输入参数数据类型不同,导致a - b和b - a结果的数据类型不一致,最终在stack算子中报错。
  5. 将stack入参数据类型转换为一致即可临时规避问题。