已关闭
[Bug-Report|缺陷反馈]: Args缓存命中后未刷新shape依赖输出tensor地址导致二阶段coredump #309
liuyi424创建于  8月12日关闭于  25 天前
liuyi424
8月12日 创建

Describe the current behavior / 问题描述 (Mandatory / 必填)

Individual op 使用 args 缓存时,缓存对象会保存 shape 依赖输出对应的 aclTensor *

第一次算子调用传入输出 tensor 地址 A,两阶段执行成功。A 随后被销毁,或者其内存被复用为其他对象。第二次调用传入新的输出 tensor 地址 B,因 tensor 描述和其他 cache key 信息相同而命中第一次的 args 缓存。

缓存命中后,原逻辑只刷新 kernel 使用的 TensorData 地址,没有同步刷新 outPutShapeMap 中保存的 aclTensor *,导致该 map 仍指向 A。二阶段执行完成并回刷输出 shape 时,NnopbaseExecutorRefreshOutputShape 通过旧地址 A 调用 SetStorageShapeSetOriginalShapeSetViewShape。当 A 已失效或被复用为其他对象时,在 SetStorageShape 处发生 coredump。

Environment / 环境信息 (Mandatory / 必填)

  • 昇腾硬件型号:Ascend950
  • CANN/opbase 版本或分支:master
  • 系统架构:x86

Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)

  1. 构造包含 shape 依赖输出的 individual op executor,并通过 NnopbaseAddOutputShapeDependTensor 传入输出 tensor A。
  2. 执行第一次 NnopbaseRunForWorkspaceNnopbaseRunWithWorkspace,两阶段执行成功,相关 args 进入缓存。
  3. 销毁 tensor A,或让 A 所在内存被复用为其他对象。
  4. 使用相同 tensor 描述和算子参数再次调用算子,shape 依赖输出改为 tensor B。
  5. 第二次调用命中第一次的 args 缓存并执行二阶段。
  6. 输出 shape 回刷时仍从缓存的 outPutShapeMap 取到 A,并在 it->second->SetStorageShape(newShape) 处发生 coredump。

Describe the expected behavior / 预期结果 (Mandatory / 必填)

每次缓存命中并刷新输入输出地址时,应同时将缓存对象的 outPutShapeMap 更新为当前调用的 map。第二次二阶段执行回刷输出 shape 时,应访问 tensor B,不应继续访问首次调用的 tensor A。

崩溃前最后一条相关日志显示:

outputShape size is 144

崩溃位置:

it->second->SetStorageShape(newShape);

现场确认的地址关系:

第一次调用:shape依赖输出tensor=A,执行成功
第二次调用:shape依赖输出tensor=B,命中缓存
第二次回刷:实际访问缓存中的A;A已被销毁或复用,不再是有效aclTensor,随后coredump

Special notes for this issue/备注 (Optional / 选填)

根因是 NnopbaseUpdateOutputAddrUpdateArgsIoAddr 两条缓存地址更新路径均未同步刷新 outPutShapeMap

修复方案是在两条路径中统一用当前调用的 map 覆盖缓存 map,并增加回归测试覆盖旧缓存和 V2 缓存更新入口。

likedislike
Lliuyi424
8月12日 添加了label:bug-report
Lliuyi424
8月12日 修改了issue 的描述
liuyi424
8月12日 评论:

/assign @liuyi424

likedislike
CANN-robotCANN-robot成员
8月12日 将 liuyi424 设为负责人
CANN-robotCANN-robot成员
25 天前 关闭了 issue
CANN-robotCANN-robot成员
25 天前 添加了label:resolved