Optimize the add_rms_norm_dynamic_quant operator and extract performance optimization points into tilelang-perf-optimization skills - #1430
Conversation
|
👋 Hi! Thank you for contributing to the TileLang project. Please remember to run We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work! 🚀 |
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive performance optimization guidelines, compiler limitation documentation, and a highly optimized 2-pass implementation of the fused AddRmsNormDynamicQuant operator for Ascend NPU. The review feedback highlights critical issues in the new operator implementation, including severe precision loss from using CAST_RINT instead of CAST_NONE during float32 to float16/bfloat16 casting, potential V pipe RAW hazards in the dual-kernel implementations under AUTO_SYNC=True, and out-of-bounds memory access risks when the dimension H is not a multiple of block_N due to a lack of partial block handling.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| T.tile.cast(x1_fp32, x1_ub[cur, :, :], "CAST_NONE", tile_elements) | ||
| T.tile.cast(x2_fp32, x2_ub[cur, :, :], "CAST_NONE", tile_elements) | ||
| T.tile.add(h_fp32, x1_fp32, x2_fp32) | ||
| T.tile.cast(out_dtype_ub, h_fp32, "CAST_RINT", tile_elements) |
There was a problem hiding this comment.
在将 h_fp32(残差相加结果)转换为 out_dtype_ub 并写入 x_out 时,代码使用了 "CAST_RINT" 模式。"CAST_RINT" 会将浮点数四舍五入为最接近的整数。由于 h_fp32 是连续的浮点值(非整数),使用 "CAST_RINT" 会导致 x_out 丢失所有小数部分,造成严重的精度损失。应该使用 "CAST_NONE" 进行标准的 float32 到 float16/bfloat16 的类型转换,以保留小数精度。此问题同样存在于第 182 行、第 419 行、第 443 行、第 679 行和第 703 行,请一并修改。
| T.tile.cast(out_dtype_ub, h_fp32, "CAST_RINT", tile_elements) | |
| T.tile.cast(out_dtype_ub, h_fp32, "CAST_NONE", tile_elements) |
| x1_fp32 = T.alloc_ub([ROWS, block_N], "float32") | ||
| x2_fp32 = T.alloc_ub([ROWS, block_N], "float32") | ||
| h_fp32 = T.alloc_ub([ROWS, block_N], "float32") | ||
| hw_fp32 = T.alloc_ub([ROWS, block_N], "float32") |
There was a problem hiding this comment.
在 _kernel_readback 中,hw_fp32 被用于连续的 in-place 操作(例如 Pass 1 中的 mul 之后紧跟 abs,以及 Pass 2 中的连续 in-place 链)。根据您在 compiler-limitations.md 和 optimization-guide.md 中记录的编译器限制,在 AUTO_SYNC=True 下,这种连续的 dst -> src 依赖链极易触发 V pipe RAW 冒险(RAW hazard),导致非确定性的精度测试失败。建议像在 _kernel_single 中那样,引入交替 buffer hw_a 和 hw_b 来消除这种冒险。此问题同样存在于 _kernel_recompute(第 361 行),请一并修改。
| hw_fp32 = T.alloc_ub([ROWS, block_N], "float32") | |
| hw_a = T.alloc_ub([ROWS, block_N], "float32") | |
| hw_b = T.alloc_ub([ROWS, block_N], "float32") |

PR内容:Skill 优化&新增算子
Skill 优化
问题简述
背景: add_rms_norm_dynamic_quant算子实际优化过程经过R0 - R7多轮迭代,之前遇到优化瓶颈等相关问题,PR基于实际开发中的相关问题,对于skill提出相应的优化建议。其中,R0 - R7的优化流程如下:
GM 读取 6x
数学变换:
max(|h * inv_rms * gamma|) = inv_rms * max(|h * gamma|)GM 读取 6x → 4x
gamma 预加载
向量化广播
MTE2/V/MTE3 流水线重叠
block_M: 4→16自适应
block_N(H<256 时block_N=H)UB 利用率 10%→42%
消除尾块
block_M: 16→32条件性
x_outreadback(双 kernel)问题:小 shape 退化 15~47%
原因:未评估分发开销(
.item()约 5~15μs)mul_add_dst融合问题:bandwidth-bound 上尝试 compute-bound 优化
原因:缺少瓶颈预判
block_M(4→8→16→32)
问题:
block_M=16在双 kernel 下退化 15~28%原因:未做交叉实验,错过全局最优组合
AUTO_SYNC=FalseFixed Core
问题 1:
AUTO_SYNC=False导致 17/20 精度失败(V pipe 队列排空问题)问题 2:Fixed Core 编译失败(TVM StmtSimplifier bug)
原因:编译器限制未记录
意外发现:
AUTO_SYNC=True下需要交替 buffer(hw_a/hw_b)消除 RAW hazardM<1024: 单 kernel +
block_M=16M≥1024: 双 kernel +
block_M=32解决 R4 小 shape 退化
分发开销评估
一、优化角度(5个维度)
1. 工作流程优化(新增3个强制门禁步骤)
优化内容:
优化理由:
block_M(浪费 1 轮)2. 参考文档完善(新增2个关键文档)
优化内容:
references/compiler-limitations.mdAUTO_SYNC=False+ V pipe 指令队列排空问题mul_add_dst在 bandwidth-bound 上无收益AUTO_SYNC=True下连续 tile 指令的 V pipe RAW hazardreferences/best-practices/vector_fused_operator_optimization.md优化理由:
AUTO_SYNC=False和 Fixed Core 都失败(编译器限制未记录)3. 决策指导强化(新增3个关键章节)
优化内容:
max(|h * inv_rms * gamma|) = inv_rms * max(|h * gamma|)AUTO_SYNC=True下连续 tile 指令存在 RAW 依赖hw_a/hw_b交替 buffer.item()host 同步开销(约 5~15μs)overhead_ratio = dispatch_overhead_us / kernel_us优化理由:
AUTO_SYNC=True下存在 RAW hazard,需要交替 buffer4. 反模式识别(新增2个反模式)
优化内容:
block_M: 4→8→16→32)优化理由:
block_M,未与 kernel 架构做交叉实验(浪费 1 轮)5. 代码示例更新(更新同步模式和Vector核示例)
优化内容:
AUTO_SYNC=FalseAUTO_SYNC=True(当前编译器推荐)AUTO_SYNC=FalseAUTO_SYNC=True+ 手动三路 flag(mte3→mte2、mte2→v、v→mte3)优化理由:
AUTO_SYNC=False存在 V pipe 队列排空问题(17/20 精度失败)AUTO_SYNC=False,会误导后续 Vector 算子二、之前 Skill 的漏洞和优化逻辑问题(8个问题)
漏洞1:缺少瓶颈预判机制
漏洞2:允许单维度递增搜索
block_M与 kernel 架构的紧耦合关系未被发现。漏洞3:缺少组合优化验证
漏洞4:编译器限制未记录
AUTO_SYNC=False+ Fixed Core 都失败)。references/compiler-limitations.md漏洞5:算法层优化优先级不明确
漏洞6:分发开销评估缺失
新增算子
新增 add_rms_norm_dynamic_quant 算子,以下为CANN-BENCH测试报告,在A3上进行测试,对比baseline为pytorch npu下实现的实测结果,加速比为0.64x,以下为精度与性能对比测试报告:
算子评测报告
评测代号: cann_final_eval_20260717_191555
评测时间: 2026-07-17T19:15:55.319301
设备: npu:0
框架版本: V0.4.0
评测集版本: tasks-v0.4.0
概览
算子详情
AddRmsNormDynamicQuant(level3/add_rms_norm_dynamic_quant)