Skip to content

qwen35: dense BF16 loading and native prompt logprobs - #2020

Open
akol1 wants to merge 33 commits into
ashhart:mainfrom
akol1:codex/qwen35-bf16-after-gdn
Open

akol1 wants to merge 33 commits into
ashhart:mainfrom
akol1:codex/qwen35-bf16-after-gdn

Conversation

@akol1

@akol1 akol1 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

Adds an experimental dense BF16 Qwen3.5 format and native nonstreamed /v1/completions prompt_logprobs, using the existing CUDA lane scheduler. Stored FP32 GDN scales stay FP32; the score head uses BF16 inputs, FP32 sums/output and full-vocabulary normalization. Existing formats retain their generation paths and scoring admission.

Checks on this head

Head: 8f1202644cfadf12c70bfcdca42e28051b69d10c.

  • Zig format: passed. No GPU: all six jobs passed, including Linux unit/contract/golden/security/fuzz checks, Windows, macOS tools, release paths and both benchmark-client platforms.
  • Full unprivileged Linux command on the qualified source: zig build test test-kernel-contract test-golden fuzz-cortheon -j8 --summary all, exit 0; 570/570 steps, 3872/3897 executed tests passed, 25 skipped, other results cached. Plain build 30/30 and native/capture build 11/11 passed.
  • The former 1729-line reference entry point is split into modules: entry 266 lines, compare 375, forward 396, inputs 380, fixtures 281; one-line comments/docstrings. Final-head Linux CI's lean gate passed. Same lean checker against pinned main: 425 baseline / 425 candidate / zero new findings. Inherited findings remain reported.
  • Parent follow-up host contract: 22/22 steps, 168/168 executed passed, remaining targets cached; both new regression cases present.
  • Reference clients: 11 precision/verdict +7 served-comparison tests passed in the Linux reference environment. With optional reference dependencies absent, the precision/verdict suite reports 8 passed, 3 skipped; the same three precision tests pass with dependencies installed. Cache-evidence tests 6/6 passed. The forward implementation is unchanged by the dependency guard.
  • Canonical NVFP4 load cleanup: all 25 affected kernel .text sections are byte-identical across the five compiled SMs.

Receipt

Summary and reproduction, compact machine-readable summary, immutable assets and checksums. Full per-request/capture results, exact public arrays, failed/superseded attempts and complete logs are outside the source tree at https://github.com/akol1/TensorFold/tree/164be6e57dae9124893e27d8d1ac8a1be7d03f1c.

One RTX PRO 6000 Blackwell Max-Q workstation GPU, sm_120, rank 1, 96 GB class/300 W; Linux x86_64, driver 615.78.08, Zig 0.17.0, NVCC 13.0.88, native 1.2.2. Host CPU: AMD Ryzen 9 9950X3D, 16 cores/32 logical CPUs. Physical RAM: 128 GB class. Serving quota: four CPUs/32 GiB, HTTP loopback, context 8192/C4/cache0 unless stated otherwise. These quotas do not prove fit on a physical 32 GiB machine. One model process holds the existing GPU lock at a time.

Public Qwen/Qwen3.5-27B, revision fc05daec18b0a78c049392ed2e771dde82bdf654; all 11 measured shard hashes/sizes match pinned public LFS bytes and were reverified after serving. No weights or drafter are distributed; new-weight licence n/a. Native binary SHA-256: fa2f415a1b7a6f47a62ee078e7f6de86f3f677d2bf74ffa5c2d273e1ce713a64.

  • API: 32/32 passed, including the 4097-ID seam, drafted/plain reply hashes, repeat/concurrent score bytes and refusal recovery.
  • Same-weight FP64: passed, six prompt rows, 12 decode rows and 24 projection captures. Worst prompt/decode head errors 2.455665e-6/2.588786e-6, logprob errors 5.418979e-6/6.144033e-6, zero argmax differences. Bounds and worst row/token identities are retained. This checks the head on identical native BF16 rows, not a whole-model FP64 forward.
  • Direct served-versus-Transformers comparison: complete, strict distances failed. All 4511 scored positions use both BF16/promoted-FP32 arms; exact positions/IDs and zero reused tokens are verified. The loader restores and byte-verifies all 96 stored FP32 norm/A_log parameters. 1719/1911 positions fall outside the FP32/BF16-reference directions; worst native distances 5.546444/5.767185. No broader hidden-state bound replaces them. The issue gate explicitly permits this comparison to fail; it does not establish equivalence. The earlier captured-row acceptance statement is superseded by the retained failed verdict and this direct HTTP evidence.
  • Lifecycle: full fresh/retained/edited/restarted reply hashes match; all seven observed-cancellation checks pass.
  • Existing formats: four alternating pinned-main/candidate processes per MLX4 and ModelOpt checkpoint; 20 full-token-hash matches each, and identical HTTP 400 scoring refusal in all four processes. Small rate changes remain descriptive (ModelOpt about -0.040% code/-0.065% chat), not a statistical noninferiority claim. ModelOpt is the pinned public Qwen3.8 export. Four EXL3 processes retain the same UnexpectedTensor refusal for F16 embeddings; no EXL3 inference is claimed.

The maintainer-requested simple per-length report uses every scored position, with no hidden-distance term or extra allowance:

Prompt IDs Scored rows Worst |served - FP32| Median |served - FP32| Same-length worst |BF16 - FP32| Worst within own BF16 distance
32 31 0.0415096283 0.004390716553 0.02388763428 failed
129 128 0.04362297058 3.433227539e-05 0.0426158905 failed
257 256 5.546443939 0.001540184021 5.224838257 failed
4097 4096 0.04362297058 1.907348633e-06 0.0426158905 failed

The simple length-level rule fails at all four lengths. Median uses statistics.median over all rows of that length. This covers the 415 smaller-fixture positions plus all 4096 scored positions of the 4097-ID seam. The full-precision derived report and reproduction script pin the published input member SHA-256. The stricter row-level counts above remain separate diagnostics.

Public BF16 workload Native SGLang 0.5.19
Code/chat median greedy decode, tokens/s 23.68 / 29.32 27.70 / 27.58
Code/chat median warm TTFT, seconds 0.352 / 0.767 0.076 / 0.079
Code/chat C4 greedy aggregate decode, tokens/s 8.9 / 9.0 109.6 / 109.5
Code/chat C4 whole-request throughput, tokens/s 8.910 / 8.973 108.572 / 108.313
Cold 2048-ID TTFT, seconds 49.515 0.447
Cold 8192-ID TTFT, seconds 199.777 1.901
Cold 32768-ID TTFT, seconds 801.786 9.211
Cold 65536-ID TTFT, seconds 1601.814 24.608

Short cells request 128 output tokens, three measured repetitions; warmups excluded. C1/C4 greedy and temperature-0.7 sampled cells are retained with exact IDs, seeds and request settings. All 60 native measured concurrency requests match solo/plain hashes. Six greedy cross-engine content/reasoning fingerprints match; SGLang full-token-ID equality is unverified. Decode excludes the first token; whole-request throughput includes prefill/makespan; SSE chunks are not GPU kernel timings. No production percentile SLO follows from three repetitions.

Cold rows each use a fresh server, cache0/C1, context N+32, exact archived IDs and eight reply tokens. TTFT starts after readiness; model load is separate, startup warmups precede readiness, and OS/compiler/kernel caches are preserved. SGLang's missing HTTP cache counter remains null and its generic qualifier remains false/exit 1; independent scheduler accounting shows exactly N new and zero cached tokens. Native short cold replies sometimes lack enough SSE chunks for decode rate; those rates stay null. All attempts are retained.

Memory is measured separately from timed requests. Native cache0/C4 process/device peaks are 5.984/54.025 GiB; retained-cache peaks 6.000/54.025 GiB, pinned sampled maximum 0.453 GiB. Through the actual native 64k request, process/device lifetime peaks are 5.992/55.302 GiB. Linux process high-water, sampled counters and cgroup charge have distinct scopes. SGLang per-process peaks are not a summed group peak; its short-run cgroup charge reached about 32 GiB. Unavailable device/pinned allocator peaks remain unmeasured.

Complete CUDA contract
SUMMARY 559 kernels: 559 pass gates 1-4, 0 fail, 6 known findings; 367 controls: 367 red as planted, 0 missed; 0 limit problems; gates 4023784 ms, limits 760889 ms
exit: 0

The six known NaN findings are identical to the previous declarations; no known entry was added. The full log preserves their actual failures and every planted control.

The five-SM compiled-resource audit exits 0: 1493 records, zero stale records and zero applicable launch failures, launch controls red. Compile records preserve later-compiler selection; launch geometry, precision and tolerances are unchanged. Registered FP32-scale RMS covers real 128-wide GDN shapes, nonfinite values, repeat/guard checks and a red wrong-dtype control. Its FP16 stress misses by 256x; BF16 output rounding can hide BF16 reduction error, as explicitly reported. Scoring reduction controls remain red.

The initial full-suite attempt stopped before numerical gates because independently compiled H3 held only sm_121. Explicit -Dsm=80,86,89,120,121 corrects that setup; the source and gates are unchanged. Exact byte searches compare all 141 file images: only H3 embedding coverage changes, and the served native binary stays identical. Failed attempt, corrected build, runner SHA-256 and full logs are retained separately.

Other physical chips/backends, multiple ranks, FP8 KV and optional grammar/tool paths remain unqualified. Vision, int8 prompt precision and learning are explicitly refused for this text format. GB10 execution remains with the maintainer as offered. Compilation for another SM proves resource coverage, not device execution.

Checklist

  • Title, description and receipt match the head and declared stack.
  • New format and score head use native lanes; drafted/plain, retained/fresh and concurrent/solo checks pass.
  • Precision retained; numerical bounds and all failing independent diagnostics disclosed.
  • Full scoped checks and exact-head hosted CI are linked; unrun coverage is explicit.
  • Changed source modules remain bounded and comments fit the contributor rules; inherited findings and zero new lean findings are reported.
  • Publication payload, archive metadata and outgoing history reviewed for private identifiers and secrets; public GitHub aliases/noreply credit retained, no AI attribution lines.
  • Full logs and per-request dumps moved to immutable checksum-pinned assets; source keeps summaries and reproduction inputs.
  • Performance qualification: BF16 prefill/concurrency remain limiting; performance remains unqualified. Existing-format small differences are descriptive.
  • Maintainer landing: parent-stack cleanup/rebase and the offered GB10 cells.

