Field Log · Entry

Paged KV Cache·Prefix Caching: Block·Eviction·Reuse (5/10)

요청의 logical KV block을 불연속 physical GPU page에 매핑하고 radix prefix tree에서 공유한 뒤 refcount, copy-on-write, eviction과 CPU·SSD tier로 관리하는 구조

오늘의 결론

  • Paged KV는 요청마다 최대 context만큼 연속 메모리를 미리 잡는 대신, token이 늘 때 fixed-size physical block을 필요만큼 붙입니다. Logical 순서는 block table이 유지합니다.
  • Paged allocation과 prefix caching은 다른 기능입니다. 전자는 공간 할당, 후자는 여러 요청이 동일한 token prefix의 이미 계산된 KV를 공유·재사용하는 정책입니다.
  • Exact prefix hit는 text가 비슷한지가 아니라 model·tokenizer·adapter·position·KV format까지 같은 token prefix인지로 판정합니다. 중간 document 조각의 KV를 임의로 이어 붙일 수 없습니다.
  • Shared block은 reference count로 보호하고, branch가 마지막 partial block을 수정할 때 copy-on-write합니다. Active·pinned block을 eviction하면 correctness bug가 됩니다.
  • Eviction은 LRU 하나로 끝나지 않습니다. Reuse probability, saved prefill time, block byte, reload cost, tenant boundary, next Agent step을 반영하고 hit rate가 아니라 절약한 prefill token·TTFT로 평가합니다.

앞 글에서는 scheduler가 iteration compute budget과 resident KV budget을 함께 관리해야 한다고 설명했습니다. 이번 글은 그 resident KV가 실제 GPU block에 배치되고 공유·회수되는 lifecycle을 다룹니다.

token sequence
  → logical KV blocks
  → per-request block table
  → physical GPU pages
  → optional shared prefix entries
  → refcount / copy-on-write
  → evict, offload, reload, or recompute

이 글에서 답하는 질문

  1. 연속 KV 예약은 왜 memory를 낭비하는가?
  2. Logical block과 physical block table은 어떻게 동작하는가?
  3. Prefix cache가 정확하게 재사용될 수 있는 조건은 무엇인가?
  4. Shared prefix 뒤의 branch는 언제 copy-on-write하는가?
  5. LRU eviction이 Agent workflow에서 실패하는 이유는 무엇인가?
  6. GPU·CPU·SSD 계층 cache와 tenant 격리를 어떻게 운영하는가?

두 요청의 logical KV block이 불연속 physical GPU page를 block table로 가리키고 동일한 system 및 tool prefix를 radix tree와 reference count로 공유하며 branch suffix는 copy-on-write하고 evictable prefix는 cost-aware policy로 CPU와 SSD tier 또는 recompute 경로로 이동하는 lifecycle

그림 1. Paged KV의 핵심은 logical 연속성과 physical 연속성을 분리하는 것이다. Prefix cache는 그 위에 identity·ownership·lifetime을 더한 별도 계층이다.


1. KV Cache가 저장하는 것

Autoregressive decoder는 과거 token마다 각 layer의 key와 value를 저장합니다. 새 token을 만들 때 과거 K/V를 다시 계산하지 않고 cache에서 읽습니다.

$$ KV(token)={K_l(token),V_l(token)}_{l=1}^{L} $$

KV는 request가 진행되는 동안 token과 함께 자랍니다. 메모리 계산 글에서 본 것처럼 GQA model의 token당 byte는 layer, KV head, head dimension, dtype으로 정해집니다.

2. 최대 길이 연속 예약의 낭비

예전 방식처럼 각 request에 최대 output 길이까지 연속 공간을 예약한다고 가정합니다.

request A: current  700 tokens / reserved 8192
request B: current 3200 tokens / reserved 8192
request C: current  120 tokens / reserved 8192

실제 사용은 4,020 token인데 24,576 token 공간을 묶습니다. Output 길이를 미리 모르므로 작은 예약은 재할당을 만들고 큰 예약은 internal·external fragmentation과 낮은 batch capacity를 만듭니다.

