昇腾910B AI Core 内部存在多级硬件执行流水线,核心三级MTE单元分工 10B特有TQue流水线同步缺陷,950硬件流水线不存在该MTE2/MTE3异步冲突

问题根源、修复方案完整详细解释

一、背景基础概念(先理清昇腾910B硬件流水线)

昇腾910B AI Core 内部存在多级硬件执行流水线,核心三级MTE单元分工:

  1. MTE2:向量计算单元(VEC)执行层,负责向量运算、数据入队出队(TQue);
  2. MTE3:数据搬运/内存写入单元,负责把计算结果通过DataCopyPad写入UB(统一缓冲区);
  3. 硬件流水线天然异步:MTE2、MTE3是独立硬件通路,默认无强制同步屏障。

1.1 原方案:TQue 数据管理逻辑

业务逻辑:用 TQue<VECIN>EnQue(入队)、DeQue(出队)管理update更新数据

  • TQue 内部自带仅MTE2内部、MTE2→V向量单元的硬件同步机制;
  • TQue设计初衷只保障:MTE2流水线内部数据有序、MTE2计算完成后向量单元才能读取有效数据;
  • TQue不提供MTE2与MTE3之间的跨级同步屏障,这是底层硬件接口的固有限制。

1.2 核心Bug:缺少MTE2→MTE3同步,UB读到垃圾数据(UB脏读/未定义数据UB)

完整数据流拆解:

  1. MTE2通过TQue完成update数据的计算、缓存排队;
  2. MTE2流水线执行完毕后立刻释放流水线资源,不会阻塞等待下游MTE3;
  3. 代码中 DataCopyPad 写UB属于MTE3硬件操作,MTE3独立启动数据搬运;
  4. 硬件异步时序冲突:
    • 极端时序下:MTE2还没把完整有效的update数据写入中间缓存,MTE3已经提前发起DataCopyPad读取;
    • MTE3读取到的是UB中残留的旧脏数据、未初始化内存碎片,也就是日志里的「垃圾数据」;
  5. 本质:两条硬件流水线无显式同步栅栏,MTE3执行时机早于MTE2有效数据生产完成,产生数据竞争。

补充边界问题:事件ID循环内重复创建
原始代码如果把同步Event定义在循环体内,每一轮迭代申请新HardEvent事件ID。昇腾硬件事件ID池总量有限,循环次数多时会快速耗尽硬件事件资源,触发硬件报错、流水线卡死。

二、修复方案逐条拆解说明

修复总原则:不改动950芯片代码、不改动tiling分块逻辑,仅替换数据容器+新增跨MTE硬同步+优化事件生命周期。

2.1 容器替换:TQue → TBuf

  1. TQue适用场景:流水线内部排队、仅MTE2/VEC单元交互,无跨MTE同步能力;
  2. TBuf(Temporal Buffer 时序缓冲区)适用场景:承载跨MTE2/MTE3的中间计算数据;
    • TBuf是AI Core专用时序缓存,原生支持绑定硬件同步事件;
    • 可承载MTE2输出结果,稳定供给下游MTE3读取,替代依赖内部排队同步的TQue;
  3. 替换收益:
    • 脱离TQue仅支持MTE2流水线同步的限制;
    • 缓冲区生命周期可控,配合显式硬件事件做读写屏障;
    • 无需调整上层tiling分块、950兼容代码,只修改本地数据管理容器,符合改动约束。

2.2 新增显式跨级同步:HardEvent::MTE2_MTE3 硬件事件

HardEvent 是昇腾TBE DSL提供的硬件级同步事件MTE2_MTE3 是专门用于阻塞MTE3、等待MTE2流水线完成的同步标记:

  1. 同步流程标准写法:
    1)MTE2完成TBuf数据写入后,触发MTE2_MTE3事件发送信号
    2)MTE3执行DataCopyPad写UB之前,阻塞等待MTE2_MTE3事件就绪
  2. 硬件屏障效果:强制MTE3流水线必须等MTE2全部向量计算、TBuf数据落地完成后,才启动DataCopyPad内存写入;
  3. 彻底消除时序竞争,保证MTE3读取TBuf时一定是完整有效的update数据,杜绝UB脏读垃圾数据。

2.3 Event ID 移至循环外部,解决事件ID耗尽问题

  1. 错误写法(原代码):
for (auto loop : tile_loop) {
  HardEvent evt = HardEvent::MTE2_MTE3; // 每轮循环新建事件ID
  // MTE2计算、MTE3拷贝
}

每一轮循环申请独立硬件事件句柄,硬件事件池容量有限,大迭代场景下快速占满,报硬件资源不足。

  1. 修复写法:
// 循环外全局单次申请事件ID,复用同一个同步事件
HardEvent evt = HardEvent::MTE2_MTE3;
for (auto loop : tile_loop) {
  evt.Wait();  // MTE3阻塞等待
  // MTE2计算完成后 evt.Signal();
}
  • 只创建一次硬件事件句柄,循环内重复复用Signal/Wait;
  • 不占用额外硬件事件资源,彻底规避ID耗尽故障。

2.4 约束说明:不修改950代码、不修改tiling代码

  1. 950芯片算子代码:指适配昇腾950的独立TBE逻辑、硬件调度逻辑,本次修复仅针对910B TQue流水线缺陷,两类芯片硬件流水线设计不同,无需同步改动950分支;
  2. tiling分块代码:负责输入数据切分、循环迭代次数、块尺寸计算,是上层调度逻辑;本次问题是AI Core内部MTE流水线异步冲突,和数据分块无关,因此完全保留原有tiling逻辑,无性能、业务逻辑变更。

三、完整时序对比:修复前后数据流差异

修复前(TQue无MTE2-MTE3同步)

  1. MTE2启动TQue EnQue写入update数据
  2. MTE2流水线未完成,MTE3异步提前执行DataCopyPad读UB
  3. 读取到未就绪脏数据 → 计算结果错误、输出垃圾值

修复后(TBuf + MTE2_MTE3硬同步)

  1. 循环外预分配MTE2_MTE3硬件事件
  2. 单次迭代:
    ① MTE2向TBuf写入完整update数据;
    ② MTE2执行evt.Signal(),标记数据就绪;
    ③ MTE3启动DataCopyPad前执行evt.Wait(),硬件阻塞;
    ④ 收到MTE2就绪信号后,MTE3才读取TBuf、写入UB;
  3. 读写强有序,不存在脏读;事件复用无资源泄漏。

四、性能与兼容性补充说明

  1. 性能损耗极小:硬件同步事件是AI Core原生硬件屏障,无CPU/微指令额外开销,仅流水线时序对齐,不会明显降低吞吐;
  2. 兼容性:仅替换本地缓存容器+增加同步原语,上层tiling、950算子分支完全不动,回归测试范围小;
  3. 适用芯片范围:仅修复910B特有TQue流水线同步缺陷,950硬件流水线不存在该MTE2/MTE3异步冲突,无需同步修改。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