Ray Shao Back to the room Desktop
ProjectsvLLM Formally Verified Sliding-Window Prefix Cache Optimization

← Projects

vLLM Formally Verified Sliding-Window Prefix Cache Optimization

Nov 2026 to Present

On this page 5 sections
  1. 1. Problem Statement
  2. Critical Bottlenecks:
  3. 2. Algorithm Architecture
  4. Invariant Principles:
  5. 3. Formal Verification in Lean 4
  6. Formal Specification: ValidWindow
  7. Proven Theorems:
  8. 4. Empirical Performance Benchmarks
  9. 4.1 CPU Scheduler Microbenchmarks (PR Stride Jumping)
  10. 4.2 Live End-to-End GPU Generation on AMD Instinct MI50
  11. 5. Upstream PR & Verification Status
Project Summary

Formally verified and implemented an O(N/W + W) stride jump search for sliding-window prefix caching in vLLM V1. The algorithm replaces an O(N) backwards linear scan. It reduces CPU scheduler stalls by up to 61.3x across models released post-June 2026. Machine-checked proofs in Lean 4 prove soundness, boundary safety, and prefix fallback correctness with zero sorry axioms. Upstream contribution submitted to vllm-project/vllm as Pull Request #65086.


1. Problem Statement

In vLLM V1 (single_type_kv_cache_manager.py), sliding window attention models require locating the rightmost contiguous run of at least W (sliding_window_contiguous_blocks) cached KV blocks.

The legacy implementation performed an O(N) linear loop scanning backwards block by block from max_num_blocks - 1 down to 0:

# Legacy linear scan
for i in range(max_num_blocks - 1, -1, -1):
    if cached_block := block_pool.get_cached_block(block_hashes[i], ...):
        ...

Critical Bottlenecks:

  1. CPU Scheduler Starvation: At 128K context (8,192 blocks), a single request performed 8,192 sequential Python hash lookups. Under concurrent batch serving, the single-threaded CPU engine stalled for hundreds of milliseconds, leaving GPUs idle.
  2. Prior Failed Attempts: Prior attempt PR #63798 attempted stride probing. However, heuristic boundary expansion caused off-lattice cache misses and corrupted prefix fallback with NULL block leaks.
  3. Open Maintainer Debt: Upstream maintainers explicitly marked line 1002 with # TODO: reduce i by sliding_window_contiguous_blocks when cache miss.

2. Algorithm Architecture

flowchart TD
    A["Candidate Window: [e - W, e)"] --> B{"Probe Anchor Block p = e - W"}
    B -- "Miss" --> C["Jump e <- e - W (Skip W blocks in 1 probe)"]
    C --> A
    B -- "Hit" --> D{"Probe Inner Blocks k in [e-1 .. p+1]"}
    D -- "Miss at k" --> E["Jump e <- k (Skip invalid window run)"]
    E --> A
    D -- "All Hit" --> F["Full Window Hit Found: Return [e - W, e)"]
    A -- "e < W (No window hit)" --> G{"Forward Prefix Fallback"}
    G --> H["Scan k in [0 .. W-1] until miss: Return Contiguous Run"]

Invariant Principles:

  1. Anchor Probing: For a window of length W ending at e, index $p = e - W$ is mandatory. If index p is a cache miss, no window ending in $[e - W + 1, e]$ can be valid. The candidate end safely jumps e \leftarrow e - W.
  2. Inner Probing: When anchor p hits, verify remaining blocks from right to left ($e - 1$ down to $p + 1$). If index k misses, jump candidate end e \leftarrow k.
  3. Sound Prefix Fallback: When $e < W$, probe forward from index 0. If block 0 misses, exit in 1 lookup. Real prefix hits align cleanly without uninitialized block leakage.

3. Formal Verification in Lean 4

The algorithm was modeled and verified in Lean 4 (lean_prefix_cache/LeanPrefixCache.lean) with zero axioms (sorry).

Formal Specification: ValidWindow

def ValidWindow (cache : Array Bool) (w : Nat) (s e : Nat) : Prop :=
  e - s ≥ w ∧ e ≤ cache.size ∧ ∀ (i : Nat), s ≤ i → i < e → ∃ (h : i < cache.size), cache[i] = true

