Row: KERNEL-QUANT-CIQ-GEMM-ROCM
DotQ4K uses the hardware __ockl_sdot4 wrapper (Dp4a,
c796fea41:src/vt/rocm/rocm_grouped_gemm.hip:78-88, called at :245, 64
invocations per superblock per lane). DotQ6K (:291-321) does not. It is
scalar multiply-add -- aux32[l] += scale * (q8p[l] * a[l]) at :312 and
:314 -- and it first materializes int8_t aux8[kQK_K], a 256-byte
per-thread array (:295).
At 128 threads per block that is 32 KB of per-block private storage for one
temporary. Whether the compiler keeps it in VGPRs or spills it to scratch is
not established here and is the first thing to measure; if it spills, the arm
pays 256 bytes written plus 256 bytes read per superblock per lane on top of
the 210 bytes of Q6_K weight it is there to read, which would more than double
the traffic of the tensor it serves.
456f9cd6f added a register-resident alternative as Fmt == 3, reachable only
through VT_ROCM_Q6K_SMALL_PRIVATE, default OFF (:459-471, :741-762). It
was added as a diagnostic A/B for the gfx1151 hang in #2511 and no throughput
verdict for it is recorded.
What it costs on the survey workload
On Qwen3.8-27B-Q4_K_M, ffn_down is the only projection with K = 17408, so
nsb = 68 > 32 and the cooperative Q6_K arm never fires for it
(KQuantDecodeCoopWarps, :777-788). Its 32 Q6_K layers are 14.54% of the
per-token swept byte budget (2,339,635,200 of 16,091,088,896 B) and they run
KQuantGemmK<OutT,2> with the scalar DotQ6K body. Lane occupancy is fine
here -- nsb = 68 fills all 32 lanes -- so this is a distinct defect from
#3016, on a distinct set of bytes, and the two do not overlap.
The ffn_down Q4_K half (32 layers, 9.97% of the budget) takes the same kernel
with the dp4a DotQ4K body, which makes this an A/B that already exists in the
same model: two arms of one tensor role, identical shape and lane occupancy,
differing only in the inner product. A rocprofv3 trace (#3015) separates them
by template instantiation without any new harness.
What is asked
- Measure whether
aux8[256] spills, by reading the ISA
(--save-temps or llvm-objdump for ScratchSize on the
KQuantGemmK<*, 2> instantiation). This needs no GPU.
- Give
DotQ6K the same Dp4a treatment DotQ4K has, or promote Fmt == 3
if it measures ahead, and record the verdict the diagnostic knob never got.
Needs a spec before code.
Related: #3016, #3015, #2109, #2511, #1910, #41.
Row:
KERNEL-QUANT-CIQ-GEMM-ROCMDotQ4Kuses the hardware__ockl_sdot4wrapper (Dp4a,c796fea41:src/vt/rocm/rocm_grouped_gemm.hip:78-88, called at:245, 64invocations per superblock per lane).
DotQ6K(:291-321) does not. It isscalar multiply-add --
aux32[l] += scale * (q8p[l] * a[l])at:312and:314-- and it first materializesint8_t aux8[kQK_K], a 256-byteper-thread array (
:295).At 128 threads per block that is 32 KB of per-block private storage for one
temporary. Whether the compiler keeps it in VGPRs or spills it to scratch is
not established here and is the first thing to measure; if it spills, the arm
pays 256 bytes written plus 256 bytes read per superblock per lane on top of
the 210 bytes of Q6_K weight it is there to read, which would more than double
the traffic of the tensor it serves.
456f9cd6fadded a register-resident alternative asFmt == 3, reachable onlythrough
VT_ROCM_Q6K_SMALL_PRIVATE, default OFF (:459-471,:741-762). Itwas added as a diagnostic A/B for the gfx1151 hang in #2511 and no throughput
verdict for it is recorded.
What it costs on the survey workload
On
Qwen3.8-27B-Q4_K_M,ffn_downis the only projection withK = 17408, sonsb = 68 > 32and the cooperative Q6_K arm never fires for it(
KQuantDecodeCoopWarps,:777-788). Its 32 Q6_K layers are 14.54% of theper-token swept byte budget (2,339,635,200 of 16,091,088,896 B) and they run
KQuantGemmK<OutT,2>with the scalarDotQ6Kbody. Lane occupancy is finehere --
nsb = 68fills all 32 lanes -- so this is a distinct defect from#3016, on a distinct set of bytes, and the two do not overlap.
The
ffn_downQ4_K half (32 layers, 9.97% of the budget) takes the same kernelwith the dp4a
DotQ4Kbody, which makes this an A/B that already exists in thesame model: two arms of one tensor role, identical shape and lane occupancy,
differing only in the inner product. A
rocprofv3trace (#3015) separates themby template instantiation without any new harness.
What is asked
aux8[256]spills, by reading the ISA(
--save-tempsorllvm-objdumpforScratchSizeon theKQuantGemmK<*, 2>instantiation). This needs no GPU.DotQ6Kthe sameDp4atreatmentDotQ4Khas, or promoteFmt == 3if it measures ahead, and record the verdict the diagnostic knob never got.
Needs a spec before code.
Related: #3016, #3015, #2109, #2511, #1910, #41.