3. OS Paging에서 가져온 생각

PagedAttention은 KV를 fixed-size block으로 나누고 request의 logical block을 임의의 free physical block에 연결합니다.

request A logical blocks: [A0, A1, A2]
block table:               [P7, P2, P11]

logical order A0 → A1 → A2
physical order P2, P7, P11 anywhere in GPU pool

Attention kernel은 token position에서 logical block 번호와 offset을 구하고 block table로 physical address를 찾습니다.

4. Address Translation

Block size를 S token이라 하면 logical token position t는:

$$ logical_block=\left\lfloor\frac{t}{S}\right\rfloor $$

$$ offset=t\bmod S $$

def kv_address(block_table, token_position, block_size):
    logical_block = token_position // block_size
    offset = token_position % block_size
    physical_block = block_table[logical_block]
    return physical_block, offset

각 layer·K/V·head dimension의 실제 byte offset은 engine layout에 따라 더해집니다.

5. Append는 Block 단위로 일어난다

Decode가 새 token을 만들 때 현재 마지막 block에 빈 slot이 있으면 그곳에 KV를 씁니다. 가득 차면 free list에서 새 physical block을 받아 block table에 붙입니다.

before: table [P7, P2] · P2 used 15/16
append: token 31 → P2 slot 15
next:   token 32 → allocate P11 · table [P7, P2, P11]

Request가 끝나면 private block의 refcount를 낮추고 0이 된 block을 free pool에 반환합니다.

6. Fragmentation은 사라지지 않고 제한된다

Paging은 request별 최대 길이 예약과 큰 contiguous hole 문제를 줄입니다. 하지만 마지막 partial block에는 빈 slot이 남습니다.

wasted slots per sequence < block_size

Active sequence가 N개면 최악의 내부 낭비는 대략 N × (S-1) token slot 미만입니다. Block size가 작을수록 마지막 낭비는 줄지만 metadata와 address translation·kernel overhead가 늘 수 있습니다.

7. Block Size의 Trade-off

작은 Block

  • On-demand allocation이 세밀합니다.
  • 마지막 block 낭비가 작습니다.
  • Block table과 hash entry가 많아집니다.
  • Prefix match·transfer가 잘게 쪼개집니다.
  • Attention address 연산이 늘 수 있습니다.

큰 Block

  • Metadata와 transfer batching이 단순해집니다.
  • Kernel locality가 좋아질 수 있습니다.
  • Partial block 낭비와 copy-on-write byte가 커집니다.
  • 짧은 prefix 재사용 granularity가 거칠어집니다.

16 token이 정답처럼 외우지 말고 model KV bytes/token, context 분포, attention backend, transfer tier로 측정합니다.

8. Paged KV와 vAttention의 차이

PagedAttention은 physical KV를 불연속 block으로 배치하고 attention kernel이 block table을 이해하게 합니다. vAttention은 큰 contiguous virtual address를 유지하면서 CUDA virtual memory API로 physical page를 demand-map하는 대안을 제시합니다.

PagedAttention: virtual/kernel-visible layout is paged
vAttention:     virtual layout contiguous, physical mapping dynamic

목적은 둘 다 physical over-reservation과 fragmentation을 줄이는 것입니다. Kernel 호환성, page mapping overhead, platform support를 target engine에서 비교합니다.

9. Prefix Caching은 별도 계층이다

요청 A와 B의 처음 token이 완전히 같다면 그 prefix의 KV도 같습니다.

A: [system][tool schema][user A][...]
B: [system][tool schema][user B][...]
    └──────── shared prefix ────────┘

첫 요청이 만든 system·tool prefix KV를 cache에 남기고 다음 요청이 참조하면 해당 token의 prefill 계산과 KV 중복 저장을 줄일 수 있습니다.

Paging 없이도 prefix caching을 구현할 수 있고, paging을 쓰면서 cache를 비활성화할 수도 있습니다. 두 기능을 같은 말로 부르면 metric과 bug 원인을 구분하기 어렵습니다.

10. Exact Reuse가 가능한 이유

Causal Transformer에서 position i의 K/V는 0..i token prefix에만 의존합니다. 두 요청의 token prefix와 execution identity가 같다면 해당 구간의 KV를 재사용할 수 있습니다.

same text처럼 보임  ≠ same token ids
same token ids       ≠ always compatible KV

KV는 model parameter, adapter, position encoding, dtype·layout에도 의존합니다. 따라서 cache key는 prompt string 하나가 아닙니다.

11. Cache Identity에 들어갈 것

최소 identity 예시:

model weights revision
tokenizer revision + chat template
adapter / LoRA identity
token IDs and exact order
position IDs / RoPE scaling policy
attention mask and sliding-window policy
KV dtype, quantization scales, layout version
tensor/pipeline parallel partition
multimodal encoder state identity
tenant or sharing scope

Serving engine·kernel upgrade로 KV layout이 바뀌면 old entry를 invalidation하거나 version namespace를 바꿉니다.

12. Text Hash가 아니라 Token Block Hash

Prefix lookup은 보통 block 단위 token ID와 이전 prefix hash를 chain으로 묶습니다.

h0 = H(namespace, token_ids[0:S])
h1 = H(h0, token_ids[S:2S])
h2 = H(h1, token_ids[2S:3S])

Hash는 lookup index이지 무조건적인 equality proof로 취급하지 않습니다. 충돌 위험에 맞춰 충분한 digest를 쓰고, 보안 경계가 중요하면 token·metadata verification을 추가합니다.

13. Partial Block의 처리

두 prompt가 30 token까지 같고 block size가 16이면 full block 1개는 안전하게 공유할 수 있습니다. 두 번째 block의 14 token도 engine에 따라 prefix node로 관리할 수 있지만 append·copy-on-write가 복잡해집니다.

단순한 구현은 full block만 reusable cache entry로 승격합니다.

matched 30 tokens
reusable full blocks = floor(30 / 16) = 1
remaining 14 tokens = recompute or special partial-block path

실제 engine의 partial-hit 규칙을 metric에 명시합니다.

14. Reference Count가 Ownership을 지킨다

Physical block P7을 cache entry와 요청 A·B가 함께 참조할 수 있습니다.

P7 refcount = 3
  1 cache residency reference
  1 request A
  1 request B

요청 A가 끝나면 3→2로 줄 뿐 free하면 안 됩니다. Cache entry가 eviction되고 B도 끝나 0이 된 뒤 free pool로 반환합니다.

refcount > 0, pinned, in-flight DMA, current kernel에서 사용하는 block은 victim으로 고르면 안 됩니다.

15. Copy-on-Write가 필요한 Branch

Shared prefix의 마지막 block에 빈 slot이 있고 A와 B가 서로 다른 suffix를 append하면 같은 physical block을 수정할 수 없습니다.

shared P7: [prefix tokens ........ free]
                        ├─ A wants suffix x
                        └─ B wants suffix y

한 branch가 쓰기 전에 block을 복사해 private block으로 바꿉니다.

A table: [..., P7] → [..., P21]  # copy prefix slots, append x
B table: [..., P7]               # unchanged shared block

Full shared block 뒤에 새 block을 붙이는 경우에는 기존 block을 수정하지 않으므로 copy가 필요 없습니다.

16. Radix Tree가 Prefix를 표현한다

SGLang의 RadixAttention은 token sequence의 공통 prefix를 radix tree로 관리하고 KV를 자동 재사용합니다.

[system]
   └─ [tool schema]
        ├─ [user A] ─ [assistant A]
        ├─ [user B] ─ [assistant B]
        └─ [shared few-shot] ─ [user C]

Tree edge는 token 구간을, node는 해당 prefix의 KV block references와 cache metadata를 가질 수 있습니다. Longest-prefix lookup 뒤 unmatched suffix만 prefill합니다.

17. Prompt 순서가 Hit를 결정한다

동일한 구성 요소라도 자주 변하는 항목이 앞에 오면 공통 prefix가 짧아집니다.

bad for reuse:
[request id][timestamp][stable system][stable tools][user]

better:
[stable system][stable tools][stable few-shot][request-specific user]

하지만 semantic·security 요구를 깨면서 cache를 위해 prompt를 재배열하면 안 됩니다. Stable prefix 안의 현재 날짜나 nonce도 매 요청 token이 달라져 hit를 끊을 수 있습니다.

18. RAG Document는 보통 Prefix가 아니다

RAG prompt가 다음과 같다면:

[system][query][retrieved doc A][retrieved doc B][instruction]

Doc A를 다른 query 뒤에 붙였을 때 그 KV는 달라집니다. 해당 position의 hidden state는 preceding query와 문맥에 의존하므로 “같은 document text”만으로 KV를 그대로 재사용할 수 없습니다.

Exact prefix cache를 활용하려면 공통 부분이 실제 앞쪽 token prefix여야 합니다. CacheBlend 같은 연구는 RAG의 여러 precomputed chunk KV를 부분 recomputation으로 결합하는 별도 기법을 다루며, 단순 exact prefix hit와 같은 것으로 취급하면 안 됩니다.

19. Cache Hit의 세 단계

Lookup Hit

Index에서 같은 prefix key를 찾았습니다.

Resident Hit

필요 KV가 GPU HBM에 있어 즉시 참조할 수 있습니다.

Useful Hit

Queue·load·transfer까지 포함해 recompute보다 실제 TTFT를 줄였습니다.

CPU·SSD에서 entry를 찾았어도 loading이 prefill보다 느리면 lookup hit는 성능 이득이 아닙니다. hit request % 하나만 보고하지 않습니다.

20. 두 가지 “KV Eviction”을 구분한다

Reusable Prefix Entry Eviction

사용하지 않는 cached prefix를 GPU에서 제거합니다. 다음 요청은 다시 prefill하거나 lower tier에서 load합니다. Exact recompute라면 품질은 바뀌지 않고 latency만 달라집니다.

Active Context Token Eviction

진행 중 요청의 과거 token KV 일부를 버리고 attention에서 보지 않게 합니다. Sliding window, sparse KV, 중요도 기반 eviction이 여기에 해당합니다. Model computation이 달라져 품질 평가가 필요합니다.

이 글의 기본 eviction policy는 첫 번째, 즉 serving cache lifecycle을 뜻합니다. Lossy KV compression·token dropping은 별도 quality gate를 둡니다.

21. LRU가 좋은 Baseline인 이유

Least Recently Used는 단순하고 O(1)에 가깝게 구현할 수 있으며 temporal locality가 있는 workload에서 잘 작동합니다.

하지만 다음 두 entry를 같은 recency로만 비교하면 부족합니다.

entry A: 128 tokens · frequently reused · cheap recompute
entry B: 32K tokens · next Agent step soon · expensive recompute

LRU는 size, saved compute, reuse schedule, load cost를 모릅니다.

22. Cost-aware Eviction Score

Eviction victim을 다음처럼 생각할 수 있습니다.

$$ value(e)=\frac{P(reuse\ within\ horizon)\times saved\ prefill\ time}{resident\ bytes+reload\ cost} $$

낮은 value부터 내리는 방식입니다. 실제 score에는 다음을 넣습니다.

  • Last access와 access frequency
  • Reused token length
  • Model별 measured prefill cost
  • Entry byte와 shared descendant 수
  • Next workflow step까지 예상 시간
  • CPU·SSD load bandwidth와 queue
  • Tenant quota와 fairness debt
  • Pin·lease·deadline

정확한 확률 model이 없어도 LRU와 size-aware·cost-aware heuristic을 trace replay로 비교할 수 있습니다.

23. Tree Eviction은 Node 하나로 끝나지 않는다

Radix tree의 상위 prefix는 많은 descendant가 공유할 수 있습니다. Parent block을 evict하면 child entry가 독립적으로 유효한지, 함께 제거해야 하는지 representation에 따라 달라집니다.

eviction unit choices
  → individual physical block
  → radix node / token span
  → entire prefix object