Proven Theorems:

  1. Soundness (strideSearch_sound):

    theorem strideSearch_sound (cache : Array Bool) (w : Nat) (s e : Nat) :
        strideSearch cache w = some (s, e) → ValidWindow cache w s e

    Guarantees that every returned window $[s, e)$ has length ≥ W and contains only valid cached blocks.

  2. Boundary Safety (strideSearch_boundary_safety):

    theorem strideSearch_boundary_safety (cache : Array Bool) (w : Nat) (s e : Nat) :
        strideSearch cache w = some (s, e) →
        e ≤ cache.size ∧ (∀ i : Nat, s ≤ i → i < e → i < cache.size)

    Guarantees no out-of-bounds indices are dereferenced or returned.

  3. Prefix Fallback Soundness (prefixFallback_correct): Guarantees maximal prefix extraction without NULL block table corruption.

The project compiled to a C shared library (libprefix_cache_lean.so) and passed 1,000 property-based random tests via C FFI.


4. Empirical Performance Benchmarks

4.1 CPU Scheduler Microbenchmarks (PR Stride Jumping)

Evaluated on official Hugging Face checkpoints released post-June 2026 using vLLM BlockPool at 5% sparse cache hits:

Model Checkpoint Release Date Sliding Window Context Upstream Latency Stride Latency Latency Speedup Hash Lookups (Legacy → Stride)
Qwen/Qwen3.8-Flash-Next 2026-08-24 2,048 tokens 4K 0.1581 ms 0.0052 ms 30.5x 256 → 12
8K 0.3263 ms 0.0073 ms 44.9x 512 → 14
32K 1.3463 ms 0.0220 ms 61.3x 2,048 → 26
thinkingmachines/Inkling 2026-07-14 512 tokens 4K 0.1717 ms 0.0084 ms 20.4x 256 → 18
8K 0.3244 ms 0.0144 ms 22.5x 512 → 26
32K 1.3479 ms 0.0547 ms 24.6x 2,048 → 74
OTel-2.0-Decision-26B 2026-10-06 1,024 tokens 4K 0.1582 ms 0.0063 ms 25.1x 256 → 14
8K 0.3269 ms 0.0098 ms 33.5x 512 → 18
32K 1.3659 ms 0.0314 ms 43.5x 2,048 → 42
DeepSeek-V4-Flash-0731 2026-07-31 128 tokens 4K 0.1574 ms 0.0227 ms 6.9x 256 → 40
8K 0.3343 ms 0.0531 ms 6.3x 512 → 72
32K 1.3640 ms 0.1914 ms 7.1x 2,048 → 264

4.2 Live End-to-End GPU Generation on AMD Instinct MI50

Validated live multi-token inference on physical AMD Instinct MI50 hardware (32 GB HBM2, gfx906, ROCm 7.14 / PyTorch 2.13):

Benchmark A: cyankiwi/Qwen3.8-27B-AWQ-INT4 (27B Post-June 2026 Model)

Benchmark B: Qwen/Qwen3-8B-AWQ (Dense 8B Model)

Benchmark C: Physical Cluster Job Algorithmic Scaling (PR #65086 vs Upstream Baseline)

Evaluated directly inside the k3s MI50 container pod (vllm-live-gpu-bench):

Sequence Length Sliding Window (W) Total Blocks (N) Upstream Baseline Lookups PR #65086 Stride Lookups Lookup Reduction Lookup Speedup
2,048 tokens 1,024 tokens (64 blk) 128 128 16 87.5% 3.85x
4,096 tokens 1,024 tokens (64 blk) 256 256 18 93.0% 6.70x
4,096 tokens 4,096 tokens (256 blk) 256 256 15 94.1% 7.41x
8,192 tokens 1,024 tokens (64 blk) 512 512 22 95.7% 14.45x
8,192 tokens 4,096 tokens (256 blk) 512 512 16 96.9% 18.03x
16,384 tokens 1,024 tokens (64 blk) 1,024 1,024 30 97.1% 24.29x
16,384 tokens 4,096 tokens (256 blk) 1,024 1,024 18 98.2% 36.34x
32,768 tokens 1,024 tokens (64 blk) 2,048 2,048 46 97.8% 29.12x
32,768 tokens 4,096 tokens (256 blk) 2,048 2,048 22 98.9% 63.07x

5. Upstream PR & Verification Status

All projectsBack to top