Expand description
A per-layer KV cache, growable one position at a time during decode. Two growth strategies exist:
with_pool: PagedAttention-style block allocation. Many caches (one per concurrent request, typically) draw fixed-size blocks from one shared, boundedKvBlockPoolinstead of each independently pre-committing to a worst-case context length. Growth happens in fixed block-sized quanta, and a cache’s blocks return to the shared pool when it’s dropped, so the pool’s free count is a real, live admission-control signal a caller can check before accepting a new request. This is the block-allocation half of PagedAttention; it does not (yet) change how attention reads a cache –k/vare still read as one contiguous slice per sequence (seeDecoder::forward_token/forward_batch), just backed by capacity that grows in block-sized steps instead of Rust’s default exponentialVecgrowth. Wiring this intoferrox-serveras live per-request admission control viaFERROX_KV_POOL_BLOCKS/FERROX_KV_POOL_BLOCK_SIZE.
Structs§
- KvBlock
Pool - A bounded pool of fixed-size KV-cache blocks (in positions) shared
across many
KvCacheinstances, typically one pool per server process. EachKvCache::with_poolacquires one block up front and one more each time it grows past its currently held capacity;free_blocksis therefore a live, accurate admission-control signal – a caller can check it before accepting a new request rather than discovering exhaustion only after committing memory. - KvCache
- KvPool
Exhausted - Returned by
KvCache::push(andwith_pool) when a pool-backed cache needs another block but its sharedKvBlockPoolhas none free. Caches built withnew/with_capacitynever return this – their growth is unconditional, matching their pre-paging behavior exactly. - Page
Group - A handle to one block in every layer.
- Paged
KvCache - One sequence’s view into a shared
PagedKvStore: a block table (which physical blocks this sequence’s positions live in, in order) plus how many positions have been written so far. UnlikeKvCache, this holds no K/V data itself – every read and write goes through the shared store. - Paged
KvStore - The other half of PagedAttention that
KvBlockPool/KvCache::with_pooldeliberately don’t implement (see this module’s doc comment): real, shared physical block storage that many sequences’ block tables can address into, instead of eachKvCachestill owning its own private, contiguousVec.KvBlockPoolonly ever bounds a count of blocks each cache may grow to;PagedKvStoreis the actual backing memory, and a sequence’sPagedKvCacheholds a block table (an ordered list of block IDs into this shared store) instead of owning K/V data directly. This is what makes non-contiguous-block reads during attention (causal_gqa_attention_paged, inattention.rs) possible at all –causal_gqa_attention’s existing contiguous-slice read pattern has no way to express “position 37 lives in block 12, cached out of order relative to block 5.” - Paged
Store Exhausted - Returned when a
PagedKvCacheneeds another block but itsPagedKvStorehas none free – the paged-storage analog ofKvPoolExhausted. - Shared
Paged Kv - Per-layer
PagedKvStores that many concurrent requests share.