Skip to content

cuda: out_prod accepts a quantized src0 — the backward through a resident quantized base (Continuum dd109d3c) - #3

Merged
joelteply merged 1 commit into
feat/props-weight-residencyfrom
continuum/cuda-out-prod-quantized
Sep 26, 2026
Merged

joelteply merged 1 commit into
feat/props-weight-residencyfrom
continuum/cuda-out-prod-quantized

Conversation

@joelteply

Copy link
Copy Markdown

What

ggml_cuda_out_prod accepts a quantized (or F16/BF16) src0. The backward of mul_mat(W, x) with respect to x is out_prod(W, grad^T); the CPU backend already dispatches every quantized src0 type to out_prod_q_f32, but this backend only took F32 — so a LoRA could train on a resident Q4_K_M base on CPU and not on CUDA (Continuum card dd109d3c, S3a of the one-resident-model design).

  • out-prod.cu: a non-F32 src0 (contiguous) is dequantized into a transient F32 pool copy through ggml_get_to_fp32_cuda(src0->type) — the converters mul_mat already uses — and the existing three cuBLAS GEMM paths run on the dense copy (F32 strides derived from ne0x, not the quantized nb0x).
  • ggml-cuda.cu supports_op: OUT_PROD admits any contiguous src0 with an F32 converter; src1/dst stay F32.

Memory: one dequantized copy of src0 per op, transient in the pool (a 5120×17408 weight is 356 MB for the duration of the GEMM). A fused dequant-GEMM (the mmq route) is the follow-on if the training-throughput gate needs it.

Measured (RTX 5090, CUDA 13.2, Windows, this branch)

test-backend-ops test -b CUDA0 -o OUT_PROD against the CPU backend as the oracle:

passed 231/231 (Backend CUDA0: OK)
per type_a OK f32 34, f16 16, q8_0 16, q4_0 16, q4_1 16, q4_K 16, mxfp4 16, nvfp4 16, iq2_xxs 16, q1_0 16, q2_0 16
FAIL 0
refused by CUDA 0
no oracle 480 broadcast cases (nr > 1) the CPU backend does not support, skipped by the harness as before

Before this change every quantized type_a case was not supported [CUDA0].

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc

…through a resident quantized base weight

The backward of mul_mat(W, x) w.r.t. x is out_prod(W, grad^T). The CPU backend
dispatches every quantized src0 type to out_prod_q_f32; this backend only took F32,
so a LoRA could train on a resident Q4_K_M base on CPU and not on CUDA (Continuum
card dd109d3c, measured 2026-09-26 on a 5090). Dequantize W into a transient F32 pool
copy through the converters mul_mat already uses, then run the existing F32 GEMMs on
the dense copy (strides from ne0x, not the quantized nb0x). supports_op admits any
contiguous src0 with an F32 converter. test-backend-ops' OUT_PROD sweep over
base_types (Q8_0, Q4_0, Q4_1, Q4_K, MXFP4, NVFP4, IQ2_XXS, ...) now runs on CUDA and
is compared against the CPU backend.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc
@joelteply
joelteply changed the base branch from master to feat/props-weight-residency September 26, 2026 22:31
@joelteply
joelteply merged commit a0c6294 into feat/props-weight-residency Sep 26, 2026
32 of 73 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant