Skip to content

fix: reject ATOM prefix cache with kv_blocks == lanes + 1 (#172) - #181

Merged
gspark-etri merged 2 commits into
optimus-rmfrom
fix/172-atom-kv-blocks
Oct 23, 2026
Merged

gspark-etri merged 2 commits into
optimus-rmfrom
fix/172-atom-kv-blocks

Conversation

@gspark-etri

Copy link
Copy Markdown
Collaborator

Background

AtomKVBlocks accepts kv_blocks == lanes + 1 (one block per lane plus the scratch block). With prefix caching on, a finished request's block becomes the only cache entry; when a new request in that lane shares its prefix, admit() calls _take(keep=src), finds no victim other than the source, raises RuntimeError("no KV block available"), and step() poisons the batcher. Repro: batch=1, blocks=2, the same prompt twice.

Changes

  • opt_prime/opt_prime/accel/platforms/atom/batching.py:81-82: with prefix_cache, AtomKVBlocks requires kv_blocks >= lanes + 2 and raises ValueError otherwise. When a lane is admitted at most lanes - 1 blocks are held by lanes, so lanes + 2 blocks always leave an entry other than the copy source (or a free block). The AtomBatcher docstring states the requirement.
  • opt_prime/tests/test_atom_batching.py: test_prefix_cache_needs_an_evictable_block checks the rejection, and that kv_blocks == lanes + 1 without prefix cache still serves the same prompt twice token-exactly.

I chose rejection over reusing the source block in place: it is a two-line change, and with a single cache block the reuse path would only help the exact-repeat case at the cost of extra special cases in _take/admit (skipping the copy, dropping the index entries, LRU bookkeeping).

Verification

CPU only (fake RBLN SDK of the existing tests, no NPU), Python 3.10, torch 2.10.0+cu128, base optimus-rm @253be20.

On the unfixed code (from opt_prime/):

TORCH_DEVICE_BACKEND_AUTOLOAD=0 CUDA_VISIBLE_DEVICES=1 PYTHONPATH=$PWD python3 -m pytest -q tests/test_atom_batching.py -k evictable
E  Failed: DID NOT RAISE ValueError
1 failed

and the issue's repro (same prompt twice, batch=1, blocks=2, prefix cache) fails with RuntimeError: no KV block available at batching.py:172. After the fix the new test passes; tests/test_atom_batching.py tests/test_pd_atom_reuse.py tests/test_pd_native_atom.py: 15 passed, 2 skipped.

Whole suite:

TORCH_DEVICE_BACKEND_AUTOLOAD=0 CUDA_VISIBLE_DEVICES=1 PYTHONPATH=$PWD python3 -m pytest -q tests
before (253be20): 400 passed, 23 skipped, 135 subtests passed
after:            401 passed, 23 skipped, 135 subtests passed

Compatibility and limits

  • Configurations with prefix_cache=True and kv_blocks == batch_size + 1 now fail at construction instead of failing on the first prefix hit; they need one more compiled KV block. docs/validation/batching/ATOM.md already describes kv_blocks = B + cache + 1.
  • Own block tables without prefix cache (PD import, plain refill) still accept kv_blocks == lanes + 1.

Related Issue

Closes #172

🤖 Generated with Claude Code

gspark-etri and others added 2 commits October 23, 2026 09:59
…#172)

With one block besides the scratch block per lane, the only cache entry is
also the copy source of a prefix hit, so _take(keep=src) found no block,
raised "no KV block available" and poisoned the batcher. Prefix caching
now needs kv_blocks >= lanes + 2, which always leaves an evictable entry
other than the source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gspark-etri
gspark-etri merged commit f2afe7a into optimus-rm Oct 23, 2026
1 check passed
@gspark-etri
gspark-etri deleted the fix/172-atom-kv-blocks branch October 23, 2026 01:07
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