← All posts

Qwen3.5-9B finds a needle in a 451K-token prompt on one RTX 3080

With upstream llama.cpp PR 29827 and a q4_0 KV cache, Qwen3.5-9B found a single needle at 50% depth at 320K, 384K and 448K context (YaRN x1.25 to x1.75). The 448K run used 9,692 MiB peak VRAM and 140 MiB of shared memory. The rerun of the 9B at its native 262K with the needle at 10% depth still did not pass: twice the model began a thinking block that quoted the prompt and gave no final answer within 96 tokens.

ExperimentE21G
Date2026-10-29
BenchmarkNeedle in a haystack: one passcode sentence at 10% or 50% depth in repeated filler text, greedy decoding, 96-token answer limit. A run passes only if 7319-4826 appears as the answer, not inside an unfinished thinking block.
ModelQwen3.5-9B, Q4_K_M GGUF, flash attention on, q4_0 K and V cache, ubatch 64
HardwareOne of my dedicated test rigs: RTX 3080 10 GB
VerdictBASELINE

What I tested

My build of upstream llama.cpp PR 29827, "CUDA: cap FA convert buffer for quantized KV" (not my work, unmerged when tested). 9B at native 262,144 context with the needle at 10% depth (two runs), then 320K (YaRN x1.25), 384K (x1.5) and 448K (x1.75) at 50% depth. A run is skipped if the server uses more than 300 MiB of shared GPU memory right after loading.

Pass bar, set before the run

None. Supporting measurement. A pass means the answer was 7319-4826.

Result

ContextDepthPrompt tokensAnswerPeak VRAMSharedPrefillTime
262K (native), run 110%256,843unfinished thinking block, no answer in 96 tokens (not passed)7,936 MiB116 MiB1,192 tok/s3.7 min
262K (native), run 210%256,843same as run 1 (not passed)7,936 MiB116 MiB1,185 tok/s3.7 min
320K (YaRN x1.25)50%321,6437319-4826 (pass)8,532 MiB124 MiB1,046 tok/s5.4 min
384K (YaRN x1.5)50%386,4437319-4826 (pass)9,106 MiB132 MiB937 tok/s7.0 min
448K (YaRN x1.75)50%451,2437319-4826 (pass)9,692 MiB140 MiB849 tok/s9.0 min

At 448K the q4_0 KV cache is 4,032 MiB and the 9B weights on the GPU are 4,861 MiB.

Not everything is in GPU memory. llama.cpp keeps the token embedding table (546 MiB for this model) in system memory as a lookup, plus a 60 MiB host staging buffer; attention and the whole KV cache are on the GPU. With no model loaded the card shows 20 MiB of shared memory, so the 116 to 140 MiB measured here is used by the server itself.

The script's automatic pass flag checked for the passcode anywhere in the reply, so it marked both 10% runs as passes even though the model only quoted the prompt while thinking. I graded them by hand. The next round requires the passcode in the final answer and allows 1,024 tokens so thinking can finish.

448K was the largest context tried in this round. The next round tries 480K.

One needle in simple repeated filler is an easy haystack. This is not a RULER score.

What happened

The 9B model held a 451K-token prompt on the card and still pulled out the passcode, using 9.7 of 10 GB. Each step from 320K to 448K added roughly 580 MiB and cost some prefill speed, from 1,046 down to 849 tokens per second. The rerun at native 262K with the needle near the start did not pass either time: the model started reasoning, restated the question, and hit the 96-token limit before answering. The memory saving that made these fit is upstream PR 29827, so credit goes to its authors.

How to rerun

powershell -ExecutionPolicy Bypass -File e21g_chain.ps1

Code

All code for E21G: README.md, e21g_chain.ps1, results.jsonl.

Prior work

No novelty claim. This measures an existing upstream llama.cpp pull request with a standard needle test.

Written by Andrew Rose with help from AI tools. Every number comes from the run logs.

Questions or ideas? me@andrewroseit.com or @AndrewRoseIT.