Fine-grained unit은 공간 활용은 좋지만 metadata와 transfer가 조각납니다. Coarse unit은 bulk I/O가 좋지만 유용한 block까지 내릴 수 있습니다.

24. Active, Pinned, Evictable을 분리한다

ACTIVE
  current request or in-flight kernel references

PINNED
  deployment warm prefix, SLA tenant, near-future Agent step

EVICTABLE
  reusable cache residency only, refcount-safe

Pinning은 무제한 권리가 아닙니다. Byte quota와 lease expiry가 없으면 hot prefix가 GPU 전체를 잠글 수 있습니다.

25. GPU·CPU·SSD Hierarchy

모든 reusable KV를 HBM에 둘 수 없으면 tier를 둡니다.

GPU HBM  → lowest access latency, scarce
CPU DRAM → larger, PCIe / interconnect transfer
NVMe SSD → much larger, high and variable latency
recompute → no stored byte, consumes GPU compute

Entry를 lower tier로 내릴지 완전히 버릴지는 transfer와 recompute를 비교합니다.

$$ T_{load}=queue_{io}+\frac{bytes}{effective\ bandwidth}+deserialize $$

$$ T_{recompute}=queue_{gpu}+prefill(tokens,shape) $$

T_load < T_recompute만으로 끝나지 않습니다. Load가 active decode의 bandwidth를 방해하는지도 봅니다.

26. Layout과 Transfer Granularity

GPU attention kernel에 좋은 paged layout이 CPU·SSD bulk transfer에는 나쁠 수 있습니다. 작은 fragmented block을 수천 번 보내면 theoretical PCIe·NVMe bandwidth를 사용하지 못합니다.

LMCache는 engine 밖의 KV layer에서 batched movement, compute/I/O pipeline, control API를 다루고, Strata는 GPU·host layout을 분리한 큰 transfer와 cache-loading-aware scheduling을 제시합니다.

핵심은 cache tier를 추가했다고 자동으로 빨라지는 것이 아니라 유효 transfer 크기와 overlap을 측정하는 것입니다.

27. Prefetch와 Delay Hit

Agent graph에서 다음 model step을 예측할 수 있다면 CPU의 prefix를 미리 GPU로 올릴 수 있습니다.

tool A running
  → next likely agent B prefix identified
  → async KV prefetch
  → tool result arrives
  → B starts without load stall

KVFlow는 Agent Step Graph와 steps-to-execution을 eviction·prefetch에 활용하는 방향을 제시합니다. 반면 여러 요청이 같은 cold prefix를 동시에 요구하면 첫 load가 끝나기 전에 중복 load·recompute하는 “delay hit”를 합쳐야 합니다.

28. Cache Invalidation

다음 변경은 namespace를 바꾸거나 entry를 폐기해야 합니다.

  • Model weight·quantization revision
  • Tokenizer vocab·normalizer·chat template
  • System prompt·tool schema revision
  • LoRA adapter revision
  • RoPE scaling·max context policy
  • KV dtype·block layout·parallel topology
  • Multimodal preprocessing revision
  • Security scope·retention policy 변경

Deployment version을 cache key에 넣고 blue/green worker 사이에서 KV compatibility를 명시합니다. “같은 model 이름”만으로 공유하지 않습니다.

29. Multi-tenant Security

KV tensor를 직접 읽을 수 없더라도 cache hit latency가 다른 tenant의 prefix 존재를 드러낼 수 있고, 잘못된 key나 refcount bug는 data leakage가 됩니다.

안전한 기본값:

  • Tenant 또는 trust domain별 namespace
  • Cross-tenant sharing은 명시적 public prefix만 허용
  • Cache key에 authorization scope 포함
  • Entry byte·age·retention quota
  • Secure deletion 또는 overwrite 요구 검토
  • Lookup·hit detail을 외부 응답에 노출하지 않음
  • Hash collision·stale pointer·use-after-free test
  • Audit log에는 prompt 원문 대신 scoped digest 사용

성능을 위해 security boundary를 암묵적으로 넓히지 않습니다.

30. RAG Agent에 맞는 Cache Policy

