Skip to content

feat(scheduler): --logprob-read-isolate makes logprob reads independent of other traffic - #96

Open
gdevenyi wants to merge 3 commits into
5080/47-rebuild-cc56b6bdfrom
5080/48-logprob-read-isolate
Open

gdevenyi wants to merge 3 commits into
5080/47-rebuild-cc56b6bdfrom
5080/48-logprob-read-isolate

Conversation

@gdevenyi

Copy link
Copy Markdown
Owner

Makes a logprob read's scores independent of other traffic, behind --logprob-read-isolate. A read is a request with logprobs and max_tokens == 1, the shape AnyJev scoring sends. The flag is off by default; production turns it on. Stacked on #95.

Commits

  • fc305238: the SamplingParams.is_logprob_read predicate and the flag.
  • fed01568: a read is prefilled in a pass of its own. It is never co-batched, so cuBLAS kernel choice by total M, the per-tensor FP8 amax and the MoE configuration all depend only on its own prompt. A chunked read's continuation is also alone.
  • cc13fecc: reads neither resume from the prefix cache nor donate to it (max_len=0, no host-tier lookup, donate none). Also guards the chunk-commit branch under none. That gap is not reachable from the scheduler today, but it is now closed in CacheManager.

Why

Batched vs single prefill differs by 0.4-1.7 nats on top-5 logprobs. The cause is GEMM kernel selection by total row count, plus per-tensor FP8 scales shared across the batch (fork #94). A prefix-cache resume also changes numerics compared with a cold prefill. So the same AnyJev question got different scores depending on what else was running and on what ran before it.

GPU check (integ7/invariance/read_checks.py, batch_debug.py, anyjev_check.py)

flag off flag on
same read 3x at 300 / 512 / 513 / 819 / 820 / 4096 tokens all differ (cache hits) bitwise equal
read after a chat turn on the same prefix differs equal
8 parallel reads vs each alone 7 of 8 differ equal
3-prompt request vs single requests up to 0.87 nats 0.0
prefill passes mixing a read with another request – 0
chat greedy fingerprints 99da06fb… identical
main conversation after 96 scoring reads evicted (13.9 s resume) survives (0.54 s)
8 parallel reads, 60 / 400 tokens 1.48 / 6.79 s 2.62 / 6.66 s

Cost: short parallel reads are about 1.8x slower, and rotation scoring is about 2x slower because there is no prefix reuse. Chat and side calls run exactly the same code path as before.

CPU tests: tests/scheduler/test_scheduler_chunked_prefill.py and test_hybrid_cache_manager.py. They fail before (6 and 4 failures) and pass after.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Td2gieja9Da2rPTN17Z846

gdevenyi and others added 3 commits October 20, 2026 18:35
…ob_read predicate

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Td2gieja9Da2rPTN17Z846
Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Td2gieja9Da2rPTN17Z846
An isolated read matches with max_len 0 (no host-tier lookup) and donates nothing.
The prefill-commit branch also skips the snapshot insert for a non-donating read;
the scheduler only reaches it for requests that keep decoding, never a read.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Td2gieja9Da2rPTN17Z846
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant