Prhub

#34172 [diffusion] LTX-2 quality=high fused RMSNorm+modulate + FFN GELU epilogue (H200 ltx23-one-stage denoise 45.85->43.24 s, ~matches torch.compile)

原始 PR 作者 BBuf 合并时间 2026-08-10 09:46 文件变更 4 提交数 1 评论 2 代码增减 +229 / -17

执行摘要

LTX-2 新增 quality=high 融合核,去噪提速 5.7% 逼近 torch.compile

PR body 的 profiling 结论是方案起点:LTX-2 视频去噪在 H200 eager 下 GPU 占用约 89%,属计算密集型,可拆分的 CUDA graph 几乎无收益;torch.compile 的优势几乎全部来自两个 elementwise 链的融合——每个 transformer block 的 adaLN RMSNorm(x) * (1 + scale) + shift 调制,以及 FFN 的 GELU。kernel-time 归因显示 compile 把 GPU-op 总时间从 8.58M µs 压到 7.37M µs(-14%),GEMM 与 attention 均未改动。因此本 PR 的目标是在 eager 里手工复现这两处融合,让 high 档位逼近 compile,同时避开 compile 分钟级 warmup 与跨会话不确定性。

值得精读,三个看点:(1)profiling 归因方法——用 kernel-time 归因定位 torch.compile 优势全部来自 elementwise 融合,从而避免盲目上 CUDA graph,方法论可直接复用于其他 compute-bound 模型;(2)quality 门控的精度工程——显式承认 ≤ 1 ULP 差异,用质量档位而非运行时自检管理精度边界,lossless 默认保持 bit-exact;(3)复用与缓存——ones 权重缓存让 weightless RMSNorm 直接复用既有 fused_rmsnorm_scale_shift_bitexact 内核。建议后续将 PSNR 验收固化为 e2e CI 测试,并为 QualityGatedFusion handler 家族补充文档。

讨论亮点

本 PR 没有任何 review 评论(review_comments_count = 0),由作者 BBuf 自审并直接合并,缺乏独立审核交峰。唯一留下的讨论是 issue 评论中的 CI 状态说明:

"CI green on all required checks after re-running two flaky lanes: 14/14 call-multimodal-gen-tests SUCCESS (the initial jit-kernel-b200-test / multimodal-gen-test-1-5090 reds cleared on rerun with no code change), finish/lint/gate SUCCESS. Remaining reds are the repo's known non-required AMD/NPU/finish-aggregator lanes (red on merged #34008/#34085 as well)."

两条初始失败的 lane 经重跑转绿且无代码变更,剩余红色为仓库已知的非必需 AMD/NPU lane,与本次变更无关。

