[Bugfix][GDN] Fix CuteDSL BF16 KKT inversion divergence (#53864)

Signed-off-by: Zoe923 <871844693@qq.com>
This commit is contained in:
Zoe923
2026-09-17 08:49:56 -07:00
committed by GitHub
parent 493d4b3c04
commit 6a7de3ba3a
2 changed files with 85 additions and 2 deletions
@@ -192,3 +192,86 @@ def test_gdn_chunk_cutedsl_correctness(num_seqs: int, state_dtype: torch.dtype):
assert no_buffer_state_error.mean().item() < 6e-4
assert buffer_o_error.max().item() == 0
assert buffer_state_error.max().item() == 0
def test_gdn_chunk_cutedsl_correlated_keys_stability():
"""Cover a KKT block where three BF16 Newton rounds diverge."""
total_tokens = 64
num_k_heads = 4
num_v_heads = 8
head_dim = 128
rng = torch.Generator("cuda").manual_seed(3456)
q = torch.zeros(
1,
total_tokens,
num_k_heads,
head_dim,
device="cuda",
dtype=torch.bfloat16,
)
k = torch.zeros_like(q)
q[..., 0] = 1
k[..., 0] = 1
v = torch.randn(
1,
total_tokens,
num_v_heads,
head_dim,
device="cuda",
dtype=torch.bfloat16,
generator=rng,
)
g = torch.zeros(
1,
total_tokens,
num_v_heads,
device="cuda",
dtype=torch.float32,
)
beta = torch.full_like(g, 0.9)
initial_state = torch.zeros(
1,
num_v_heads,
head_dim,
head_dim,
device="cuda",
dtype=torch.float32,
)
cu_seqlens = torch.tensor([0, total_tokens], device="cuda", dtype=torch.int32)
chunk_indices, chunk_offsets = prepare_metadata_cutedsl(cu_seqlens, total_tokens)
ref_o, ref_state = chunk_gated_delta_rule(
q=q,
k=k,
v=v,
g=g,
beta=beta,
initial_state=initial_state,
output_final_state=True,
cu_seqlens=cu_seqlens,
use_qk_l2norm_in_kernel=False,
)
actual_o, actual_state = chunk_gated_delta_rule_cutedsl(
q=q,
k=k,
v=v,
g=g,
beta=beta,
initial_state=initial_state,
cu_seqlens=cu_seqlens,
chunk_indices=chunk_indices,
chunk_offsets=chunk_offsets,
)
torch.accelerator.synchronize()
assert torch.isfinite(actual_o).all()
assert torch.isfinite(actual_state).all()
output_error = (actual_o.float() - ref_o.float()).abs()
state_error = (
actual_state.float() - ref_state.to(actual_state.dtype).float()
).abs()
assert output_error.max().item() < 1e-1
assert output_error.mean().item() < 2e-3
assert state_error.max().item() < 2e-1
assert state_error.mean().item() < 6e-4
@@ -573,8 +573,8 @@ class Sm100ChunkUWKernel:
for i in cutlass.range_constexpr(4):
M[i] = _bf16x2_sub(_bf16x2_neg(eye[i]), M[i])
# 3 rounds of Newton-Schulz
for _ in cutlass.range_constexpr(3):
# The fourth round keeps correlated-key KKT blocks stable in BF16.
for _ in cutlass.range_constexpr(4):
# First MMA: -AiM = Ai @ (-M)
cute.copy(stsm_atom, Ai_bf16, sA_ldsm[None, (warp_id_, warp_id_)])
cute.arch.sync_warp()