KV cache vs prompt cache: khác nhau thế nào?
KV cache dùng RAM hoặc VRAM cho từng request và có thể làm model không load được. Prompt cache chỉ giảm billing, latency khi prefix ổn định được hit.
KV cache và prompt cache: câu trả lời ngắn
KV cache và prompt cache của provider có chung một từ, nhưng gần như không có điểm gì khác. KV cache là bộ nhớ làm việc của từng request. Nó nằm trong RAM hoặc VRAM trên server của bạn trong toàn bộ thời gian xử lý một request, đồng thời tăng theo độ dài context và số request chạy đồng thời. Prompt caching của provider là tính năng về billing và latency. Provider lưu một prefix ổn định trong prompt trên server của họ, sau đó tính phí với mức chiết khấu khi bạn gửi lại prefix đó.
Một loại là bộ nhớ bạn mua dưới dạng phần cứng. Loại kia là bộ nhớ do bên khác lưu giữ và tính phí thuê.
Sự khác biệt trên thực tế quan trọng hơn định nghĩa. Bạn có thể hết KV cache. Khi đó, model không load được hoặc request bị từ chối. Bạn không thể hết prompt cache. Bạn chỉ có thể không hit được cache, rồi vẫn phải trả đầy đủ mà không có cảnh báo rõ ràng.
Nội dung của KV cache và lý do nó tồn tại
Khi transformer sinh token số 500, nó phải attention đến toàn bộ 499 token trước đó. Với mỗi token, mỗi layer cần một key vector và một value vector. Nếu phải tính lại toàn bộ các vector này cho mỗi token mới, thời gian sinh sẽ tăng theo bình phương độ dài chuỗi. Vì vậy runtime giữ lại chúng. Vùng lưu trữ đó là KV cache (key/value cache).
KV cache là state riêng của từng request vì nó được xây dựng từ chính chuỗi token của request đó. Hai người dùng gửi các prompt khác nhau không thể dùng chung cache này, trừ khi runtime có prefix caching. Đây là một tính năng riêng sẽ được mô tả ở phần sau.
Quá trình serving có 2 phase. Prefill đọc toàn bộ prompt và điền vào cache; phase này bị giới hạn bởi năng lực tính toán. Decode sinh từng token một và nối token đó vào cache; phase này bị giới hạn bởi băng thông bộ nhớ. Đó là lý do tốc độ xử lý prompt và tốc độ sinh token được báo cáo khác nhau khi bạn đo số token mỗi giây trên máy của mình.
Cache KV sử dụng bao nhiêu bộ nhớ?
Không cần tìm bảng thông số của vendor. Kích thước này có thể tính lại bằng công thức cho mọi model:
bytes per token = 2 * layers * kv_heads * head_dim * bytes per elementSố 2 đại diện cho key và value. Mọi con số khác đều lấy từ config.json của model, được công bố trên trang Hugging Face của model.
Lấy Llama 3.1 8B làm ví dụ. Cấu hình của model ghi num_hidden_layers là 32 và num_key_value_heads là 8. hidden_size bằng 4096, chia cho 32 attention head nên kích thước mỗi head là 128. Với f16, mỗi phần tử chiếm 2 byte:
2 * 32 * 8 * 128 * 2 = 131072 bytes = 128 KiB per tokenNhân kết quả này với context bạn yêu cầu, sau đó nhân tiếp với số request chạy đồng thời.
The data behind this chart
[
{
"label": "2k context",
"one_request_gib": 0.25,
"four_requests_gib": 1
},
{
"label": "8k context",
"one_request_gib": 1,
"four_requests_gib": 4
},
{
"label": "32k context",
"one_request_gib": 4,
"four_requests_gib": 16
},
{
"label": "128k context",
"one_request_gib": 16,
"four_requests_gib": 64
}
]Với context 8k, cache là 1 GiB cho một request. Với 32k, cache là 4 GiB, tương đương với mức sử dụng của chính các weight 4-bit. Ở context tối đa 128k của model, cache là 16 GiB cho một request và 64 GiB nếu 4 request đều dùng đầy context. Các weight không thay đổi. Chỉ có cache tăng lên.
Grouped query attention (GQA) có vai trò lớn trong con số này. Llama 3.1 8B có 8 key/value head phục vụ 32 query head, nên 4 query head dùng chung một cặp key/value được lưu. Một model có num_key_value_heads bằng num_attention_heads sẽ sử dụng lượng cache gấp 4 lần ở cùng số parameter. Hãy kiểm tra trường đó trước khi cho rằng 2 model 8B có chi phí phục vụ như nhau.
Vì sao model chạy ở 2k lại từ chối load ở 32k
Runtime reserve KV cache khi load model. Dung lượng cache được tính theo context length bạn cấu hình, không phải prompt thực tế bạn gửi. context window mặc định của Ollama là 4096 token. Tăng lên 32k nghĩa là bạn yêu cầu cấp phát thêm 4 GiB trước khi có một token nào được gửi.
OLLAMA_CONTEXT_LENGTH=32768 ollama serveĐặt cùng tùy chọn này cho từng session từ interactive prompt:
ollama run llama3.1:8b
/set parameter num_ctx 32768Lỗi hiển thị khác nhau trên mỗi stack. vLLM kiểm tra phép tính khi startup rồi từ chối chạy:
ValueError: The model's max seq len (131072) is larger than the maximum number of tokens that can be stored in KV cache (78336). Try increasing `gpu_memory_utilization` or decreasing `max_model_len` when initializing the engine.Trên VPS chỉ dùng CPU, không có bước kiểm tra như vậy vì đây là cấp phát system RAM thông thường. Kernel's out-of-memory killer sẽ dừng process và ghi bằng chứng vào kernel ring buffer:
dmesg -T | grep -i "killed process"Nếu thấy một dòng có tên serving process của bạn, nghĩa là máy đã cần nhiều memory hơn mức đang có. Cách khắc phục là giảm context, không phải tăng swap file: KV cache được page xuống disk sẽ phải đọc ở mỗi token được generate, khiến tốc độ generation chậm đến mức không thể sử dụng. Cách chọn giá trị hợp lý được trình bày trong hướng dẫn của chúng tôi về num_ctx và context length trong Ollama.
Concurrency ảnh hưởng đến con số như thế nào
Mỗi request đang xử lý đều có KV cache riêng. Đây là điểm mà hầu hết kế hoạch năng lực bỏ sót. Bốn người dùng, mỗi người giữ context 32k, cần tổng cộng 16 GiB, chưa tính weights.
Các runtime xử lý việc này khác nhau. Ollama và llama.cpp dành sẵn context bạn yêu cầu khi model được load, vì vậy bộ nhớ được cấp phát dù không có ai sử dụng. vLLM chia pool thành các block có kích thước cố định và cấp chúng khi từng request tăng lên, nên request 500 token chỉ giữ phần tương ứng với 500 token. Dù theo cách nào, pool vẫn có giới hạn. Khi pool đầy, request mới sẽ xếp hàng thay vì được chạy. Ảnh hưởng của việc xếp hàng đó đến thời gian phản hồi được phân tích trong LLM tự host có thể phục vụ bao nhiêu người dùng đồng thời.
Four ways to make the KV cache smaller
- Lower the context length. This is the biggest lever and usually the cheapest. Most chat workloads never come close to 32k.
- Quantise the cache itself. Ollama's
OLLAMA_KV_CACHE_TYPEdefaults tof16and acceptsq8_0, which uses about half the memory, andq4_0, which uses about a quarter. The llama.cpp equivalents are-ctk q8_0and-ctv q8_0. - Pick a model with fewer key/value heads or fewer layers. Read
config.jsonbefore you download 40 GB of weights. - Serve fewer requests at once and queue the rest.
At q4_0 the Llama 3.1 8B figure drops from 128 KiB per token to roughly 32 KiB, so 32k of context costs about 1 GiB instead of 4 GiB. That saving is not free. The keys and values are stored with less precision, so compare output on your own prompts before you keep it.
Provider prompt caching thực sự mang lại gì
Provider prompt caching là một sản phẩm khác, với đơn vị tính khác. Bạn đánh dấu một prefix ổn định, provider lưu prefix đó, rồi những lần gọi sau lặp lại chính xác prefix này sẽ được tính với mức giá input thấp hơn thay vì giá input đầy đủ.
Các hệ số do Anthropic công bố, tính đến tháng 8 năm 2026: ghi cache 5 phút có chi phí bằng 1.25 lần giá token input cơ bản. Ghi cache 1 giờ có chi phí bằng 2 lần, còn đọc cache có chi phí bằng 0.1 lần. Đặt một system prompt dài 20,000 token vào phép tính này thì lợi ích trở nên rõ ràng.
The data behind this chart
[
{
"label": "No caching, every call",
"billed_token_equivalents": "20,000"
},
{
"label": "First call, 5 minute cache write",
"billed_token_equivalents": "25,000"
},
{
"label": "First call, 1 hour cache write",
"billed_token_equivalents": "40,000"
},
{
"label": "Every later call, cache hit",
"billed_token_equivalents": "2,000"
}
]Hãy xem đây là phép tính số học. Phần chênh lệch khi ghi cache 5 phút tương đương 5,000 token ở lần gọi đầu tiên: 25,000 so với 20,000 nếu gửi prefix mà không cache. Mỗi lần gọi tiếp theo trong thời gian hiệu lực được tính 2,000 thay vì 20,000, tiết kiệm 18,000 token. Vì vậy, cache 5 phút bắt đầu có lợi từ lần gọi thứ hai.
Cache 1 giờ là một lựa chọn khác. Lần ghi cache được tính 40,000, tức cao hơn 20,000 token tương đương, nên cần có hai lần đọc cache trong một giờ thì mới có lợi. Đây là vấn đề về mô hình lưu lượng của bạn, không phải về model. Toàn bộ phép tính, bao gồm cách chọn thời gian hiệu lực, có trong phép tính điểm hòa vốn cho Claude prompt caching.
Hai chi tiết quyết định việc bạn có đọc được cache hay không. Thứ nhất, prefix ngắn hơn độ dài tối thiểu của model sẽ không được cache mà không có thông báo: tính đến tháng 8 năm 2026, độ dài tối thiểu được công bố là 512 token cho Claude Opus 5 và 1,024 token cho Claude Sonnet 5; request ngắn hơn sẽ được xử lý bình thường và không trả về lỗi. Thứ hai, thời gian hiệu lực được tính từ lúc bắt đầu request ghi hoặc đọc entry, và mỗi lần đọc đều gia hạn entry mà không phát sinh thêm chi phí. Vì vậy, một endpoint có lưu lượng cao có thể duy trì cache 5 phút vô thời hạn. Một endpoint chỉ được gọi mỗi mười phút sẽ phải trả phần chênh lệch khi ghi cache trong mọi lần gọi và không bao giờ thu được lợi ích.
Hãy kiểm tra response thay vì mặc định cho rằng cache hoạt động. Object usage báo cáo cache_creation_input_tokens và cache_read_input_tokens. Nếu số lần đọc luôn bằng 0 trong mọi lần gọi, bạn đang trả tiền để ghi cache nhưng không nhận lại được gì.
Khi hai loại cache giao nhau
Một system prompt dài là nơi hai loại cache này gặp nhau, và nó tính phí ở cả hai phía cùng lúc.
Ở local, system prompt 20,000 token chiếm khoảng 2.4 GiB KV cache trên server Llama 3.1 8B chạy f16. Phần cache này được cấp riêng cho từng request đồng thời có chứa prompt đó. Ở remote, cùng prefix đó chỉ tốn một lần ghi cache, sau đó mỗi lần gọi tiếp theo chỉ tính 0.1 lần input. Chi phí local tăng theo số người dùng. Chi phí remote tăng theo lưu lượng và được đặt lại trong thời gian không có request.
Có một tính năng local trông giống provider prompt caching và thường bị nhầm với nó: prefix caching. Tài liệu vLLM mô tả automatic prefix caching là việc cache “KV cache của các query hiện có, để query mới có thể dùng lại trực tiếp KV cache nếu có cùng prefix với một query hiện có”. Server llama.cpp mặc định giữ prompt cache theo từng slot, còn --cache-reuse N đặt kích thước chunk nhỏ nhất mà server sẽ thử dùng lại.
Prefix caching giúp giảm prefill compute. System prompt 20,000 token của bạn được xử lý một lần thay vì trong mọi request, nhờ đó giảm đáng kể time to first token. Trong vLLM, các block dùng chung được tái sử dụng thay vì nhân bản, nên mức sử dụng memory cũng giảm. Tuy nhiên, tính năng này không làm giảm lượng cache cần giữ cho các token hiện đang hoạt động. Việc giữ weights trong memory giữa các request là một cơ chế liên quan nhưng tách biệt, được trình bày trong giữ model Ollama đã load giữa các request.
Cần đo gì trên máy của bạn
Nạp model với context mục tiêu, rồi đọc số liệu thực tế thay vì chỉ tin vào con số ước tính.
ollama ps
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
free -gollama ps liệt kê model đã nạp cùng với dung lượng và cho biết model đang chạy trên GPU hay CPU. Nếu một model mà bạn dự kiến sẽ nằm hoàn toàn trên GPU lại báo có phần chạy trên CPU, nghĩa là KV cache đã đẩy một phần model ra ngoài GPU và tốc độ sinh sẽ giảm tương ứng. nvidia-smi cung cấp dung lượng VRAM thực tế, còn free -g thực hiện chức năng tương tự trên VPS chỉ dùng CPU. Tăng context theo từng bước, nạp lại model và theo dõi con số thay đổi. Kết quả tính toán và con số được báo cáo phải gần bằng nhau. Nếu không, phần chênh lệch thường là các compute buffer do runtime tự cấp phát, không phải lỗi trong công thức.
Nếu các con số này khiến bạn phải dùng phần cứng mà bạn không muốn thuê, phần so sánh với việc trả tiền theo token được trình bày trong GPU VPS so với token API.
FAQ
KV cache có phải là prompt caching không?
Không. KV cache là bộ nhớ theo từng request bên trong tiến trình serving, lưu các vector key và value cho mọi token trong context hiện tại. Nó nằm trong RAM hoặc VRAM của bạn và được giải phóng khi request kết thúc. Prompt caching của provider là một tính năng tính phí, lưu prefix ổn định của prompt trên hạ tầng của provider và tính mức phí thấp hơn khi bạn gửi lại prefix đó. Hết KV cache sẽ khiến model không thể load. Không có prompt cache chỉ làm tăng hóa đơn và thời gian đến token đầu tiên.
Vì sao model load được ở context 2k nhưng lại fail ở 32k?
Vì runtime cấp phát toàn bộ KV cache ngay khi load, với kích thước dựa trên độ dài context bạn cấu hình thay vì prompt bạn gửi. Với Llama 3.1 8B ở f16, cache cần 128 KiB cho mỗi token, nên context 2k cần 0.25 GiB và 32k cần 4 GiB. Weights vừa đủ trong cả hai trường hợp. Phần bị fail là việc reservation. vLLM báo lỗi này dưới dạng ValueError, cho biết số token tối đa mà nó có thể lưu, đồng thời đề xuất tăng gpu_memory_utilization hoặc giảm max_model_len. Trên máy chỉ có CPU, kernel out-of-memory killer sẽ kill tiến trình thay vào đó. Bạn có thể xác nhận bằng dmesg -T | grep -i "killed process".
Làm thế nào để tính kích thước KV cache cho model?
Nhân 2 với số layer, số key/value head, head dimension và số byte trên mỗi phần tử. Kết quả là số byte trên mỗi token. Sau đó nhân với context length và số request chạy đồng thời. Đọc số layer và head từ config.json của model. Dùng 2 byte cho mỗi phần tử với f16 hoặc bf16. Cache q8_0 cần khoảng một nửa dung lượng đó, còn q4_0 cần khoảng một phần tư.
Prompt caching có giảm lượng memory mà server của tôi cần không?
Prompt caching của provider không làm gì cho phần cứng của bạn, vì dữ liệu được lưu ở phía provider. Cơ chế tương đương ở local là prefix caching, được cả vLLM và llama.cpp server hỗ trợ. Nó tái sử dụng các vector key và value đã tính cho một prefix dùng chung, nhờ đó giảm prefill compute và rút ngắn thời gian đến token đầu tiên. Trong vLLM, các block dùng chung được tái sử dụng thay vì nhân bản, nên memory cũng giảm. Cả hai tính năng đều không làm giảm cache cần cho các token đang được xử lý, nên context và concurrency vẫn quyết định mức tối thiểu.
Có đáng cache một prompt mà tôi chỉ gửi một lần không?
Không. Ghi cache có chi phí cao hơn input thông thường: ở mức 1.25 lần giá cơ bản cho tùy chọn 5 phút tính đến tháng 8 năm 2026. Vì vậy, prefix không được gửi lại trong khoảng thời gian này sẽ gây lỗ trực tiếp. Caching có lợi khi cùng một prefix được lặp lại, chẳng hạn system prompt dài hoặc một tài liệu mà bạn sẽ đặt nhiều câu hỏi. Kiểm tra cache_read_input_tokens trong API response để xác nhận bạn đang nhận được cache hit thay vì phải trả phí cho thao tác ghi.