Repository navigation
Conversation
The fused routed+shared expert stack needs one bit width and group size, so a checkpoint whose shared expert is wider (oQ: 8-bit g64 over 4-bit g32 routed experts) was refused. When the widths differ, the shared expert now loads as its own projections at its own width and runs beside the routed launch; tf_moe_combine_gate adds it inside the same fp32 slot accumulation, weighted by the router's shared gate. Checkpoints whose widths match keep the fused stack, unchanged. Fixes ashhart#1599
|
Thanks for taking this on — supporting a shared expert at its own width is useful. A few things before it can leave draft:
|
Contract test at all three output kinds, bit-equal to tf_moe_combine with the shared expert as y's last slot, and usage records for every served chip.
…d stack core.quant.experts now stacks a same-width shared expert into the routed stack and leaves a wider one beside it as separate. This bridge always stacks, so a separate shared expert would be dropped and the router's last pick would index past the stack. Refuse it at the HIP host index, where both Bridge.init and fromCheckpointRank consume the stack, and test that a mixed-width qwen3_5-shaped expert set is refused.
Place the shared expert's row as the combine kernel's last slot and compare the two kernels' outputs at fp32, fp16 and bf16. The gate's own y keeps a poison value in that slot, so a gate that summed every slot instead of reading the shared operand could not match. Decode rows, a width that does not fill a block's columns, and a single routed slot beside the shared one.
|
Thanks, all three points are addressed in three new commits; receipts on gfx1151 (the only chip I have), TensorFold 1. Contract, device test, act.hip bytes
2. qwen3_5
Your concern was real. I served an oMLX oQ4e quantization of Qwen3.6-35B-A3B (8-bit g128 shared expert over 4-bit g64 routed experts) three ways: the base refuses it with 3. Token equality and the checkpoint
Other checks on the branch: |
What this changes
When a checkpoint's shared expert has a different bit width or group size from its routed experts, the HIP MoE loads it as its own projections (each tensor at its own width) and runs it beside the routed launch, instead of refusing the checkpoint; a new
tf_moe_combine_gateadds its row inside the same fp32 slot accumulation astf_moe_combine, weighted by the router's shared-expert gate. Matching widths keep the fused stack exactly as before. Fixes #1599.Receipt
7c068895plus this change,tensorfold-native 1.1.8built withzig build native-hip -Dhip-arch=gfx1151, Ubuntu archive HIP 7.1 (clang 21), AMD Ryzen AI MAX+ 395 with Radeon 8060Sgfx1151(128 GB unified memory). Checkpoints:TensorFold/Qwen3.8-Flash-Next-MLX-4bit-MTPrevision2b170fa6(fused path) and an oMLX oQ4e quantization of Qwen3.8-Flash-Next whose shared expert is 8-bit g64 over 4-bit g32 routed experts (separate path).--parallel 1 --context 131072 --prompt-cache-gib 0.token_sha256oftools/bench_openai.py,tools/bench_concurrent.pyand bothtools/bench_cache.pyprompts identical to the base build on the same machine;bench_concurrent --alone --serialevery cellalone3/3 and 12/12 equal,serialequal, 0 failed. Separate path (oQ4e): loads (stock refuses withdoes not stack with the shared expert),alone12/12 equal, 0 unequal, outputs deterministic across repeats.tools/bench_openai.py --tokens 256 --reps 3 --temperatures 0: fused path base 46.98 -> 46.59 tok/s (code), within run noise on a shared machine; separate path (oQ4e, no baseline exists since stock refuses it) 40.2 code / 37.1 chat tok/s, MTP 3 drafts.tools/bench_cache.py --require-coldon public 7,377- and 29,364-token arrays: fused path unchanged within noise (individual cold cells -1.0% to +0.7%).zig build test -Dhip=true --summary all466/466 steps, 0 failed; new host tests inexperts.zig(8-bit g64 shared over 4-bit g32 routed loads with both widths kept, rank slicing keeps the shared expert on rank 0 only, a 7-bit shared expert and a wrong shape still refuse) fail on the base with its refusal and pass with the change;zig build hip-kernel-test15/15 steps;zig build hip-kernel-contracton gfx1151:SUMMARY gfx1151 49 kernels: 49 pass gates 1-4, 0 fail, 0 known findings; 5 controls: 5 red as planted, 0 missed; 126 limit problems, the same as the base (the 126 limit problems are live-versus-recorded register counts under this machine's compiler, identical on the base);python3 tools/zig/lean_check.py425 on base and change;git diff --checkclean.tf_moe_combine_gateis not registered with the kernel contract: none of the Flash Next MoE kernels (tf_moe_combine,tf_moe_select,tf_moe_act,tf_moe_route) have contract entries yet, and I would rather agree how to cover that family than add one record alone.hip-kernel-contract-limitsstops on this machine's compiler attiles/dot2_tiles.hipfor gfx1100 (branch size exceeds simm16, same on the base, see HIP: dot2_tiles.hip fails to compile for gfx1100 with Ubuntu clang 21.1.8 ("branch size exceeds simm16") #1521). Metal and CUDA (HIP-only change); other AMD chips.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.SUMMARYline is in the receipt. (tf_moe_combine_gatenot yet registered, see above.)