[Kernel] Fuse Q/K RMSNorm and RoPE (#5990)

Signed-off-by: Bo Li <22713281+bobboli@users.noreply.github.com>
Signed-off-by: lishunyang12 <lishunyang12@163.com>
Signed-off-by: Mengjie Zhao <zmj0129@gmail.com>
Co-authored-by: lishunyang12 <lishunyang12@163.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-08-14 00:46:59 +00:00
1 parent 90a08c0eda
commit 596c16a550
5 files changed
+420 -27

No files matched your search

@@ -33,6 +33,7 @@ from vllm_omni.diffusion.distributed.sp_plan import (
SequenceParallelInput,
SequenceParallelOutput,
)
from vllm_omni.diffusion.layers.fused_qk_norm_rope import fused_qk_norm_rope
from vllm_omni.diffusion.layers.norm import RMSNorm
from vllm_omni.diffusion.layers.rope import RotaryEmbedding
@@ -237,6 +238,15 @@ class MiniMaxH3Rope(nn.Module):
return torch.cat((half, half), dim=-1) # [S, 96]
def _build_rope_table(freqs: torch.Tensor) -> torch.Tensor:
"""Materialize H3's packed ``[cos(freqs[:48]), sin(freqs[:48])]`` table."""
half = freqs.shape[-1] // 2
return torch.cat(
(torch.cos(freqs[..., :half]), torch.sin(freqs[..., :half])),
dim=-1,
).to(_BF16_DTYPE)
class MiniMaxH3TimeEmbedder(nn.Module):
def __init__(
self,
@@ -453,7 +463,7 @@ class MiniMaxH3Attention(nn.Module):
self,
x: torch.Tensor,
*,
rope_freqs: torch.Tensor | None,
rope_table: torch.Tensor | None,
cu_seqlens: torch.Tensor,
max_seqlen: int,
packed_total: int | None = None,
@@ -479,11 +489,18 @@ class MiniMaxH3Attention(nn.Module):
q = q.view(total, self.num_heads, self.head_dim)
k = k.view(total, self.num_kv_heads, self.head_dim)
v = v.view(total, self.num_kv_heads, self.head_dim)
q = self.q_norm(q)
k = self.k_norm(k)
if rope_freqs is not None:
q = self._apply_rope(q, rope_freqs)
k = self._apply_rope(k, rope_freqs)
if rope_table is None:
q = self.q_norm(q)
k = self.k_norm(k)
else:
q, k = fused_qk_norm_rope(
q,
k,
self.q_norm.weight,
self.k_norm.weight,
rope_table,
self.q_norm.variance_epsilon,
)
# The packed layout uses a second document for alignment padding.
# Local/Ulysses backends unpad it, while Ring keeps aligned rows for
@@ -628,7 +645,7 @@ class MiniMaxH3TokenRefinerBlock(nn.Module):
) -> torch.Tensor:
x = x + self.attn(
self.norm1(x),
rope_freqs=None,
rope_table=None,
cu_seqlens=cu_seqlens,
max_seqlen=max_seqlen,
)
@@ -707,7 +724,7 @@ class MiniMaxH3DiTBlock(nn.Module):
*,
t_emb: torch.Tensor,
combined_indices: torch.Tensor,
rope_freqs: torch.Tensor,
rope_table: torch.Tensor,
cu_seqlens: torch.Tensor,
max_seqlen: int,
packed_total: int,
@@ -735,7 +752,7 @@ class MiniMaxH3DiTBlock(nn.Module):
h = _modulate_scale_shift(h, shift_msa, scale_msa, combined_indices, dtype=_BF16_DTYPE)
h = self.attn(
h,
rope_freqs=rope_freqs,
rope_table=rope_table,
cu_seqlens=cu_seqlens,
max_seqlen=max_seqlen,
packed_total=packed_total,
@@ -817,10 +834,10 @@ class MiniMaxH3SPPrepare(nn.Module):
def forward(
self,
hidden_states: torch.Tensor,
rope_freqs: torch.Tensor,
rope_table: torch.Tensor,
combined_indices: torch.Tensor,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
return hidden_states, rope_freqs, combined_indices
return hidden_states, rope_table, combined_indices
class MiniMaxH3SPGather(nn.Module):
@@ -1153,8 +1170,8 @@ class MiniMaxH3DiTModel(nn.Module):
if inverse_indices.shape[0] != seq_len:
raise ValueError(f"inverse_indices must be [{seq_len}], got {list(inverse_indices.shape)}")
device = x.device
# Compute RoPE frequencies over the full packed sequence.
rope_freqs = self.rope(img_position_ids).to(device)
# Compute the packed RoPE table once for all transformer blocks.
rope_table = _build_rope_table(self.rope(img_position_ids).to(device))
decoder_input, t_emb = self._embed(
x=x,
@@ -1175,7 +1192,7 @@ class MiniMaxH3DiTModel(nn.Module):
hidden = decoder_input
cu_seqlens = cu_seqlens.to(device)
block_rope = rope_freqs
block_rope = rope_table
block_combined = combined_indices
hidden, block_rope, block_combined = self.sp_prepare(
@@ -1188,7 +1205,7 @@ class MiniMaxH3DiTModel(nn.Module):
hidden,
t_emb=t_emb,
combined_indices=block_combined,
rope_freqs=block_rope,
rope_table=block_rope,
cu_seqlens=cu_seqlens,
max_seqlen=max_seqlen,
packed_total=seq_len,