MTE 与 L2 Cache 说明与注意事项

1. MTE 数据搬运与 L2 Cache 的交互

1.1 MTE2 (GM → UB/L1) — 读路径

GM ──read──► L2 Cache ──hit/miss──► MTE2 Engine ──► UB / L1

场景 A: L2 Cache Hit
  GM数据已在L2中 → MTE2直接从L2读取 → 延迟低, 带宽高
  例: 反复使用的权重矩阵, 已被前次MTE2加载到L2

场景 B: L2 Cache Miss
  GM数据不在L2 → 必须从DDR读取到L2 → 再由MTE2读取 → 延迟高
  例: 首次加载新Tile的输入数据

场景 C: L2 Cache Persistent Hit (CTRL[19:16]=0010)
  权重被标记为persistent → 常驻L2 → 所有Tile循环中持续命中
  例: GEMM中同一块权重被N个输出Tile复用

1.2 MTE3 (UB → GM) — 写路径

UB ──► MTE3 Engine ──write──► L2 Cache ──write-back──► GM

场景 A: Normal Write-Back (CTRL[23:20]=0000)
  MTE3写入L2 → 数据暂存L2 → 后续读回可命中 → 减少GM带宽
  例: 中间结果写入后紧接着bias-add等后处理读回

场景 B: Not-Alloc / Clean-Invalid (CTRL[23:20]=0100)
  MTE3写入L2 → 写后即逐出 → 不占用L2空间
  例: 最终输出, 不再读回

场景 C: Write-Through-Share (CTRL[23:20]=1100)
  MTE3写入同时传播到GM → 其他Core立即可见
  例: 多核共享的flag/counter写入

2. CTRL 寄存器 L2 Cache Hint 配置

2.1 MTE2 读路径 Hint

名称 对 MTE2 的影响 推荐场景
4’b0000 Normal, first victim 默认缓存策略, L2自然管理 通用数据, 多轮迭代复用
4’b0001 Last victim 填充后标记为最先逐出 输入数据, 只读一次
4’b0010 Persistent 常驻L2, 不被逐出 权重/常量, 反复复用
4’b0100 Not-alloc, keep 不分配新cache line 已缓存数据的二次读取
4’b0101 Clean 清理(write-back但不逐出) 确保数据一致性
4’b0110 Drop 丢弃cache line 不再需要的数据释放L2空间

2.2 MTE3 写路径 Hint

名称 对 MTE3 的影响 推荐场景
4’b0000 Normal, first victim 默认write-back 中间结果(后续要读回)
4’b0100 Not-alloc, clean-invalid 不分配cache, 直接写GM 最终输出(不再读回)

3. MTE L2 Cache 预取策略

3.1 MTE2 预取时机

  • 最佳预取时机: MTE2 发起搬运之前的 ~50-100 条标量指令周期
  • 在昇腾950 没有 MTE2 的预取L2 的能力,可以使用 dc_preload 实现scalar预取到L2, 然后MTE2 从L2 获取的方式(有点绕)
无预取:
  T0: MTE2 DataCopy GM → UB (tile_0)
      ← L2 Cold miss, MTE2 等待 DDR 读取, 延迟 ~100ns

优化模式 (提前预取):
  T0: DC_PRELOADI [tile_1_addr], 7     ← 提前预取 8 条 cache line (512B)
  T1-T80: 其他标量/计算指令              ← 预取在后台进行
  T81: MTE2 DataCopy GM → UB (tile_1)   ← L2 Cache Hit, 延迟 ~2ns

预取距离计算:
  prefetch_distance = DDR_latency / scalar_throughput × safety_factor
  例: 100ns / 2ns × 1.5 ≈ 75 条指令

循环预取模式 (双缓冲):
  loop_start:
    DC_PRELOADI [next_tile_addr], #num_lines   ; 预取下一个Tile
    MTE2 DataCopy GM → UB (current_tile)       ; 搬运当前Tile (已在L2)
    Compute(current_tile)                       ; 计算
    ; next_tile 的预取与当前计算并行进行
    ... update addrs ...
    JMP loop_start

4. MTE 与其他管线的 Cache 一致性

4.1 MTE3 与 LD_DEV/ST_DEV

  MTE3 写数据到 GM (经过 L2 write-back)
  另一个路径用 ST_DEV 写同一地址 (旁路 DCache, 不旁路L2 )

4.2 MTE2 与 Scalar LD

问题场景:
  Scalar Pipe 用 LD.b32 读 GM (经过 L2)
  MTE2 同步搬运同一区域 (也经过 L2)
  → 两个 Pipe 竞争同一 cache line

5. MTE L2 Cache 性能优化

MTE2 理论带宽:
  L2 Cache Hit:  接近片上带宽 (~数百 GB/s)
  L2 Cache Miss: 降至 DDR 带宽 (~100 GB/s)
  → L2 Hit Rate 直接决定 MTE2 实际带宽

提升 L2 Hit Rate 的方法:
  1. 权重 persistent hint → 权重常驻 L2
  2. 输入 last-victim hint → 不浪费 L2 空间给不复用数据
  3. DC_PRELOAD 预取 → 提前填充 L2
  4. Tile 尺寸设计 → 确保 Tile 数据量 ≤ L2 容量

6. 注意事项与陷阱

MTE2 (GM → UB) 搬运前:
  □ 权重数据是否设置了 persistent hint 
  □ 一次性输入是否设置了 last-victim hint  
  □ 是否需要 DC_PRELOAD 预取下一个 Tile?
  □ 地址是否与 non-cached 区域 (ATOM/LD_DEV) 隔开 ≥ 4KB?

MTE3 (UB → GM) 写回后:  
  □ 写后是否还有后处理读回? 是则 ST hint=normal; 否则 not-alloc

混合使用 MTE + ATOM/RED:
  □ ATOM/RED 操作同一地址前后是否 DSB + DCCI?
  □ MTE2 读取 ATOM 修改过的地址前是否先清理了 DCache?
  □ DCCI 选用定向清理 (OUT/ATOMIC) 而非 ALL?

persistent 数据使用完毕:
  □ 是否主动设置 Drop hint 释放 L2?
  □ 是否确认后续 MTE 不再需要该数据?
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