mudler / mudler/vllm.cpp

test_cuda_deepseek_v4's COMPUTE-on-CUDA case cannot discriminate the fused EXL3 MoE arm: doubling its output moves max |diff| by 4.6e-5 against a 1e-2 tolerance

Open
#2,500 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
423
Forks
53
Avg merge
20h 26m
Merged PRs (30d)
310

Description

Row: MODEL-DSV4-EXL3

test_cuda_deepseek_v4's case "W2: the EXL3 routed experts COMPUTE on CUDA and
agree with the CPU arm" reports max |diff| = 0 and passes CHECK(max_abs < 1e-2). That number reads as a strong correctness result for the fused EXL3 MoE
arm. It is not one. The case cannot discriminate the fused arm's output.

The measurement

Measured on thor:gpu0 (sm_110) under an rc lease, job
0e398e1f-44a3-454f-a801-a79c75a2d26a, on the tree that fixes the #2458 kernel
fault. Each mutation was applied to a scratch copy of src/vt/cuda/cuda_exl3.cu,
rebuilt (binary mtime checked), run, and the file restored byte-for-byte.

mutation of the fused MoE band's epilogue max |diff| verdict
none (baseline) 0 pass
store the finished tile to SHARED memory instead of global, so the last k-slice never reaches temp_intermediate 0 pass
drop the output Hadamard from the standalone GEMM (shmem_out_had = false) 0 pass
DOUBLE every value the band stores 4.57764e-05 pass

4.57764e-05 is exactly 3 / 65536. Doubling the entire routed-expert
intermediate moves the compared logits by one fp16 quantization step, against a
tolerance of 1e-2. That is 218x of headroom over a 2x error, so the two
mutations that vanished to exactly 0 are not a mystery: they are perturbations
that fell under the rounding floor of the path between the MoE band and the
logits.

Why this is a gate defect and not a fixture nitpick

The trace says the routing is real, not degenerate:

[dsv4 moe trace] ne=2 T=3 topk=1 H=256 mi=512 assignments=3 max_rows=128 num_active=1
[dsv4 moe trace] expert 0 count=3
[dsv4 moe trace] expert 1 count=0

Three tokens go to one expert, 3 <= max_rows, so the fused arm TAKES that
expert and the per-expert host loop skips it. The fused kernel's output is the
only source of expert 0's contribution to those logits, and doubling it is still
invisible.

The contrast that proves the geometry is the problem and not the algebra: the
CPU-side sibling test_deepseek_v4_exl3_forward gates the same op against a
dequantized-dense reference at rel_rms <= 2.0e-2, and doubling the CPU fused
MoE's scatter-add there takes rel_rms from ~0 to 0.373 and reds the suite
immediately. So the fused MoE contribution is gateable; this fixture's
comparison point just is not where it is visible.

What the case does prove

That the device forward completes without faulting, that the tower is
device-staged, and that the device and host arms agree bitwise on a workload
whose routed-expert contribution is at the quantization floor. Those are worth
having. The claim it does NOT support is "the fused arm computes the right
numbers on CUDA", and .agents/specs/model-dsv4-exl3.md should not be read as
saying so.

What is owed

A device gate whose failure signal is above the rounding floor. Options, not a
decision:

  • compare the fused arm against the per-expert loop arm on the SAME device queue
    and the same weights, which removes the lm_head and every non-MoE stage from
    between the mutation and the assertion;
  • assert on the MoE op's output tensor rather than on the model's logits;
  • widen the fixture so the routed experts dominate the compared row.

Whichever is chosen, the acceptance condition is a mutation test: doubling the
band's stored intermediate must red the gate.

Found while fixing #2458 (the dropped shmem_out_had template parameter). It is
filed rather than fixed in the same flow because it changes what a gate measures
for this row, which AGENTS.md routes through the row's own spec and a fresh
review rather than through an in-flow repair. Listed under ## Owed in
.agents/specs/model-dsv4-exl3.md.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the W2 case in test_cuda_deepseek_v4 and the fused implementation in src/vt/cuda/cuda_exl3.cu; read AGENTS.md and the ## Owed entry in .agents/specs/model-dsv4-exl3.md. Compare the device fused arm with the per-expert loop or assert on the MoE output, then run the CUDA case. Done means doubling the stored intermediate causes the gate to fail.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
machine-learning, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.