| 2026-07-08 (conc-32 gap ROOT-CAUSED: host↔GPU memcpy SYNC, not kernels — batch-cap + mnbt hypotheses DISPROVEN) | Chased the conc-32 scaling gap (0.785×). (1) BENCH METHODOLOGY: our bench caps batch at `concurrency` (max_num_seqs=conc + client in-flight cap, bench_core.h:396/426) while vLLM `bench throughput` runs the full np=192 backlog at max_num_seqs=1024. HYPOTHESIS: unfair. DISPROVEN by the fair test below. (2) FAIR matched-batch (in1024/out128 np192, both batch≤32, GM0.6): ours=829.81, vLLM **graphed** max_num_seqs=32 = **1051.53 → 0.789×** (≈ the 'unfair' 0.785×); vLLM graphed batch-32 ≈ batch-192 (~1055) because the workload is PREFILL-BOUND (89% prefill) so batch size barely matters. So the harness cap was NOT the cause. Decode-vs-eager: ours 829 / eager-vLLM 862 = 0.96×; eager→graphed = +22% (vLLM's torch.compile fusion + async/graph). (3) mnbt (prefill budget) A/B at conc-32: default(8192)=829, 16384=788, 24576=803 → NEUTRAL (Explore's 'raise to 16384' DISPROVEN; the 454 for explicit-8192 was a measurement glitch — same config as default). | (measurement + 2 Explores + nsys) | **STEADY-STATE nsys (load EXCLUDED, window t=60-110s of an np256 run): `cudaMemcpyAsync` = 98.8% of API time (49s of a 50s window), 23,872 calls, median 7.5us but MAX 168ms → a few hundred BLOCKING stalls; GPU only ~58% busy on kernels (cutlass GEMM 43%, nvjet 8%, GDN chunk WMMA ~16%), ~42% IDLE on host memcpy sync. cudaGraphLaunch=122 (decode IS graphed) yet host stalls → sync is OUTSIDE the graph. CODE (Explore a4a91f8): the DECODE path is already fully hoisted/on-device (6-7 small H2D/step, GDN conv+ssm state in-place with gidx uploaded once, sampler downloads only token-ids); BUT the PREFILL GDN path (`GdnBlockPaged` np>0) STILL rebuilds step-constant metadata (dqsl/dhis/dpqsl from `meta.*`) as fresh pageable H2D uploads INSIDE the per-layer loop (~90 H2D/prefill-step across 30 GDN layers) — each pageable cudaMemcpyAsync blocks until the prior layer drains, serializing the 30 GDN layers per prefill step. Same class of bug the code already fixed for decode (StepDevInputs, 'replaced ~110 copies/step') + GdnPrefill qsl ('~67% GPU-idle in prefill'). LEVER IN PROGRESS: hoist prefill GDN metadata into StepDevInputs (build once/step, reuse across layers) behind VT_HOIST_GDN_PREFILL_META — worktree agent. If gap persists, next lever is the decode token-readback lockstep (async scheduling / on-device input build). KERNEL levers (GDN-as-cutlass-GEMM ~16%, flash_fwd, nvjet re-steer) are BLOCKED behind closing the ~42% host-sync idle first.** |
0 commit comments