ashhart and others added 4 commits November 3, 2026 07:47
Reuse ashhart#1764's existing kernel, resource records and required symbol bindings for the Qwen dense/MoE and Nemotron ModelOpt port. Keep one six-entry numerical/replacement/control set. Cache the serving choice: TF_CUDA_PROMPT_BF16=0 restores the lane but leaves required symbols bound. The threshold is fixed at 1024 rows.

Host ABI and fixture-lifetime checks pass; fresh CUDA contract and checkpoint A/B receipts remain required on this rebased tree.

Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
Dory packs its unquantized projections in the shared BF16 lane layout and
runs prompt chunks through Linear. Opt it into ashhart#1764's existing tile at
the fixed 1024-row threshold; TF_CUDA_PROMPT_BF16=0 restores the lane.
The required symbols stay bound and decode stays on its existing path.

Exercise the actual family projection at the CUDA ABI without a device.
Fresh greedy and seeded token equality and a 2K prompt timing on a GB10
remain required. Refs ashhart#1762, ashhart#1764.
Adapt ashhart#1764's staged chain-warp gated norm to Qwen dense and MoE.
Retain the old recurrence and post kernels and each BF16 boundary;
TF_CUDA_GDN_CHAIN_NORM=0 restores their separate launches.

Register byte replacements for rows, state, sums and chunk seams with
source controls. Host ABI checks pass; device and compiler gates are
pending. Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
Adapt ashhart#1764's expert-first grid to Qwen MoE's 16-row router.
Retain each original FP32 FMA chain and the row-first kernel;
TF_CUDA_MOE_EXPERT_FIRST=0 restores its symbol and launch grid.

Add FP64 and byte-replacement contracts, padded/live-row cases and a
source row-coupling control. Complete shared contract image routing,
keep callback tables static, and compile GDN controls with the production
chain so their compiler flags match. Device qualification is pending.
Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
@akol1

akol1 commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Qualification update on 91197649ca24d2234f9cde2ff8e6e68b7a09b730: the public API/FP64 reports and exact fixtures are now committed under docs/receipts/qwen35-bf16-scoring/. The complete strict CUDA contract is still running; this remains a draft.

Hosted format passed. The No GPU run was cancelled before completion, as was the previous head's run. There has been no subsequent push to supersede this head. The macOS zig build dev-tools step completed successfully, but that does not establish a complete hosted pass. The unprivileged Linux host suite passed locally, with the counts retained in the PR description.

Could a maintainer confirm whether the repeated cancellation is intentional and how to obtain the remaining hosted checks? I have not changed workflow policy or repeatedly retried cancelled runs. The outstanding checks remain explicitly unchecked.

@akol1

akol1 commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

The complete strict CUDA run is now retained in the receipt, including its full text output and binary identity:

SUMMARY 550 kernels: 550 pass gates 1-4, 0 fail, 6 known findings; 365 controls: 365 red as planted, 0 missed; 342 limit problems; gates 4013421 ms, limits 726300 ms
exit: 1

The numerical gates and every planted control passed their intended checks; six existing NaN findings reproduce. All four new function records pass live sm_120 checks, and all 20 new function/SM records are current in the five-SM asset audit.

The remaining failure is 188 registry problems plus 154 live record/device mismatches. The separate parent/candidate five-SM audits both exit 1 with 637 problems and identical diagnostic multisets; the comparison retains those diagnostics. The parent's full/live-only run was not run, so this is not presented as a matching parent live SUMMARY or a clean qualification.

Could the maintainer advise the appropriate catalog-resolution scope for these existing records? The PR stays draft. Native serving measurements have resumed, with performance, lifecycle, cold-prefill and existing-format receipts still pending.

@ashhart

ashhart commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Thank you, @akol1. This is careful work: the dense BF16 path keeps every existing checkpoint on main's code, the
prompt scores have their own FP32 head with planted controls, and your callback-lifetime fix in commit 8 found a real
bug in the base we stacked under you. We'll take that fix into #1762 with credit. Three requests before this can land.
First, please drop the four base commits once #1762 is in, and keep only the summary receipts here, moving the
per-request dumps and the full contract log to a linked asset with their checksums. Second, the FP64 check covers the
score head on the engine's own rows; could you add a comparison of the served prompt logprobs against a transformers
forward of the pinned checkpoint, bounded by transformers' own BF16 distance from FP32? Third, a small wording change
in the recipe's line about the GPU lock, and a fuller message on the main commit. We'll run the GB10 cells on our side.

@ashhart

ashhart commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Your callback fix (d8f5efbc93) is now on #2008 under your name (789846adb), so it lands with the base. You can drop it from this branch when you rebase.

akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
Load the dense Qwen3.5-27B checkpoint from its stored BF16 safetensors and
serve per-token prompt logprobs from the rows the prompt path scores. Dense
attention and MoE projections keep the checkpoint's BF16 weights and
activations; FP32 sums and the stored GDN scales are unchanged, and no
tolerance moves.

Score the served rows locally: `prompt_logprobs` follows `/v1/completions`,
`top` accepts 0/1/20, the first entry stays null, and an unknown `top` or an
input id at the vocabulary sentinel is a 400. The head accumulates in FP32 and
takes its logsumexp over the full vocabulary.

