Skip to content

#606: the fused SwiGLU q8_1 quantizers keep the block's scale and sum finite too - #838

Closed
sergqwer wants to merge 1 commit into
Niko1221:mainfrom
sergqwer:pr/q8_1-finite-fused
Closed

sergqwer wants to merge 1 commit into
Niko1221:mainfrom
sergqwer:pr/q8_1-finite-fused

Conversation

@sergqwer

@sergqwer sergqwer commented Oct 4, 2026

Copy link
Copy Markdown

Completes the #606 clamp. 0.1.39 made two q8_1 activation quantizers keep the block's fp16 scale and sum finite: q8_1_store in iq_kernels.cu and native_quantize_q8_1_kernel in native_mmvq.cu. Two fused SwiGLU + q8_1 kernels still store the block raw:

kernel where it runs
native_swiglu_quantize_q8_1_kernel (native_mmvq.cu:166-169) the shared expert, decode (shared_expert.cu:203) and the multi-token pass (:310); on by default (STRATA_FUSED_SWIGLU_Q81 unset)
native_gu_fused_kernel (iq_kernels.cu:2416-2420) the routed experts' fused gate/up on gfx906 builds with STRATA_EXP_MODE=8 (IQ types 18/21/22/23)

Both now go through q8_1_finite / q8_1_quant / q8_1_ds, the same three lines as their siblings. Every block that was finite before is stored bit for bit as before, so normal output does not change.

rwkeyes found the first one in #606 but has no NVIDIA card to test it. The second one turned up in a sweep for amax / 127.0f after it; nothing else in src stores a q8_1 block without the clamp now.

Test

iq_multi_parity's #606 check now runs native_swiglu_quantize_q8_1 as a third path. It uses gate = 32 and up = x / 32: silu(32) is exactly 32 in float, so the fused kernel sees the same activations x as the other two paths and is held to the same expectations.

RTX 5090, CUDA 13, sm_120:

# this branch
q8_1 finite (quantize_q8_1_rows): 237 finite blocks as before, 3 overflowed blocks clamped finite
q8_1 finite (native_quantize_q8_1): 237 finite blocks as before, 3 overflowed blocks clamped finite
q8_1 finite (native_swiglu_quantize_q8_1): 237 finite blocks as before, 3 overflowed blocks clamped finite
iq_multi_parity: 0 failures

# the same test with native_mmvq.cu from v0.1.39
q8_1 finite (native_swiglu_quantize_q8_1): 237 finite blocks as before, 0 overflowed blocks clamped finite  FAIL
iq_multi_parity: 4 failures

The gfx906 kernel is not covered: I have no gfx906 card to run it on. Its change is the same three lines as q8_1_store in the same file.

Data point

On a fork of 0.1.39 (RTX 5090), a Qwen3.8-Flash-Next served conversation also turned into '!' (token 0) mid-thinking at about 99K positions, and later requests carrying that history kept producing it. Replaying the conversation up to that point did not reproduce it. So I cannot tie that run to this kernel; it is only the same symptom #606 describes, on a build that still had this store unclamped.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio

… finite too

0.1.39 clamped two q8_1 activation quantizers (#606: an fp16 sum or scale past 65504 rounds to inf, the dot products
then read inf * 0 = NaN, and a NaN in the residual ends as one token repeated). Two more store the block unclamped:
- native_swiglu_quantize_q8_1_kernel (native_mmvq.cu), the shared expert's fused SwiGLU + q8_1, on by default
  (STRATA_FUSED_SWIGLU_Q81) in decode and the multi-token pass;
- native_gu_fused_kernel (iq_kernels.cu), the routed experts' fused SwiGLU + q8_1 (gfx906 builds, STRATA_EXP_MODE=8).
Both now go through q8_1_finite / q8_1_quant / q8_1_ds as their siblings do: every finite block is stored bit for bit
as before. iq_multi_parity's #606 check covers the shared expert's one (gate = 32, up = x / 32: its activations are x
exactly). rwkeyes found the first one (#606).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio
txiki739 added a commit to txiki739/Strata3090-5060TI that referenced this pull request Oct 5, 2026
…Niko1221#606, 19de7f4 + PR Niko1221#838) at this fork's five sites

A q8_1 block stores d = amax / 127 and the sum of its 32 values as fp16: past 65504 they round to inf and the dot
products read inf * 0 = NaN, after which the model answers one token forever (upstream saw 36,689 "!" tokens;
ggml-org/llama.cpp#23606 is the same defect). include/strata/kernels/q8_1_finite.hpp is upstream's helper. Here the
quantizers are q8_1_store and the fused gate/up + SwiGLU entry loop (iq_kernels.cu), native_quantize_q8_1 and its
interleaved copy (native_mmvq.cu), and the router kernel's q8_1 rows (native_router.cu, its own rounding kept).
Every block that was finite before is stored bit for bit as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
txiki739 added a commit to txiki739/Strata3090-5060TI that referenced this pull request Oct 5, 2026
@sergqwer sergqwer closed this Oct 5, 2026
@sergqwer

sergqwer commented Oct 6, 2026

Copy link
Copy Markdown
Author

Reopened as #1049, the same branch and commit. GitHub closed this one when my fork was made private by mistake, which took it out of the fork network.

@Niko1221

Niko1221 commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Merged for 0.1.40: the fused SwiGLU q8_1 quantizers now keep the block's scale and sum finite too, finite blocks bit for bit. The parity test covers the third quantizer. Thank you.

MistVVK added a commit to MistVVK/XeStrata that referenced this pull request Oct 7, 2026
q8_1 の量子化(launch_quantize_q8_1、エキスパートの SwiGLU と一体の量子化、
native_quantize_q8_1)は、32 個の活性値の和を fp16 で持つ。65504 を超えると
inf になり、amax が 8.3M を超えると尺度も inf になって、内積で inf * 0 = NaN、
残差に NaN が入ると同じトークンを出し続ける(upstream Niko1221#606)。upstream の
19de7f4 と未マージの Niko1221#838(融合した SwiGLU の量子化)にならい、尺度と和を
fp16 の最大の有限値で抑え、値を int8 の範囲に収める。有限だったブロックは
ビット単位で同じ。

B70 の coder-iq1_m のロジットは変更前とビット一致。作業用のプローブで、
和が 96,000・-69,984、amax が 2e7 のブロックが有限になることを確かめた。
eddoursul pushed a commit to eddoursul/StrataFast that referenced this pull request Oct 12, 2026
…Niko1221#606, 19de7f4 + PR Niko1221#838) at this fork's five sites

A q8_1 block stores d = amax / 127 and the sum of its 32 values as fp16: past 65504 they round to inf and the dot
products read inf * 0 = NaN, after which the model answers one token forever (upstream saw 36,689 "!" tokens;
ggml-org/llama.cpp#23606 is the same defect). include/strata/kernels/q8_1_finite.hpp is upstream's helper. Here the
quantizers are q8_1_store and the fused gate/up + SwiGLU entry loop (iq_kernels.cu), native_quantize_q8_1 and its
interleaved copy (native_mmvq.cu), and the router kernel's q8_1 rows (native_router.cu, its own rounding kept).
Every block that was finite before is stored bit for bit as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DarthCY-K pushed a commit to DarthCY-K/Strata that referenced this pull request Oct 20, 2026
…q8_1 clamp completed (Niko1221#838) - README, docs/NVFP4.md and the bundle version

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants