Repository navigation
Conversation
The fused prompt-expert kernels (moe_fused.cu for the Strata Q2_0 pack, moe_fused_iq.cu native_kernel for the native packs) on sm_75, with STRATA_PF_FUSED=1 STRATA_PF_FUSED_SM75=1: - cp.async -> plain 16-byte copies (the barriers around them stay), prefetch.global.L2 kept; - mma m16n8k32 / m16n8k16 s8 -> four / two m8n8k16 (exact int32 sums, the same d as the sm_80 instructions), MAGIC as the C operand; - two activation stages on Turing (64 KB of shared memory); - native_kernel takes Q2_0 gate/up (64-value blocks, a block per stage), so the canonical Q2_0 pack (Q2_0 / Q2_0 layers) runs fused; on Turing only that pair is set up; - Turing, Q2_0: the two halves of a stage share the weight scale, so a row's dot is d (dx_0 dot_0 + dx_1 dot_1) - 11 % fewer instructions. RTX 2080 Ti, one layer, 512 experts top 10 (prefill_fused_iq_test, Q2_0 / Q2_0 pair added): 2048 tokens MMQ 12.98 ms -> fused 6.59 ms, 16384 tokens 55.08 -> 37.16 ms; fused vs MMQ rel RMS 2e-5, the same error against the FP32 reference. In the engine (canonical Q2_0 pack, 98K prompt, 16K chunks): prefill 58.3 -> 53.3 s; layer 0 expert rows vs MMQ: median rel 1.6e-7. Teacher-forced 2048 tokens at P = 16K / 32K / 64K: perplexity vs MMQ +3.4 % / -4.5 % / +0.6 % (FP16 path vs MMQ +0.7 % / +0.1 % / +0.3 %) - trajectory noise, no systematic shift; the verify phase (same tokens) 42.36 s MMQ, 42.28 s fused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Niko1221
pushed a commit
that referenced
this pull request
Oct 17, 2026
The fused prompt-expert kernels (moe_fused.cu for the Strata Q2_0 pack, moe_fused_iq.cu native_kernel for the native packs) on sm_75, with STRATA_PF_FUSED=1 STRATA_PF_FUSED_SM75=1: - cp.async -> plain 16-byte copies (the barriers around them stay), prefetch.global.L2 kept; - mma m16n8k32 / m16n8k16 s8 -> four / two m8n8k16 (exact int32 sums, the same d as the sm_80 instructions), MAGIC as the C operand; - two activation stages on Turing (64 KB of shared memory); - native_kernel takes Q2_0 gate/up (64-value blocks, a block per stage), so the canonical Q2_0 pack (Q2_0 / Q2_0 layers) runs fused; on Turing only that pair is set up; - Turing, Q2_0: the two halves of a stage share the weight scale, so a row's dot is d (dx_0 dot_0 + dx_1 dot_1) - 11 % fewer instructions. RTX 2080 Ti, one layer, 512 experts top 10 (prefill_fused_iq_test, Q2_0 / Q2_0 pair added): 2048 tokens MMQ 12.98 ms -> fused 6.59 ms, 16384 tokens 55.08 -> 37.16 ms; fused vs MMQ rel RMS 2e-5, the same error against the FP32 reference. In the engine (canonical Q2_0 pack, 98K prompt, 16K chunks): prefill 58.3 -> 53.3 s; layer 0 expert rows vs MMQ: median rel 1.6e-7. Teacher-forced 2048 tokens at P = 16K / 32K / 64K: perplexity vs MMQ +3.4 % / -4.5 % / +0.6 % (FP16 path vs MMQ +0.7 % / +0.1 % / +0.3 %) - trajectory noise, no systematic shift; the verify phase (same tokens) 42.36 s MMQ, 42.28 s fused.
Niko1221
added a commit
that referenced
this pull request
Oct 17, 2026
…capability through STRATA_EMULATE_CC like the other kernels
Niko1221
added a commit
that referenced
this pull request
Oct 17, 2026
…) calls it; the HIP build of #2145 as submitted did not compile)
Niko1221
added a commit
that referenced
this pull request
Oct 17, 2026
…n's only (sm_80+ with STRATA_PF_FUSED=1 is bit-identical to base again) The z440 A4000 Q2_0 gate with STRATA_PF_FUSED=1 on both arms found the residual dump different from base: gu_covered() took Q2_0 on every CUDA card and d.ok on sm_80+ now required the Q2_0 gate/up setup.
Owner
|
Thanks rafatxf. Ported with your authorship plus three changes of ours. The shared launch used host_astages() which did not exist in the HIP build, so we added it. The capability check follows our emulation switch for tests. And your Q2_0 gate/up addition reached sm_80+: with STRATA_PF_FUSED=1 an RTX A4000 with the Q2_0 pack stopped matching the old output (and prompt speed dropped 4.5 % at 4K), so it is now limited to the Turing opt-in (STRATA_PF_FUSED=1 STRATA_PF_FUSED_SM75=1). With that, the default and the sm_80+ opt-in paths are byte-identical to before. We could not measure the +9 % without a Turing card. |
Contributor
Author
|
Ported in 0.1.45, thanks! Turing numbers for |
chaog992
added a commit
to chaog992/Strata
that referenced
this pull request
Oct 27, 2026
…/ Q2_0 layers on the fused int8 kernels on sm_80+ A host whose CPU lacks the AVX-512 set setup looks for gets the native Q2_0 pack, and on a CUDA card of sm_80 or newer its Q2_0 gate/up layers read prompts through MMQ's Q2_0 kernel (its 128-wide tile: 255 registers with spills on sm_120, ptxas -v), because b6443f3 kept Niko1221#2145's fused coverage of that format to the Turing opt-in: with STRATA_PF_FUSED=1 an RTX A4000 stopped matching the old output and read 4K prompts 4.5% slower (the port note on this opt-in sets it up and takes it for the Q2_0 / Q2_0 layers under its own variable, so STRATA_PF_FUSED=1 keeps its bits and an unset engine is unchanged. A ctest entry runs the kernel test's Q2_0 / Q2_0 pair with the variable alone (the test's new --unset-pf-fused leaves STRATA_PF_FUSED unset instead of setting it to 1; 77 without a card and below sm_80, where nothing is set up with it unset). RTX 5080 (sm_120, 16 GB), i9-14900K (no AVX-512), Q2_0 native pack, 2,100 experts in VRAM, CPU prompt share off, against the same build unset: at the same 4,864-token chunk (4 interleaved rounds) prompts of 4K, 16K and 23K tokens read 2-3.5% faster; with --prefill auto (5 rounds) the fused path's smaller buffers make the chunk 5,632 instead of 4,864 and the 16K prompt reads 32-33% faster (2,592 -> 3,438 tok/s), the 23K one 14%, a 4K one 0-2%. Per layer the fused path is 1.3-1.9x the MMQ path with the same error against FP32 (prefill_fused_iq_test). First-token KL against the FP16 prompt path over 30 prompts of 1.5-4.6K tokens: fused 0.0110, MMQ 0.0112. Unset, the first-token logits are byte-identical to v0.2.2's. Tests: prefill_fused_iq_test --only='Q2_0 / Q2_0' --unset-pf-fused with STRATA_PF_FUSED_Q2N=1 passes on the RTX 5080.
Niko1221
pushed a commit
that referenced
this pull request
Oct 27, 2026
… sm_80+, STRATA_PF_FUSED_Q2N=1 (#3809) A PC whose CPU lacks the AVX-512 set that setup checks for gets the native Q2_0 pack. On a CUDA card of sm_80 or newer its Q2_0 / Q2_0 prompt experts run through MMQ, although the fused int8 kernel for that format (#2145) is in the binary and set up only on a Turing card (b6443f3). STRATA_PF_FUSED_Q2N=1 sets that kernel up on any sm_80+ card and takes it for the Q2_0 / Q2_0 layers, under its own variable so that STRATA_PF_FUSED=1 keeps its bits. STRATA_PF_FUSED=0 and STRATA_PF_FUSED_NATIVE=0 still turn it off. A failed setup leaves the occupancy as it was and the layers on MMQ. - moe_fused_iq.cu: DevInfo.q2n; dev_info() sets up Q2_0 gate/up when the switch is set; gu_covered() and native_supported() take the pair only when q2n is set (a Q2_0 gate with another down type is refused, as on Turing). - tests/cuda/prefill_fused_iq_test.cpp: --unset-pf-fused leaves STRATA_PF_FUSED unset (the engine's default) and skips below sm_80; CMakeLists.txt: the ctest entry prefill_fused_iq_test_q2n runs the Q2_0 / Q2_0 pair with the switch alone (exit 77 = skipped without an sm_80+ card; CUDA branch only). - docs/DETAILS.md: one section in the author's measured numbers (RTX 5080) and the A4000 caveat below. Unset (the default), nothing changes: dev_info() reads the variable once and sets nothing up, gu_covered() and native_supported() return what they returned. Read line by line against base: the Turing path (t75) and the HIP path are untouched. Set, the prompt arithmetic changes (first-token KL against FP16 0.0110, MMQ 0.0112, the author's figure) and the fused path's smaller buffers let --prefill auto pick a larger chunk, which is most of the author's 16K gain; the generated text can change. Not verified: an RTX A4000 (sm_86). The kernel was taken on every CUDA card in #2145 and then kept to Turing after an A4000 no longer matched the old output and read 4K prompts 4.5% slower; the PR does not repeat that run. Merge note: #3277 and #3779 change dev_info() and native_supported() in the same file. Tests: prefill_fused_iq_test_q2n and prefill_fused_iq_test pass on an RTX A4000 (sm_86, synthetic data); on the Q2_0 / Q2_0 layer the fused kernel is 1.76x / 1.30x / 1.24x the MMQ path at 2048 / 4864 / 8192 tokens with the same relative RMS against FP32. Builds on CUDA sm_86 (Linux) and sm_120 (MSVC). Not covered: no model run; the engine-level A4000 check is the gate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Turing the prompt path's experts always go through llama.cpp's MMQ: the fused int8 kernels (
moe_fused.cufor the Strata Q2_0 pack,moe_fused_iq.cu'snative_kernelfor the native packs, #136) need sm_80. On an RTX 2080 Ti MMQ's Q2_0 kernel runs at ~20-30 TOPS (255 registers with spills, one CTA per SM) and is the largest single cost of a long prompt read.This ports both to sm_75, opt-in on top of
STRATA_PF_FUSED=1withSTRATA_PF_FUSED_SM75=1:cp.async→ plain 16-byte copies (the barriers around them stay),prefetch.global.L2kept;mmam16n8k32 / m16n8k16 with s8 operands → four / twom8n8k16(rows g / g + 8 by k 0-15 / 16-31). The int32 sums are exact in any order, sodis what the sm_80 instruction gives; MAGIC is passed as the C operand of each pair's firstm8n8k16;smem_bytes/ the launch / the occupancy query take the device's depth (host_astages());native_kerneltakes Q2_0 gate/up (64-value blocks: a block per stage, as the down rows already read theirs), so the canonical Q2_0 pack (Q2_0 / Q2_0 in every layer) runs fused.gu_covered()lists Q2_0 on CUDA;DevInfo::t75:native_supportedanswers false for the others, which keep MMQ);T75_DEV): a stage's two 32-value halves share the block'sd, so a row's dot isd (dx_0 dot_0 + dx_1 dot_1)- 11 % fewer instructions (the kernel is bound by its FP32 epilogue on Turing, not the tensor pipe). sm_80+ keeps its code and bits.prefill_fused_iq_testgets the Q2_0 / Q2_0 pair, and skips the pairs a Turing card does not set up instead of failing.Setup
RTX 2080 Ti 22 GB (sm_75), i7-6700, CUDA 13.0, SM 1650 MHz, 240 W;
v0.1.43. Canonical Q2_0 pack,--prefill auto:16384,STRATA_BF16_TC=1,STRATA_SELECT_SIMT=2.Kernels (
prefill_fused_iq_test --only="Q2_0 / Q2_0", one layer, 512 experts, top 10)* before the Q2_0 epilogue change. Fused vs MMQ rel RMS 1.6e-5 - 2.7e-5; both 1.09e-2 against the FP32 reference (the int8 activations' own error).
prefill_fused_moe_test(Strata pack) passes too: 5.29 ms fused vs MMQ 3.67×, rel RMS 6.7e-5.Engine
98K prompt (16K chunks, two runs each, deterministic run to run): 58.3 → 53.3 s (+9.4 %). 4K: 3.63 → 3.54 s.
Accuracy in the engine: layer 0 of a 32K prompt (identical input on both paths), every one of the 163,840 (token, expert) rows of the expert output against MMQ's: median rel 1.6e-7, p99.9 2.6e-3, max 7.6e-3 (the rows where H's int8 rounding falls the other way); against the FP16 expert path (
STRATA_PREFILL_MMQ=0) MMQ and fused have the same error (median 1.08e-2).Teacher-forced, as in #655 / #2071 (the first P tokens through the prompt path, the next 2,048 through the verify windows,
STRATA_LOGPOS_TOPK=20):The perplexity moves either way (+3.4 %, −4.5 %, +0.6 %) - trajectory noise: the QSA selection is discrete, so any change of the prompt path's rounding gives KLs of this size (enabling only one layer's fused experts already moves the first logit by KL ~1e-3, as much as the FP16 path in every layer). The verify phase's time over the same 2,048 tokens: MMQ 42.36 s, fused 42.28 s.
The server here will run with
STRATA_PF_FUSED=1 STRATA_PF_FUSED_SM75=1.🤖 Generated with Claude Code