Stable Prefix

System instruction, 공통 tool schema, 고정 few-shot을 가능한 한 안정된 앞부분에 둡니다.

Retrieved Evidence

Query별 document는 exact prefix reuse가 제한적임을 인정합니다. Document KV cache를 쓰려면 CacheBlend류의 별도 correctness·quality 검증이 필요합니다.

Multi-turn Session

대화 prefix를 turn 사이에 재사용하면 prefill을 줄일 수 있습니다. Conversation compaction이나 message edit가 일어난 지점 뒤의 KV는 invalid합니다.

Tool Wait

짧은 wait는 active KV 유지, 긴 wait는 tier 이동 또는 recompute를 선택합니다. Next-step probability와 wait duration을 eviction score에 넣습니다.

Parallel Branch

Plan 후보들은 공통 prefix block을 refcount로 공유하고 suffix만 copy-on-write합니다. Branch 취소 시 private block을 즉시 반환합니다.

31. Scheduler와 Cache의 계약

Scheduler가 알아야 할 정보:

matched_prefix_tokens
resident_tier and load_eta
new_physical_blocks_required
pinned / active references
copy_on_write_blocks
future_output_reservation
eviction_or_preemption_cost

Cache manager가 free block 수만 주면 scheduler는 곧 load될 prefix나 COW peak를 놓칩니다. 반대로 cache가 독자적으로 eviction하면 imminent Agent step을 내릴 수 있습니다. Shared control plane 또는 명시적 API가 필요합니다.

32. Metric은 Token과 Byte로 본다

Capacity

  • GPU·CPU·SSD resident KV byte
  • Free·used·pinned·active physical block
  • Internal fragmentation token
  • Block table·radix metadata byte

Reuse

  • Lookup·resident·useful hit rate
  • Matched·reused token 수
  • Avoided prefill token·GPU ms
  • Prefix length histogram
  • Tenant·prompt class별 hit

Lifecycle

  • Allocation·free·COW block/s
  • Refcount error와 delayed free
  • Eviction·offload·reload·recompute byte
  • Transfer queue·bandwidth·p95 latency
  • Prefetch usefulness와 late·wasted prefetch

Outcome

  • Hit·miss별 TTFT
  • Cache가 없을 때 대비 goodput
  • Decode ITL interference
  • Cache manager CPU overhead

33. Failure Injection

  1. Block boundary 직전·직후 prompt를 생성합니다.
  2. 두 branch가 shared partial block 뒤에 동시에 append합니다.
  3. Request cancellation과 eviction을 같은 순간에 발생시킵니다.
  4. Refcount가 있는 block을 victim 후보에 넣고 방어를 확인합니다.
  5. Hash collision 또는 corrupted metadata를 주입합니다.
  6. Model·adapter·tokenizer revision을 중간에 교체합니다.
  7. CPU·SSD load를 느리게 하고 timeout·retry를 검증합니다.
  8. 같은 cold prefix 요청을 burst로 보내 duplicate load를 확인합니다.
  9. Tenant scope가 다른 같은 token prefix를 보냅니다.
  10. Worker crash·restart 뒤 stale cache pointer가 없는지 확인합니다.
  11. Prefix hit와 full recompute의 logits·greedy token을 비교합니다.
  12. Long-running churn에서 leaked block과 fragmentation을 측정합니다.

34. 최소 구현 순서

  1. Token당 KV byte와 target block size를 계산합니다.
  2. Physical block pool, free list, per-request block table을 구현합니다.
  3. Append·finish·cancel에서 allocation/free invariant를 test합니다.
  4. Refcount와 active/pinned/evictable state를 추가합니다.
  5. Shared full-block prefix와 longest-prefix lookup을 구현합니다.
  6. Partial block branch에 copy-on-write를 구현합니다.
  7. Model·tokenizer·adapter·layout을 포함한 namespace를 정의합니다.
  8. LRU를 baseline으로 넣고 reused token·TTFT를 계측합니다.
  9. Size·cost·aging을 반영한 eviction을 trace replay로 비교합니다.
  10. CPU offload의 transfer/recompute break-even을 측정합니다.
  11. Tenant isolation과 invalidation·failure injection을 통과시킵니다.
  12. Scheduler에 cache hit, load ETA, KV reservation API를 연결합니다.

