[AI][昇腾950] MTE 与 L2 Cache 说明
·
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 不再需要该数据?
更多推荐




所有评论(0)