Skip to content

fix(CUDA): fmt=8/fmt=6 scale-byte accounting — rebase of #1100 by @monotophic - #1114

Merged
JustVugg merged 3 commits into
devfrom
fix/cuda-fmt8-rebased
Aug 19, 2026
Merged

fix(CUDA): fmt=8/fmt=6 scale-byte accounting — rebase of #1100 by @monotophic#1114
JustVugg merged 3 commits into
devfrom
fix/cuda-fmt8-rebased

Conversation

@JustVugg

Copy link
Copy Markdown
Owner

@monotophic's #1100, rebased onto dev by the maintainers — commits and authorship theirs. It went conflicting the moment #1098 (their own __syncthreads() fix) merged, since both add a test to the cuda-test target.

Conflict resolution: pure union, both mechanical — the cuda-test dependency line now lists both test_absorb_determinism.cu (from #1098) and test_fp8_cuda.cu (this PR), and both recipe bodies are kept in their intended order (fp8 before MXFP4, absorb-determinism last, per each test's own comment about schedule sensitivity).

Fix and its regression test unchanged. Targeting v1.7.0. Supersedes #1100 on merge.

monotophic and others added 3 commits August 19, 2026 17:08
coli_cuda_tensor_free recomputed freed scale bytes as O*ng*sizeof(float),
but coli_cuda_tensor_upload charges tensor->scale_count*sizeof(float) --
and for fmt=8, scale_count is ((O+127)/128)*ng block-scales, not O*ng.
Free therefore overcounted, the tensor_bytes >= bytes guard silently
declined the subtraction, and coli_cuda_stats' diagnostic counter stuck
non-zero forever after freeing any tracked fmt=8 tensor. Diagnostic-only:
cudaFree still runs unconditionally, so there was no real leak.

Fix: free() now charges tensor->scale_count*sizeof(float) directly --
the exact expression upload uses -- so the two can't drift independently
again. Verified this reproduces the compressed-path charge (archive_bytes
+ O*sizeof(float)) and the fmt=4-grouped charge unchanged.

Added a byte-accounting regression to test_fp8_cuda.cu: create+free a
tracked fmt=8 dense tensor and a fmt=4-grouped tensor, assert
coli_cuda_stats returns to its pre-upload value exactly. Confirmed FAILS
on the pre-fix code (count 0->0 bytes 40432->38152) and PASSES with the
fix, plus full `make cuda-test` on spark1 (NVIDIA GB10, sm_121).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…scale bytes

coli_cuda_tensor_bytes() used the same buggy O*ng scale-byte shape that
44e1d48 already fixed in tensor_free(): for fmt=8 the real footprint is
scale_count = ((O+127)/128)*ng 128x128-block scales, not O*ng, and the
bare `tensor->fmt ?` guard (vs. upload/free's `fmt && fmt != 6`) charged
fmt=6 a phantom scale buffer it never allocates. Replaced with the same
scale_count*sizeof(float) expression upload and free already use, so all
three can no longer drift independently.

Not diagnostic-only: c/colibri.c's two callers (repin refresh accounting
and initial VRAM-tier placement) feed the value into m->gpu_expert_bytes
and the per-device `remaining[]` capacity gate that decides how many
experts get placed on GPU and which device -- a real, if conservative
(under-placement, not OOM), budget decision.

Extended test_fp8_cuda.cu with a tensor_bytes() regression: fmt=8 dense
against hand-computed weight_bytes+scale_count*4 (exact equality), fmt=6
(must equal weight_bytes alone, scale_count==0), and fmt=4-grouped as a
regression (scale_count=O*ng, value unchanged by this fix).

Verified on spark1 (NVIDIA GB10, sm_121, CUDA 13.0): reverting only this
hunk reproduces the failure (got 63744 want 61464), restoring it passes;
full make cuda-test (COLI_GPU=0) passes all four stages, make_rc=0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tprint oracle

Wire tests/test_fp8_cuda.cu into the cuda-test recipe (compiled alone like
test_fp8_warp_cuda.cu since it includes backend_cuda.cu, run before the
MXFP4 test) so the fmt=8 regression cases actually execute.

Add an independent assert to the tensor_bytes fmt=8 check: expected
footprint computed from quant.h's documented block layout (O*I e4m3
bytes + ceil(O/128)*ceil(I/128) f32 scales) rather than the struct
fields the accessor itself reads.
@JustVugg

Copy link
Copy Markdown
Owner Author

Deferred to the next release (v1.7.1/v1.8.0) — not on merit, on infrastructure. This PR is 21/22 green; the one job left is CUDA syntax check, which downloads the CUDA network installer from NVIDIA's CDN, and that download has been hanging on GitHub's runners all afternoon (three separate jobs stuck on third-party downloads today — the Vulkan job's apt install has the same problem). Retrying twice changed nothing, because the stall is not ours.

Rather than hold v1.7.0 — which ships a sixth engine with its GPU tier — on NVIDIA's CDN, this goes in the moment the runners recover. The branch is already rebased and ready; it needs a green, nothing else.

Follow-up on our side: your PRs are the argument for putting timeout-minutes and toolkit caching on these jobs (#953), so a slow mirror fails fast instead of blocking a release.

@JustVugg
JustVugg merged commit 9b6e949 into dev Aug 19, 2026
78 of 80 checks passed
@JustVugg
JustVugg deleted the fix/cuda-fmt8-rebased branch August 20, 2026 00:57
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