실전 체크리스트

  • Logical token order와 physical KV block을 분리했다.
  • Block table address translation을 boundary별로 test했다.
  • Last partial block의 internal fragmentation을 측정한다.
  • Block size를 metadata·kernel·transfer까지 포함해 선택했다.
  • Paging과 prefix caching을 별도 기능·metric으로 본다.
  • Prefix cache key가 text가 아니라 token·execution identity를 포함한다.
  • Model·tokenizer·adapter·RoPE·KV layout revision이 namespace에 있다.
  • Full·partial block hit 규칙이 명시돼 있다.
  • Shared block의 reference count가 request와 cache residency를 구분한다.
  • Shared partial block append에 copy-on-write가 있다.
  • Active·pinned block은 eviction할 수 없다.
  • Reusable prefix eviction과 lossy active-token eviction을 구분했다.
  • LRU를 saved prefill time·size·next use와 비교했다.
  • Lookup·resident·useful hit를 구분한다.
  • CPU·SSD load와 recompute break-even을 측정했다.
  • Fragmented small transfer의 실효 bandwidth를 측정했다.
  • Delay hit와 duplicate load를 합친다.
  • Tenant·authorization scope가 cache key에 있다.
  • Hit·miss 결과의 logits·token correctness를 검증했다.
  • Cancellation·crash·revision change에서 block leak이 없다.

스스로 확인하기

Q1. Paged KV가 prefix caching과 같은 기능인가?

아닙니다. Paged KV는 한 request의 logical KV를 on-demand physical block에 배치하는 allocator입니다. Prefix caching은 동일한 과거 token prefix의 KV를 요청 사이에서 재사용하는 cache policy입니다.

Q2. Paged KV를 쓰면 fragmentation이 0이 되는가?

아닙니다. 큰 연속 예약과 external fragmentation을 크게 줄이지만 sequence의 마지막 partial block에는 최대 block_size-1 token slot이 남을 수 있고 metadata도 필요합니다.

Q3. 같은 document text의 KV를 어떤 query 뒤에도 재사용할 수 있는가?

아닙니다. Causal model의 KV는 preceding token과 position에 의존합니다. Exact prefix가 아니라 중간 chunk를 재사용하려면 partial recomputation 같은 별도 기법과 품질 검증이 필요합니다.

Q4. Prefix entry를 LRU eviction하면 model 품질이 떨어지는가?

Exact entry를 버리고 나중에 같은 prefix를 정상 prefill한다면 결과는 같고 latency·compute만 늘어납니다. 진행 중 context token을 attention에서 제거하는 lossy eviction은 다른 문제이며 품질 평가가 필요합니다.

Q5. Cache hit request 비율만 보면 안 되는 이유는 무엇인가?

10-token hit와 30K-token hit의 절약량이 다르고, lower tier load가 recompute보다 느릴 수도 있기 때문입니다. Reused token, avoided GPU ms, hit·miss TTFT와 goodput을 함께 봐야 합니다.

다음 글

이번 글은 과거 token의 KV를 저장하고 재사용하는 방법을 다뤘습니다. 다음 글 Speculative Decoding: Draft·Verify·Acceptance와 Serving 설계에서는 미래 token 후보를 작은 model이 먼저 제안하고 target model이 병렬 검증해 decode step 수를 줄이는 방법을 살펴봅니다.

참고문헌

검증 메모 — 개념과 문헌은 2026년 7월 16일 확인했습니다. Block size, layout, prefix hash, eviction과 offload API는 engine revision마다 다릅니다. 본문의 cache key와 score는 설계 예시이며 target model·tokenizer·adapter·parallel topology로 correctness와 보안을 검증하고 실제 trace에서 reused token·TTFT·goodput을 측정해야 합니다. 2025년 KVFlow·LMCache는 preprint로 구분했습니다.