实现拆解

  1. Profiling 归因确定切入点:在 H200 上对比 ltx23-one-stage 的 5 步去噪 eager 与 torch.compile,确认 compute-bound(GPU-busy ≈ 89%)、CUDA graph 无收益、compile 的 -14% GPU-op 时间全部来自 elementwise 融合(aten vectorized_layer_norm、通用 elementwiseGELU 启动折叠为 Triton 融合核),GEMM/attention 未动。这决定了方案不做 CUDA graph,而是复现两处融合。
  2. 新增内核封装模块:新建 python/sglang/kernels/ops/diffusion/ltx2_rmsnorm_modulate.py,复用 QualityGatedFusion 基座(与 fused_linear_gelufused_ln_modulatefused_gate_rmsnorm 同族),提供 mark_ltx2_rms_norm_modulate_sitemount_ltx2_rms_norm_modulateunmount_ltx2_rms_norm_modulateltx2_rms_norm_modulate_active 四个钩子;利用 LTX-2 的 RMSNormNoWeight 无权重特性,通过按 (device, hidden) 缓存的 ones 张量复现均方根归一化语义;直接复用现有 fused_rmsnorm_scale_shift_bitexact Triton 内核,将 rms_norm(x) * (1 + scale) + shift 折叠为一次启动。can_fuse_ltx2_rms_norm_modulate 守卫仅放行 CUDA bf16,其余回退 eager。
  3. 模型接入:修改 python/sglang/multimodal_gen/runtime/models/dits/ltx_2.pyLTX2TransformerBlock.forward 中 6 个 adaLN 位置(视频/音频自注意力、视频/音频 prompt 交叉注意力、视频/音频 FFN 前调制)统一经新增 _ltx2_rms_norm_modulate 路由;LTX2FeedForward__init__ 中执行 mark_fused_gelu_site(self, "proj_in")forwardfused_gelu_activecan_fuse_linear_gelu 通过时走 fused_linear_gelu_tanh(cublasLt GELU epilogue),未挂载时保持原 proj_in + GELU 路径。
  4. 管线注册:在 python/sglang/multimodal_gen/runtime/pipelines_core/stages/denoising.py_QUALITY_FUSION_HANDLERS 元组新增 "LTX-2 fused RMSNorm+modulate" 成员,使 quality="high" 请求在批次边界统一 mount/unmount,与既有三个融合族(linear+GELU、LN+modulate、gate RMSNorm)共存;未标记站点的模型不受影响。
  5. 测试与验收:新增 test/registered/kernels/ops/diffusion/test_ltx2_rms_norm_modulate.py(注册 CUDA base-b-kernel-unit 与 AMD nightly CI),覆盖未挂载路径 torch.equal 于 eager 参考、挂载路径精确等于融合核输出且相对 eager 保持在 bf16 半精度舍入内;手工完成 PSNR 验收(全 121 帧 min 35.29 / mean 36.34 dB,验收线 > 25 dB)与 H200 性能基准(one-stage denoise 45.85 → 43.24 s)。
文件 模块 状态 重要度
python/sglang/multimodal_gen/runtime/models/dits/ltx_2.py 模型层 modified 7.81
python/sglang/kernels/ops/diffusion/ltx2_rmsnorm_modulate.py 融合内核 added 7.07
test/registered/kernels/ops/diffusion/test_ltx2_rms_norm_modulate.py 单元测试 added 7.04
python/sglang/multimodal_gen/runtime/pipelines_core/stages/denoising.py 去噪管线 modified 5.52

关键符号

_ltx2_rms_norm_modulate fused_ltx2_rms_norm_modulate can_fuse_ltx2_rms_norm_modulate _ones_weight mark_ltx2_rms_norm_modulate_site mount_ltx2_rms_norm_modulate unmount_ltx2_rms_norm_modulate ltx2_rms_norm_modulate_active LTX2FeedForward.forward LTX2TransformerBlock.forward

关键源码片段

python/sglang/multimodal_gen/runtime/models/dits/ltx_2.py core-logic

模型主路径:6 个 adaLN 位置与 FFN GELU 全部接入融合路由,是本 PR 的业务落地点,也是回归风险集中处(+69/-17)。

# ---- python/sglang/multimodal_gen/runtime/models/dits/ltx_2.py(重构后)----def _ltx2_rms_norm_modulate(
    block: nn.Module,
    rms_norm: nn.Module,
    x: torch.Tensor,
    scale: torch.Tensor,
    shift: torch.Tensor,
    eps: float,
) -> torch.Tensor:
    # 挂载且 per-call 守卫通过时走融合内核(≤ 1 bf16 ULP 差异)
    # 否则执行原样 eager 链,保证 lossless 默认路径逐位不变
    if ltx2_rms_norm_modulate_active(block) and can_fuse_ltx2_rms_norm_modulate(
        x, scale, shift
    ):
        return fused_ltx2_rms_norm_modulate(x, scale, shift, eps)
    return rms_norm(x, eps) * (1 + scale) + shift# LTX2TransformerBlock.forward 中视频自注意力支路的 adaLN 位置
# 原为内联表达式 self.rms_norm(...) * (1 + vscale_msa) + vshift_msa
norm_hidden_states = _ltx2_rms_norm_modulate(
    self, self.rms_norm, hidden_states, vscale_msa, vshift_msa, self.norm_eps
)# LTX2FeedForward.forward:proj_in 与 tanh-GELU 融合为 cublasLt epilogue
# fused_gelu_active / can_fuse_linear_gelu 双守卫,未挂载时保持原路径
def forward(self, x: torch.Tensor) -> torch.Tensor:
    if fused_gelu_active(self) and can_fuse_linear_gelu(self.proj_in, x):
        x = fused_linear_gelu_tanh(x, self.proj_in.weight, self.proj_in.bias)
    else:
        x, _ = self.proj_in(x)
        x = self.act(x)
    x, _ = self.proj_out(x)
    return x
python/sglang/kernels/ops/diffusion/ltx2_rmsnorm_modulate.py infrastructure

新增内核封装模块:复用 QualityGatedFusion 与既有 Triton 内核,引入 ones 权重缓存,是 quality=high 融合能力的核心载体。

# ---- python/sglang/kernels/ops/diffusion/ltx2_rmsnorm_modulate.py(新增)----_SITE_MARKER_ATTR = "_sgl_ltx2_rms_norm_modulate_site"
_SITE_ENABLED_ATTR = "_sgl_ltx2_rms_norm_modulate_enabled"# 与 fused_linear_gelu / fused_gate_rmsnorm 同族的 QualityGatedFusion 基座:
# mark 声明融合站点,mount/unmount 在 quality="high" 请求的批次边界切换
_FUSION = QualityGatedFusion(
    name="LTX-2 RMSNorm+modulate",
    marker_attr=_SITE_MARKER_ATTR,
    enabled_attr=_SITE_ENABLED_ATTR,
)# RMSNormNoWeight 不施加权重,ones 向量即可精确复现其数值语义;
# 按 (device, hidden) 缓存,避免每个 batch 重复分配 ones 张量
_ONES_WEIGHT_CACHE: dict[tuple[torch.device, int], torch.Tensor] = {}
​
​
def _ones_weight(x: torch.Tensor) -> torch.Tensor:
    key = (x.device, int(x.shape[-1]))
    w = _ONES_WEIGHT_CACHE.get(key)
    if w is None:
        w = torch.ones(x.shape[-1], device=x.device, dtype=torch.bfloat16)
        _ONES_WEIGHT_CACHE[key] = w
    return w
​
​
def can_fuse_ltx2_rms_norm_modulate(
    x: torch.Tensor, scale: torch.Tensor, shift: torch.Tensor
) -> bool:
    # 仅 CUDA bf16 允许融合;其余情况回退 eager 参考路径
    if x.dtype is not torch.bfloat16 or not x.is_cuda:
        return False
    # 复用既有 Triton 内核的布局 / 规格守卫
    return can_use_fused_rmsnorm_scale_shift(x, _ones_weight(x), scale, shift)
​
​
def fused_ltx2_rms_norm_modulate(
    x: torch.Tensor, scale: torch.Tensor, shift: torch.Tensor, eps: float
) -> torch.Tensor:
    # 单次内核启动完成 rms_norm(x) * (1 + scale) + shift
    return fused_rmsnorm_scale_shift_bitexact(x, _ones_weight(x), scale, shift, eps)
test/registered/kernels/ops/diffusion/test_ltx2_rms_norm_modulate.py test-coverage

新增测试覆盖两条关键行为:lossless 默认逐位一致、high 挂载走融合核且精度在 bf16 舍入内,并注册 CUDA/AMD CI。

# ---- test/registered/kernels/ops/diffusion/test_ltx2_rms_norm_modulate.py(新增)----# hidden 4096 = LTX-2 视频流,2048 = 音频流
@pytest.mark.parametrize("hidden", [4096, 2048])
def test_lossless_default_is_bitexact(hidden):
    # 标记但未挂载的站点(lossless 默认)必须与 eager 参考逐位一致
    block = nn.Module()
    mark_ltx2_rms_norm_modulate_site(block)
    rms, x, scale, shift = _inputs(hidden)
    out = _ltx2_rms_norm_modulate(block, rms, x, scale, shift, 1e-6)
    assert torch.equal(out, _eager(rms, x, scale, shift, 1e-6))