Add an independent FP32 head over the same captured BF16 normalized rows, with
its own build, a FP64 dot/logsumexp tool and planted controls, so a score can
be checked without trusting the production head. Register the new
function/SM and record identities with byte replacements; existing
declarations and tolerances stay as they are.

The CUDA contract still fails 342 launch limits, so this is qualification
input, not a passed contract. Refs ashhart#1762, ashhart#2020.
akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
…erence

The receipt tree carried 3.26 MB of per-request dumps and the complete CUDA
contract log beside the summaries. Remove the per-request dumps, the two
per-request concurrency bodies and the cold replay bodies; asset.json pins the
sha256 and byte count of every removed file, and of the transformers payload and
run log kept out of the tree with them, so the tracked receipts stay auditable
against what was removed. The removed files themselves stay with the author and
are not published.

Add tools/zig/qwen35_transformers_reference.py, which runs the pinned checkpoint
on CPU in two arms, stored BF16 and every decoder layer's stored parameters and
buffers promoted to FP32, and transformers-comparison.json, which compares the
served prompt scores against that forward and adds the tables to the receipt.
The transformers arm's own BF16-to-FP32 distance bounds the comparison: 18/18
rows stay inside their bound, the worst tracked native-to-transformers difference
is 0.830 on one prompt row at position 255, the other 17 rows are at or under
0.018, and 408/415 argmax rows agree. The BF16 arm's hidden states are bitwise
equal to a plain library forward, and extending a prompt by the served
continuation tokens leaves the prompt rows bitwise unchanged.

Also name the existing GPU lock and admission guard, with one model process per
test machine, in the recipe's serving line, and re-pin the commit ids the topic
rewrite changed in the required checksum records.

Refs ashhart#1762, ashhart#2020.
@akol1
akol1 force-pushed the codex/qwen35-bf16-after-gdn branch from b651e8b to adfe474 Compare November 4, 2026 02:42
akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
Load the dense Qwen3.5-27B checkpoint from its stored BF16 safetensors and
serve per-token prompt logprobs from the rows the prompt path scores. Dense
attention and MoE projections keep the checkpoint's BF16 weights and
activations; FP32 sums and the stored GDN scales are unchanged, and no
tolerance moves.

Score the served rows locally: `prompt_logprobs` follows `/v1/completions`,
`top` accepts 0/1/20, the first entry stays null, and an unknown `top` or an
input id at the vocabulary sentinel is a 400. The head accumulates in FP32 and
takes its logsumexp over the full vocabulary.

Add an independent FP32 head over the same captured BF16 normalized rows, with
its own build, a FP64 dot/logsumexp tool and planted controls, so a score can
be checked without trusting the production head. Register the new
function/SM and record identities with byte replacements; existing
declarations and tolerances stay as they are.

The CUDA contract still fails 342 launch limits, so this is qualification
input, not a passed contract. Refs ashhart#1762, ashhart#2020.
akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
…erence

The receipt tree carried 3.26 MB of per-request dumps and the complete CUDA
contract log beside the summaries. Remove the per-request dumps, the two
per-request concurrency bodies and the cold replay bodies; asset.json pins the
sha256 and byte count of every removed file, and of the transformers payload and
run log kept out of the tree with them, so the tracked receipts stay auditable
against what was removed. The removed files themselves stay with the author and
are not published.

Add tools/zig/qwen35_transformers_reference.py, which runs the pinned checkpoint
on CPU in two arms, stored BF16 and every decoder layer's stored parameters and
buffers promoted to FP32, and transformers-comparison.json, which compares the
served prompt scores against that forward and adds the tables to the receipt.
The transformers arm's own BF16-to-FP32 distance bounds the comparison: 18/18
rows stay inside their bound, the worst tracked native-to-transformers difference
is 0.830 on one prompt row at position 255, the other 17 rows are at or under
0.018, and 408/415 argmax rows agree. The BF16 arm's hidden states are bitwise
equal to a plain library forward, and extending a prompt by the served
continuation tokens leaves the prompt rows bitwise unchanged.

Also name the existing GPU lock and admission guard, with one model process per
test machine, in the recipe's serving line, and re-pin the commit ids the topic
rewrite changed in the required checksum records.

Refs ashhart#1762, ashhart#2020.
@akol1
akol1 force-pushed the codex/qwen35-bf16-after-gdn branch from adfe474 to d397c8c Compare November 4, 2026 02:45
ashhart and others added 13 commits November 3, 2026 18:47
Reuse ashhart#1764's existing kernel, resource records and required symbol bindings for the Qwen dense/MoE and Nemotron ModelOpt port. Keep one six-entry numerical/replacement/control set. Cache the serving choice: TF_CUDA_PROMPT_BF16=0 restores the lane but leaves required symbols bound. The threshold is fixed at 1024 rows.

Host ABI and fixture-lifetime checks pass; fresh CUDA contract and checkpoint A/B receipts remain required on this rebased tree.

Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
Dory packs its unquantized projections in the shared BF16 lane layout and
runs prompt chunks through Linear. Opt it into ashhart#1764's existing tile at
the fixed 1024-row threshold; TF_CUDA_PROMPT_BF16=0 restores the lane.
The required symbols stay bound and decode stays on its existing path.

Exercise the actual family projection at the CUDA ABI without a device.
Fresh greedy and seeded token equality and a 2K prompt timing on a GB10
remain required. Refs ashhart#1762, ashhart#1764.
Adapt ashhart#1764's staged chain-warp gated norm to Qwen dense and MoE.
Retain the old recurrence and post kernels and each BF16 boundary;
TF_CUDA_GDN_CHAIN_NORM=0 restores their separate launches.

Register byte replacements for rows, state, sums and chunk seams with
source controls. Host ABI checks pass; device and compiler gates are
pending. Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
Adapt ashhart#1764's expert-first grid to Qwen MoE's 16-row router.
Retain each original FP32 FMA chain and the row-first kernel;
TF_CUDA_MOE_EXPERT_FIRST=0 restores its symbol and launch grid.

Add FP64 and byte-replacement contracts, padded/live-row cases and a
source row-coupling control. Complete shared contract image routing,
keep callback tables static, and compile GDN controls with the production
chain so their compiler flags match. Device qualification is pending.
Refs ashhart#1762, ashhart#1764.

Co-authored-by: Armin <2369138+Arminova@users.noreply.github.com>
Load the dense Qwen3.5-27B checkpoint from its stored BF16 safetensors and
serve per-token prompt logprobs from the rows the prompt path scores. Dense
attention and MoE projections keep the checkpoint's BF16 weights and
activations; FP32 sums and the stored GDN scales are unchanged, and no
tolerance moves.

Score the served rows locally: `prompt_logprobs` follows `/v1/completions`,
`top` accepts 0/1/20, the first entry stays null, and an unknown `top` or an
input id at the vocabulary sentinel is a 400. The head accumulates in FP32 and
takes its logsumexp over the full vocabulary.

Add an independent FP32 head over the same captured BF16 normalized rows, with
its own build, a FP64 dot/logsumexp tool and planted controls, so a score can
be checked without trusting the production head. Register the new
function/SM and record identities with byte replacements; existing
declarations and tolerances stay as they are.

The CUDA contract still fails 342 launch limits, so this is qualification
input, not a passed contract. Refs ashhart#1762, ashhart#2020.
…erence

The receipt tree carried 3.26 MB of per-request dumps and the complete CUDA
contract log beside the summaries. Remove the per-request dumps, the two
per-request concurrency bodies and the cold replay bodies; asset.json pins the
sha256 and byte count of every removed file, and of the transformers payload and
run log kept out of the tree with them, so the tracked receipts stay auditable
against what was removed. The removed files themselves stay with the author and
are not published.

Add tools/zig/qwen35_transformers_reference.py, which runs the pinned checkpoint
on CPU in two arms, stored BF16 and every decoder layer's stored parameters and
buffers promoted to FP32, and transformers-comparison.json, which compares the
served prompt scores against that forward and adds the tables to the receipt.
The transformers arm's own BF16-to-FP32 distance bounds the comparison: 18/18
rows stay inside their bound, the worst tracked native-to-transformers difference
is 0.830 on one prompt row at position 255, the other 17 rows are at or under
0.018, and 408/415 argmax rows agree. The BF16 arm's hidden states are bitwise
equal to a plain library forward, and extending a prompt by the served
continuation tokens leaves the prompt rows bitwise unchanged.

Also name the existing GPU lock and admission guard, with one model process per
test machine, in the recipe's serving line, and re-pin the commit ids the topic
rewrite changed in the required checksum records.

Refs ashhart#1762, ashhart#2020.
@akol1
akol1 force-pushed the codex/qwen35-bf16-after-gdn branch from d397c8c to 54f9459 Compare November 4, 2026 02:57
akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
Load the dense Qwen3.5-27B checkpoint from its stored BF16 safetensors and
serve per-token prompt logprobs from the rows the prompt path scores. Dense
attention and MoE projections keep the checkpoint's BF16 weights and
activations; FP32 sums and the stored GDN scales are unchanged, and no
tolerance moves.

Score the served rows locally: `prompt_logprobs` follows `/v1/completions`,
`top` accepts 0/1/20, the first entry stays null, and an unknown `top` or an
input id at the vocabulary sentinel is a 400. The head accumulates in FP32 and
takes its logsumexp over the full vocabulary.

Add an independent FP32 head over the same captured BF16 normalized rows, with
its own build, a FP64 dot/logsumexp tool and planted controls, so a score can
be checked without trusting the production head. Register the new
function/SM and record identities with byte replacements; existing
declarations and tolerances stay as they are.

The CUDA contract still fails 342 launch limits, so this is qualification
input, not a passed contract. Refs ashhart#1762, ashhart#2020.
akol1 added a commit to akol1/TensorFold that referenced this pull request Nov 4, 2026
…erence

The receipt tree carried 3.26 MB of per-request dumps and the complete CUDA
contract log beside the summaries. Remove the per-request dumps, the two
per-request concurrency bodies and the cold replay bodies; asset.json pins the
sha256 and byte count of every removed file, and of the transformers payload and
run log kept out of the tree with them, so the tracked receipts stay auditable
against what was removed. The removed files themselves stay with the author and
are not published.

Add tools/zig/qwen35_transformers_reference.py, which runs the pinned checkpoint
on CPU in two arms, stored BF16 and every decoder layer's stored parameters and
buffers promoted to FP32, and transformers-comparison.json, which compares the
served prompt scores against that forward and adds the tables to the receipt.
The transformers arm's own BF16-to-FP32 distance bounds the comparison: 18/18
rows stay inside their bound, the worst tracked native-to-transformers difference
is 0.830 on one prompt row at position 255, the other 17 rows are at or under
0.018, and 408/415 argmax rows agree. The BF16 arm's hidden states are bitwise
equal to a plain library forward, and extending a prompt by the served
continuation tokens leaves the prompt rows bitwise unchanged.

Also name the existing GPU lock and admission guard, with one model process per
test machine, in the recipe's serving line, and re-pin the commit ids the topic
rewrite changed in the required checksum records.

Refs ashhart#1762, ashhart#2020.
@akol1

akol1 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Rebased and reworked — head is now 54f945941 (13 commits: the four base commits still carried under this branch while #1762/#2008 are open, plus our nine). Our callback fix is gone from here: it landed on #2008 as 789846adb, so it travels with the base, as you said. Every receipt that cited a build commit now cites the rebased id (manifest.source_commit, inference_build_commit, stack_parent, host-and-ci, limits-comparison, exl3-admission), and the tree is the same content as before the rebase.

Receipts: the per-request dumps and the full contract log are out of the tree. README.md keeps summaries only; asset.json pins the sha256 and byte count of each removed file, the dumps tarball's 21 members, and the exact command lines. I have not published them — no release, no upload — because those captures came from a private machine and the author asked to keep them private. The checksums are in the tree so a later publication, if authorized, is verifiable; nothing else about them is claimed.

Transformers comparison (transformers-comparison.json, tracked; script tools/zig/qwen35_transformers_reference.py, pinned revision fc05daec18b0a78c049392ed2e771dde82bdf654): a CPU-only transformers forward of the pinned checkpoint, attn_implementation: eager, compared against the served prompt logprobs. The sweep runs the forward twice, BF16 and FP32, so the BF16 arm's own distance from FP32 is measured rather than assumed. On fixture 3 that distance is up to |Δlogprob| 4.035 (pos 216; mean 0.061, 408/415 argmax and 388/415 rank agreement); fixtures 1 and 2 stay ≤0.0577. Served scores sit inside that envelope on all 18 captured rows (15 metas: prompt and decode, plus repeats): the largest |served − BF16 arm| is 0.830 on one prompt row (fixture 3, pos 255) and the other 17 rows are ≤0.0179. So the scores match the pinned checkpoint's own forward within the distance that forward's BF16 arithmetic shows from FP32, and the comparison records the bound per row, not a single global tolerance.

Wording: the recipe line now reads "Use the existing GPU lock and admission guard, with one model process per test machine", matching docs/recipes/SKILL.md. The main commit message now spells out the FP32 head arithmetic, the independent FP32 head and FP64 tool, the identity byte-replacements, and the 342 known launch-limit findings as qualification input rather than a passed contract.

The four base commits stay only until the base lands; once #1762/#2008 are in I drop them and keep the nine. CI is queued on the new head; I'll report anything that goes red. Refs #1762.

akol1 added 2 commits November 3, 2026 20:48
…dence

Keep the original measured source and CI identities after the history rewrite. Link the reviewed evidence assets outside the source branch with immutable hashes.

Split the finite Transformers reference into bounded modules without changing its numerical functions. Return failure for the measured BF16-distance counterexamples instead of treating a broader hidden-distance diagnostic as acceptance. Scrub identifying runner metadata in future JSON exports and retain seven verdict/privacy regressions.
@akol1

akol1 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up on 07034aa264af49baa0e21d3953f20f4590809a5b:

  • The three evidence files are now linked immutably with hashes outside the source branch. All 21 archive members and both additional payloads were reviewed for identifying metadata/secrets; their published bytes match the recorded SHA-256s.
  • The earlier reference status overstated acceptance. The broader hidden-distance diagnostic passes, but the measured BF16-distance comparison does not: three captured rows fail against the FP32 reference (fixture 3 positions 255/256/260); one fails against the alternate BF16-reference envelope (position 256). The existing head-rounding allowance is retained. These are captured native rows, not yet a direct served HTTP prompt-score comparison. The 4097-token fixture has no FP32 arm. Counterexamples stay failed; no hidden-distance term is used to waive them.
  • Split the 1729-line finite reference into bounded modules, preserving all 32 non-CLI executable ASTs. CPU head bytes and FP64 profiles match. Seven verdict/privacy tests pass on Python 3.11/3.14 and Linux 3.12; lean 473→430, zero new. Forward qualification now exits nonzero on the failed envelope; future JSON exports scrub runner identifiers/paths.
  • Restored original tested commit/binary/CI identities in historical receipts. Rebased IDs are ancestry mappings, not new executions. The PR body now matches this head and its outstanding gates.

#2008 remains open, so the four inherited base commits stay pending its landing; this follow-up does not touch native conflict paths or force-push history. Recipe lock wording and the fuller main commit message are retained. Native fidelity, catalog/performance acceptance and post-base qualification remain outstanding; GB10 cells remain with the maintainer as offered.

Before changing native arithmetic, please confirm whether the intended acceptance is error relative to the Transformers FP32 arm bounded by its BF16 error, or distance directly to its BF16 arm. Both failing directions are reported explicitly. The previous broadened bound is not presented as satisfying either request.

akol1 and others added 4 commits November 3, 2026 21:01
Collect actual HTTP selected-token scores with exact row/token coverage and cache-off checks. Report both measured BF16-distance directions without replacing the agreed same-weight FP64 gate with an invented cross-engine threshold. Include the long-prompt FP32 arm and reject incomplete reference evidence.
Fill the four five-SM launch receipts from nvcc 13.0.88. Keep later
compiler records pending and test the real registry lookups and limits.
@akol1

akol1 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Readiness work is proceeding on the reconciled candidate 2475f27c (native build source 7308aa0c). Ordinary merges include current main 785da95d and the declared #2008 dependency 789846adb, including the credited callback fix. The image-list conflict retains both gdn_prefill and main's nvfp4_experts32. No history is force-pushed; inherited dependency history remains until the parent lands.

The final release-compiler build, complete host checks and full pinned Transformers reference (including the previously missing 4097-token FP32 arm) are running. A finite client now collects actual HTTP prompt scores against both reference arms with exact per-position/token coverage and zero-cache checks.

Gate scope is the original agreement: same-weight FP64 prompt/decode worst-row/token evidence, the reduction/control, server integration and unchanged existing formats. As that agreement states, the other-engine tolerance need not pass. We will keep both measured distance directions visible and will not use the broader hidden-distance diagnostic as a substitute. The earlier blanket “fidelity fixes required” status overstated the agreed gate; the missing direct served comparison and 4097-token reference coverage are being completed.

ATC overlap coverage is incomplete (pullFilesLimit). Two concrete remaining overlaps are #2086 (qwen3_5/cuda_geometry.zig, layer-pattern parsing beside the new BF16 format field) and #2011 (qwen3_5/cuda_prompt.zig, paging beside the BF16-only unfused FP32-scale post). Their landing order needs coordination: keep each PR's parsing/paging behavior and this format's FP32 GDN-scale guard. Existing shared contract-record overlaps remain disclosed. This does not claim conflict-free integration with every open branch or take over either PR's work.

akol1 added 6 commits November 3, 2026 21:36
Restore the 96 FP32 GDN normalization and decay tensors that Transformers auto-dtype downcasts, and verify their original bytes before either precision arm. Keep repeated runs incomplete until they finish and exclude prose and request identifiers from HTTP evidence.

Repair two current-main verification prerequisites: reuse the unchanged canonical loads in the block-32 experts rather than adding primitive copies, and let the compiled-image limits command inspect files without initializing CUDA. No native Qwen arithmetic or precision is changed.
@akol1
akol1 force-pushed the codex/qwen35-bf16-after-gdn branch from b168b36 to 55dbec4 Compare November 4, 2026 07:12
akol1 added 2 commits November 4, 2026 00:29
…ship

The four NVCC 13.0 resource tuples match the independently qualified cubins. Resolve their formatting overlap with the upstream records and import its two registry regressions through the compiler-set test module so registry.zig stays within the source limit. Inference code and contract values are unchanged; actual GPU execution provenance remains b168b36.
Keep the three stored-FP32 parameter checks active when torch and safetensors are installed. A host without those reference-only dependencies now reports three explicit skips instead of failing test discovery; missing transitive dependencies still fail.
@ashhart

ashhart commented Nov 4, 2026

Copy link
Copy Markdown
Owner

Thanks @akol1. The rebase is clean on our side: outside the receipts, the code is line for line what we reviewed, so every existing format still takes main's path. Your MLX 4-bit and NVFP4 runs, 20 of 20 token hashes equal, back that. The receipt tree is down from 52,508 lines to 9,250. We checked the 21 kept-out files' hashes in asset.json against the copies we reviewed last round, and all 21 match. The recipe wording matches our own contributor guide, which is fine.

Two things are left:

  1. The transformers comparison. Running both a BF16 and an FP32 forward was the right way to measure the
    distance, and judged per length the served scores sit inside it (worst 0.0046 at 32 tokens, 0.0001 at 129 and
    2.38 at 257). But it compares only 18 captured rows, six of them prompt rows, and nothing at 4,097 tokens, where
    the FP32 arm was skipped. That's the fixture that crosses the chunk seam, so it matters most. The served
    prompt_logprobs in your API responses already hold every row. Could you compare all of them against both arms
    (415 rows across 32, 129 and 257, plus the 4,097 fixture) and report the worst and median |served − FP32| per
    length, next to that length's own BF16-vs-FP32 worst? If the FP32 forward at 4,097 is too heavy on CPU, the last
    few hundred rows of that fixture would do. We'd rather use that simple per-length rule than the bound with the
    hidden-distance terms, which grows with exactly the drift we want to see.
  2. The lean check. On our main, tools/zig/qwen35_transformers_reference.py adds 47 problems: it's 1,729 lines,
    over the 600-line limit, with 37 multi-line comments and 9 multi-line docstrings. Please split it into modules of
    600 lines or fewer, with one-line comments.

When this lands, we'll squash the receipt commits, so the full contract text and dumps added and then removed in this series don't stay in history. The four base commits come out once #1762 and #2008 are in, as you said. The 342-problem limit catalog is ours to clear, and we'll run the GB10 cells on our side.

Keep source-tree summaries and reproduction inputs, with immutable links and member checksums for complete serving, reference and CUDA evidence. Retain exact producer/binary identities, the failed strict cross-engine comparisons, historical attempts and performance limits. Record the full 559-kernel/367-control pass and zero launch-limit problems on sm_120, with six unchanged known findings; other hardware and production/performance qualification remain outside this experimental scope.
@akol1
akol1 marked this pull request as ready for review November 4, 2026 11:09
@akol1

akol1 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Completed on 8f1202644cfadf12c70bfcdca42e28051b69d10c, ready for review as an experimental functional text/scoring format.

  • The complete CUDA command exits 0: 559 kernels pass, 367/367 controls red, zero gate/launch-limit failures, with the same six declared known findings. The final-head format and all six No GPU jobs pass. Device executions retain source b168b36d; equivalent parent receipt tables, host-only tests, the optional reference dependency guard and condensed docs are identified separately.
  • Per-request/capture results and complete logs are now in immutable evidence assets, with archive and member checksums. The 387-file current payload and all 53 original source-tree receipts were reviewed; the three earlier assets remain unchanged. The packet and the per-length supplement downloads match their recorded hashes. The actual BF16 shard hashes/sizes match the pinned public Qwen LFS manifest before and after serving. Submitted text/metadata/history contain no private infrastructure identifiers or credentials; approved public aliases/noreply credit remain.
  • The requested actual HTTP prompt-logprob comparison is complete at all 4511 scored positions, including the 4097-ID seam, in both Transformers BF16/promoted-FP32 arms. All 96 stored FP32 parameters are restored and byte-verified. Strict measured-distance checks fail: 1719 positions in the FP32-reference direction and 1911 in the BF16-reference direction. Those counterexamples remain in the asset; no wider hidden-state bound substitutes for them. This supersedes the earlier captured-row acceptance statement. The agreed issue gate separates this diagnostic from the passing same-weight FP64 checks. Model equivalence and performance qualification remain unclaimed; slow BF16 prefill/concurrency and all sampled/negative cells are disclosed.
  • The former 1729-line reference entry point is now 266 lines; its compare/forward/inputs/fixture modules are 375/396/380/281 lines, with one-line comments/docstrings. Final-head Linux CI's lean check passes, and the same-checker comparison is 425 baseline/425 candidate/zero new findings. The recipe's GPU-lock wording matches the contributor skill, and the fuller main-commit message is preserved. CUDA: #1764's BF16 prompt tile for Qwen ModelOpt, Nemotron and Dory, plus two exact Qwen prompt kernels (#1762) #2008 is still open at 30e9b872; the credited callback fix travels with that parent. Parent-stack cleanup/rebase remains conditional on landing, and the offered GB10 cells remain with the maintainer. The latest ATC scan is incomplete (pullFilesUnavailable, timeLimit) and reports conflicts with qwen CUDA: streams on pages by default (256 positions, the engine's own too), with the paged prompt and decode at the window path's speed #2011 and glm cuda: EXL3 mcg experts at any whole-bit width, mixed by projection #2094; the description identifies the FP32-scale guard, registry sets and per-compiler records to preserve at integration.

The source receipt keeps summaries and reproduction inputs. Unrun physical chips/backends, multiple ranks and optional paths remain explicit.

The maintainer-requested simple per-length report uses every scored position, with no hidden-distance term or extra allowance:

Prompt IDs Scored rows Worst |served - FP32| Median |served - FP32| Same-length worst |BF16 - FP32| Worst within own BF16 distance
32 31 0.0415096283 0.004390716553 0.02388763428 failed
129 128 0.04362297058 3.433227539e-05 0.0426158905 failed
257 256 5.546443939 0.001540184021 5.224838257 failed
4097 4096 0.04362297058 1.907348633e-06 0.0426158905 failed

The simple length-level rule fails at all four lengths. Median uses statistics.median over all rows of that length. This covers the 415 smaller-fixture positions plus all 4096 scored positions of the 4097-ID seam. The full-precision derived report and reproduction script pin the published input member SHA-256. The stricter row-level counts above remain separate diagnostics.

@ashhart

ashhart commented Nov 4, 2026

Copy link
Copy Markdown
Owner

Thanks @akol1, for doing the full comparison and for reporting it straight: all 4,511 positions, the 4,097 seam included, both arms, no extra allowance. The reference script split is clean too, and lean is unchanged on our main.

The per-length rule fails at all four lengths. Most clearly at 32 tokens, where the worst served row is 0.0415 from FP32 against the BF16 arm's own 0.0239. At 129 and 4,097 the worst rows sit just above (0.0436 against 0.0426). Your FP64 check shows the head is exact on the rows it's given, so the drift comes from earlier in the BF16 body. Could you run a layer-by-layer comparison on the 32-token fixture against transformers FP32, to find the layer where the served rows first leave the BF16 arm's distance? That tells us whether it's one accumulation we can fix or the format's floor. We'll come back on whether it lands as an experimental format with those numbers stated.

One more thing: main's layer-pattern change now conflicts with the BF16 branch in cuda_geometry.zig's parse, so it needs a rebase. The GB10 cells are still ours.

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