Skip to content

Commit caae4cd

Browse files
docs(adr-0015): item #1 done - SDPA+chunked-logits unblocks long context (recall 1.0)
Measured on H200: 16k N=1-only->N=4, 32k OOM->N=2, 62k OOM->N=1, all recall 1.0; 16k N=1 peak 138.8->74.5GB. Honest: per-session memory still grows ~linearly (full-T K/V capture + f_theta intermediates), so the concurrency win vs vLLM's 15.5@62k is gated on item #2 (bounded native decode cache). Evidence log added. Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent 5bcf75b commit caae4cd

3 files changed

Lines changed: 54 additions & 4 deletions

File tree

docs/adr/0015-kakeya-attention-and-engine-substrate.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ long prefills (N=1-only at 16k, OOM at 32k) due to O(T²) eager scores +
4949
full-vocab logits + a redundant `capture_verifier_own_kv` forward.
5050

5151
**Substrate work items (ordered):**
52-
1. **Memory-efficient restoration prefill** — replace the patched *eager*
53-
attention with SDPA/FlashAttention, chunk the LM-head logits, drop the
54-
redundant full forward for the exact layers. (Unblocks long context.)
52+
1.**Memory-efficient restoration prefill** — patched forward routes to
53+
**SDPA** (`--attn-impl sdpa`), LM-head logits chunked (`logits_to_keep=1` on
54+
the restored forward + `capture_verifier_own_kv`), restored K/V held in bf16.
55+
**Unblocked long context** (recall 1.0): 16k went N=1-only→N=4, 32k OOM→N=2,
56+
62k OOM→N=1; 16k N=1 peak 138.8→74.5 GB. (`docs/reports/kakeya-vs-vllm-longcontext-h200.md`.)
5557
2. **Bounded decode cache as the native KV layout** — resident sink+window +
56-
5 exact full-attention layers; no Python per-step `DynamicCache`.
58+
5 exact full-attention layers; no Python per-step `DynamicCache`. **This is
59+
the gating item for the long-context concurrency win**: today the bench still
60+
captures full-T K/V at decode (~17 GB/session @16k), so the bounded advantage
61+
is not yet realized — #1 only made the prefill *run*.
5762
3. **CUDA graphs** for the decode step; **fused-MoE** kernels for the verifier.
5863
4. (Optional) integrate Kakeya Attention as a **vLLM attention backend** so the
5964
bounded window rides vLLM's paged store + scheduler.

docs/reports/kakeya-vs-vllm-longcontext-h200.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,34 @@ where bounded-KV produces a real long-context concurrency sweet spot.
7575
gemma-4** on this hardware (it runs 62k at ~15× concurrency; Kakeya eager does
7676
not run past 16k N=1).
7777

78+
## Update — ADR 0015 item #1 (SDPA + chunked logits) landed
79+
80+
Replacing the eager restoration prefill with **SDPA** (`--attn-impl sdpa`, the
81+
patched forward routes to `all_attention_functions["sdpa"]`) + **chunked logits**
82+
(`logits_to_keep=1` on the restored forward and `capture_verifier_own_kv`) +
83+
**bf16 restored K/V** **unblocked long context**, recall **1.0** throughout:
84+
85+
| ctx | eager (before) | SDPA (after) | peak @ max N |
86+
| --- | --- | --- | --- |
87+
| 16k | N=1 only (138.8 GB) | **N=4** (recall 1.0) | 124.6 GB |
88+
| 32k | **OOM at N=1** | **N=2** (recall 1.0) | 133.8 GB |
89+
| 62k | OOM at N=1 | **N=1** (recall 1.0) | 120.8 GB |
90+
91+
(16k N=1 peak dropped 138.8 → 74.5 GB.) This is the item-#1 win: the restoration
92+
prefill now executes at 32k/62k where eager could not.
93+
94+
**Remaining bottleneck (→ items #2–3).** Per-session memory still grows
95+
~linearly with context (~17 GB/session @16k, ~37 GB @32k) because **this bench
96+
captures the full-T K/V into the decode cache** and holds the f_θ projection
97+
intermediates — i.e. it does **not** yet exercise the *bounded* resident cache
98+
(SinkWindowKVCache). So the restored path here is still effectively full-KV at
99+
decode; beating vLLM's **15.5-way** 62k concurrency requires item #2 (bounded
100+
native decode cache: store only sink+window + 5 exact layers, restore on demand)
101+
+ freeing the f_θ intermediates. Item #1 was the prerequisite (it makes long
102+
prefills run at all); the concurrency-ceiling win is gated on #2.
103+
104+
Evidence: `results/research/k3_cuda_mt_longctx_sdpa_ceiling_h200nvl.log`.
105+
78106
## Evidence
79107

80108
- `results/research/vllm_multitenant_parallel_h200nvl_ctx62k.json`
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
===== ctx16k restored-only sdpa N=1,2,4,8 =====
2+
[mt] modal prompt len=16038, 20 equal-length prompts (of 24)
3+
[mt] N= 1 | AR nan tok/s (xnan, recall nan) | restored 11.09 tok/s (x1.0, recall 1.0) | peak 74.46GB
4+
[mt] N= 2 | AR nan tok/s (xnan, recall nan) | restored 22.99 tok/s (x2.07, recall 1.0) | peak 92.39GB
5+
[mt] N= 4 | AR nan tok/s (xnan, recall nan) | restored 36.7 tok/s (x3.31, recall 1.0) | peak 124.61GB
6+
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 5.38 GiB. GPU 0 has a total capacity of 139.80 GiB of which 5.00 GiB is free. Process 3233087 has 134.79 GiB memory in use. Of the allocated memory 133.74 GiB is allocated by PyTorch, and 380.97 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://docs.pytorch.org/docs/stable/notes/cuda.html#optimizing-memory-usage-with-pytorch-cuda-alloc-conf)
7+
===== ctx32k restored-only sdpa N=1,2,4 =====
8+
[mt] modal prompt len=32038, 20 equal-length prompts (of 24)
9+
[mt] N= 1 | AR nan tok/s (xnan, recall nan) | restored 10.22 tok/s (x1.0, recall 1.0) | peak 97.02GB
10+
[mt] N= 2 | AR nan tok/s (xnan, recall nan) | restored 17.73 tok/s (x1.73, recall 1.0) | peak 133.84GB
11+
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 502.00 MiB. GPU 0 has a total capacity of 139.80 GiB of which 389.06 MiB is free. Process 3235509 has 139.41 GiB memory in use. Of the allocated memory 138.48 GiB is allocated by PyTorch, and 262.44 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://docs.pytorch.org/docs/stable/notes/cuda.html#optimizing-memory-usage-with-pytorch-cuda-alloc-conf)
12+
===== ctx62k restored-only sdpa N=1,2 =====
13+
[mt] modal prompt len=62038, 20 equal-length prompts (of 24)
14+
[mt] warmup note: CUDA out of memory. Tried to allocate 14.34 GiB. GPU 0 has a total capacity of 139.80 GiB of which 11.77 GiB is free. Process 3238344 has 128.02 GiB memory in use. Of the allocated memory 127.15 GiB is allocated by PyTorch, and 202.42 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://docs.pytorch.org/docs/stable/notes/cuda.html#optimizing-memory-usage-with-pytorch-cuda-alloc-conf)
15+
[mt] N= 1 | AR nan tok/s (xnan, recall nan) | restored 7.55 tok/s (x1.0, recall 1.0) | peak 120.8GB
16+
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 14.34 GiB. GPU 0 has a total capacity of 139.80 GiB of which 8.41 GiB is free. Process 3238344 has 131.39 GiB memory in use. Of the allocated memory 130.24 GiB is allocated by PyTorch, and 487.67 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://docs.pytorch.org/docs/stable/notes/cuda.html#optimizing-memory-usage-with-pytorch-cuda-alloc-conf)
17+
CEILING_DONE

0 commit comments

Comments
 (0)