​
​
@pytest.mark.parametrize("hidden", [4096, 2048])
def test_mounted_high_uses_fused_kernel(hidden):
    block = nn.Module()
    mark_ltx2_rms_norm_modulate_site(block)
    assert mount_ltx2_rms_norm_modulate(block)
    try:
        rms, x, scale, shift = _inputs(hidden)
        out = _ltx2_rms_norm_modulate(block, rms, x, scale, shift, 1e-6)
        # 挂载路径必须精确等于融合内核输出
        assert torch.equal(out, fused_ltx2_rms_norm_modulate(x, scale, shift, 1e-6))
        # 且相对 eager 参考保持在 bf16 半精度舍入范围内
        ref = _eager(rms, x, scale, shift, 1e-6)
        assert torch.allclose(out.float(), ref.float(), atol=3e-2, rtol=1e-2)
    finally:
        unmount_ltx2_rms_norm_modulate(block)

评论区精华

CI 状态与 flaky lane 重跑 other

无实质 review 评论。作者 BBuf 在 issue 评论中说明 CI 情况:初始 jit-kernel-b200-test 与 multimodal-gen-test-1-5090 两条 lane 变红,重跑后 14/14 call-multimodal-gen-tests SUCCESS,期间无任何代码变更;剩余红色是仓库已知非必需的 AMD/NPU/finish-aggregator lanes,在已合并的 PR #34008、#34085 上同样为红。

结论:两条 flaky lane 经重跑通过,代码无需修改;非必需 lane 的红色与本次变更无关。 · 已解决

风险与影响

  1. 精度路径:融合核非 bit-exact(rsqrt.approx vs aten 的 rsqrtf,≤ 1 bf16 ULP),仅 quality="high" 启用;PSNR 验证(min 35.29 dB)通过,但该验证是手工 benchmark,未固化为自动化 CI 回归测试,后续内核微调可能引入精度漂移而不被及时发现。
  2. 默认路径安全:lossless 默认完全未改动,仍走原样 eager 参考链(bit-exact),默认用户无回归风险。
  3. 模型主路径改动ltx_2.pyforward 修改了 6 个 adaLN 调用点,若 can_fuse_ltx2_rms_norm_modulate 或 mount 门控出现漏洞(如非 CUDA / 非 bf16 环境误启用),会产生静默数值偏差;当前有双重守卫(mount 状态 + per-call 检查)与单元测试兜底。
  4. 平台依赖:融合路径依赖 fused_rmsnorm_scale_shift_bitexact Triton 内核在目标平台的可用性,AMD 等平台由 can_use_fused_rmsnorm_scale_shift 判定,不可用即回退 eager,性能收益随之消失但正确性不受影响。
  5. 审核缺口:该 PR 无 review 评论即合并,融合路径(尤其精度门控语义)缺少独立技术审核,属于流程性风险。

用户侧:LTX-2 推理用户在 quality="high" 下获得约 5.7% 去噪提速(one-stage 场景),与 torch.compile 相当但无 warmup;quality 语义新增中间档位,lossless 默认行为逐位不变。系统侧:新增 python/sglang/kernels/ops/diffusion/ltx2_rmsnorm_modulate.py 模块,denoising 阶段 fusion handler 增至 4 族;其他 Diffusion 模型未标记站点,完全不受影响。团队侧:进一步确立"QualityGatedFusion + 站点标记 + 批次边界挂载"的可扩展融合模式,后续模型接入成本低,但该模式目前缺少成文文档,依赖代码内注释传递约定。

非 bit-exact 精度路径(≤ 1 bf16 ULP) 仅 quality=high 启用,默认 lossless 不变 PSNR 验收未固化为自动化 CI 依赖既有 Triton 内核可用性 无 review 审核直接合并

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论