Repository navigation
Cuda mmq moe oob fix - #28383
Cuda mmq moe oob fix#28383Herculians wants to merge 4 commits into
Conversation
8ae8da3 to
1e71507
Compare
The tile_y staging loop always reads a full J-wide tile from the y buffer. For MoE experts whose rows end at the end of the buffer this reads up to J-1 rows past the end of the allocation and can crash with an illegal memory access. Clamp the read to the valid columns of the tile, rows past them are never used. Assisted-by: GLM-5.3
The ids_dst buffer only has col_diff valid entries for each expert but is read J-wide in both MoE branches of mul_mat_q and in the stream-k fixup kernel. The values past col_diff are never used, do not read them. Assisted-by: GLM-5.3
ggml_cuda_mmq_get_J_max returns 0 when ne11 < 8, for example for MoE gate/up projections with broadcast activations, leaving no padding for the J-wide tile reads. Return the smallest valid J instead. Also pad the NVFP4 y_scale allocation, the stream-k fixup reads it J-wide. Assisted-by: GLM-5.3
256 experts, top-6, m=2048, k=4096, skewed expert distribution and broadcast activations, as produced by MoE gate/up projections. Assisted-by: GLM-5.3
1e71507 to
bb3c275
Compare
|
Can you check whether #29941 fixes these issues? |
|
Sorry, I forgot to mention: there were more issues found, see #29953 . In general these out-of-bounds issues should not be solved using explicit checks in device code since the performance is quite sensitive to those. So I would really not want to merge changes like in this PR if at all possible. |
|
Test set: MXFP4 DeepSeek-shape
#29941 does not fix my issues, but #29953 does! Remaining questions/proposals: |
|
Sorry, but I think we should be careful with adding new structs and large tests to It should not be necessary to pad I'm closing this PR in favor of the other one. |
What is not working:
Fresh server > first request (web UI vision chat, system prompt + one 1024×1536 PNG + short prompt: 743 prompt tokens) dies instantly.
Bug hunting:
SWIGLU_CLAMP is a sticky-error misattribution (async kernels; first checkpoint after the fault reports it).
CUDA_LAUNCH_BLOCKING=1 > names MUL_MAT_ID as the faulting op cuda-gdb with CUDA_DEVICE_WAITS_ON_EXCEPTION=1 > fault at mmq.cuh:926, tile_y[l] = by0[l], CUDA_EXCEPTION_30 Warp MMU Fault = global MMU fault, not shared memory.
mul_mat_q_process_tilestaging loop copies a full J-wide tile from the y buffer regardless of valid columns.When a MoE expert's rows end at the buffer end, the read walks past the mapped region >
Warp MMU Fault> sticky illegal-memory-access. Values pastcol_diffare never used, so it's a silent overread unless it crosses the pool's 2 MiB VMM mapping boundary.Proposed fixes:
ids_dstreads including stream-k fixupget_J_maxfloor forne11 < 8(the intended host-side tail ggml_cuda_mmq_get_J_max(...)*sizeof(block_q8_1_mmq) returns 0 for ne11 == 1 (broadcast MoE gate/up) > no tail at all)y_scaletailVerified:
10/10 pre-fix crashes, now 7/7 clean
test-backend-ops3464/3464 (RTX 4090) and 2199/2199 (RTX 5090)perf neutral-to-positive (386 > 360 microseconds on the n=512 case)
Environment:
c5a5535e6(build 10792, tag b10792)cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES="120;89"+cmake --build build --config ReleaseDeepSeek-V4-Flash-Vision-Exp- only FP8 converted to Q8_0, MXFP4 and other weigths are intact.--device CUDA0,CUDA1 --split-mode layer --n-gpu-layers all --tensor-split 1,0 --override-tensor "blk\.3[0-5]\..*_exps=CUDA0,blk\.(3[6-9]|4[0-2])\..*_exps=CUDA1,ffn_.*_exps=CPU" --mmproj /path_to_modelAdditional information
I found two stale-closed reports for the likely the same cause: #24174 and #25721
You unable to reproduce the #25721 because it is layout-dependence mechanism. The pool/layout state need to be produced by the model load and the specific allocation sequence of this request's ubatches. For example, with default
--ubatch-size 512, the 743-token prefill splits into ubatches 512 + 231 and 231-token ubatch crashes.Staging loop is shared by the Blackwell native-FP4 path and the dense ne11 < 8 path.
Requirements