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’b0000Normal, first victim默认缓存策略, L2自然管理通用数据, 多轮迭代复用4’b0001Last victim填充后标记为最先逐出输入数据, 只读一次4’b0010Persistent常驻L2, 不被逐出权重/常量, 反复复用4’b0100Not-alloc, keep不分配新cache line已缓存数据的二次读取4’b0101Clean清理(write-back但不逐出)确保数据一致性4’b0110Drop丢弃cache line不再需要的数据释放L2空间2.2 MTE3 写路径 Hint值名称对 MTE3 的影响推荐场景4’b0000Normal, first victim默认write-back中间结果(后续要读回)4’b0100Not-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_start4. MTE 与其他管线的 Cache 一致性4.1 MTE3 与 LD_DEV/ST_DEVMTE3 写数据到 GM (经过 L2 write-back) 另一个路径用 ST_DEV 写同一地址 (旁路 DCache, 不旁路L2 )4.2 MTE2 与 Scalar LD问题场景: Scalar Pipe 用 LD.b32 读 GM (经过 L2) MTE2 同步搬运同一区域 (也经过 L2) → 两个 Pipe 竞争同一 cache line5. 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 hintnormal; 否则 not-alloc 混合使用 MTE ATOM/RED: □ ATOM/RED 操作同一地址前后是否 DSB DCCI? □ MTE2 读取 ATOM 修改过的地址前是否先清理了 DCache? □ DCCI 选用定向清理 (OUT/ATOMIC) 而非 ALL? persistent 数据使用完毕: □ 是否主动设置 Drop hint 释放 L2? □ 是否确认后续 MTE 不再需要该数据?
[AI][昇腾950] MTE 与 L2 Cache 说明
发布时间:2026/6/26 8:41:32
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’b0000Normal, first victim默认缓存策略, L2自然管理通用数据, 多轮迭代复用4’b0001Last victim填充后标记为最先逐出输入数据, 只读一次4’b0010Persistent常驻L2, 不被逐出权重/常量, 反复复用4’b0100Not-alloc, keep不分配新cache line已缓存数据的二次读取4’b0101Clean清理(write-back但不逐出)确保数据一致性4’b0110Drop丢弃cache line不再需要的数据释放L2空间2.2 MTE3 写路径 Hint值名称对 MTE3 的影响推荐场景4’b0000Normal, first victim默认write-back中间结果(后续要读回)4’b0100Not-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_start4. MTE 与其他管线的 Cache 一致性4.1 MTE3 与 LD_DEV/ST_DEVMTE3 写数据到 GM (经过 L2 write-back) 另一个路径用 ST_DEV 写同一地址 (旁路 DCache, 不旁路L2 )4.2 MTE2 与 Scalar LD问题场景: Scalar Pipe 用 LD.b32 读 GM (经过 L2) MTE2 同步搬运同一区域 (也经过 L2) → 两个 Pipe 竞争同一 cache line5. 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 hintnormal; 否则 not-alloc 混合使用 MTE ATOM/RED: □ ATOM/RED 操作同一地址前后是否 DSB DCCI? □ MTE2 读取 ATOM 修改过的地址前是否先清理了 DCache? □ DCCI 选用定向清理 (OUT/ATOMIC) 而非 ALL? persistent 数据使用完毕: □ 是否主动设置 Drop hint 释放 L2? □ 是否确认后续 MTE 不再需要该数据?