KV cache بمقابلہ prompt cache: اصل فرق کیا ہے؟
KV cache ہر request پر server کی RAM یا VRAM استعمال کرتی ہے اور ختم ہو کر model load روک سکتی ہے۔ prompt cache صرف provider کی لاگت اور latency کم کرتی ہے۔
KV cache بمقابلہ prompt cache: مختصر جواب
KV cache اور provider کے prompt cache میں ایک لفظ مشترک ہے، تقریباً باقی کچھ نہیں۔ KV cache ہر request کی عارضی working memory ہے۔ یہ ایک request کی پوری مدت تک آپ کے server کی RAM یا VRAM میں رہتی ہے، اور context length اور بیک وقت چلنے والی requests کی تعداد کے ساتھ بڑھتی ہے۔ Provider کا prompt caching billing اور latency کی سہولت ہے۔ آپ کے prompt کا ایک مستقل prefix provider کے servers پر محفوظ کیا جاتا ہے، پھر اسے دوبارہ بھیجنے پر کم نرخ وصول کیا جاتا ہے۔
ایک ایسی memory ہے جس کے لیے آپ hardware خریدتے ہیں۔ دوسری memory کوئی اور فریق اپنے پاس رکھتا ہے اور آپ سے اس کا کرایہ وصول کرتا ہے۔
عملی فرق تعریف سے زیادہ اہم ہے۔ KV cache ختم ہو سکتی ہے، اور ایسا ہونے پر model load ہونے سے انکار کر دیتا ہے یا request مسترد ہو جاتی ہے۔ Prompt cache ختم نہیں ہو سکتی۔ صرف یہ ہو سکتا ہے کہ request اس سے match نہ کرے، اور پھر آپ خاموشی سے پوری قیمت ادا کرتے ہیں۔
KV cache کیا محفوظ کرتا ہے، اور یہ کیوں موجود ہے
Transformer جب token نمبر 500 تیار کرتا ہے تو اسے اپنے سے پہلے موجود تمام 499 tokens پر attention دینی ہوتی ہے۔ ان میں سے ہر token کے لیے ہر layer کو ایک key vector اور ایک value vector درکار ہوتا ہے۔ ہر نئے token کے لیے ان سب کو دوبارہ تیار کرنے سے generation کی لاگت sequence length کے مربع کے ساتھ بڑھتی، اس لیے runtime انہیں محفوظ رکھتا ہے۔ اس محفوظ شدہ ذخیرے کو KV cache (key/value cache) کہتے ہیں۔
یہ ہر request کی الگ state ہوتی ہے، کیونکہ یہ اسی request کی بالکل درست token sequence سے بنتی ہے۔ مختلف prompts بھیجنے والے دو users اسے share نہیں کر سکتے، الا یہ کہ runtime prefix caching استعمال کرے۔ یہ ایک الگ feature ہے جس کی وضاحت آگے کی گئی ہے۔
Serving دو phases میں ہوتی ہے۔ Prefill آپ کے پورے prompt کو پڑھ کر cache بھرتا ہے، اور اس کی حد compute ہوتی ہے۔ Decode ایک وقت میں ایک token تیار کرتا ہے اور اسے cache میں شامل کرتا ہے، اور اس کی حد memory bandwidth ہوتی ہے۔ اسی تقسیم کی وجہ سے prompt processing اور token generation کی رفتار مختلف رپورٹ ہوتی ہے، جب آپ اپنے box پر tokens per second کی پیمائش کرتے ہیں۔
KV cache کتنی memory استعمال کرتا ہے؟
کسی vendor table کو تلاش کرنے کی ضرورت نہیں۔ سائز کا حساب ہے، جسے آپ کسی بھی model کے لیے دوبارہ کر سکتے ہیں:
bytes per token = 2 * layers * kv_heads * head_dim * bytes per element2 کا تعلق key اور value دونوں سے ہے۔ باقی ہر عدد model کے config.json سے آتا ہے، جو model کے Hugging Face صفحے پر شائع ہوتا ہے۔
Llama 3.1 8B کو دیکھیں۔ اس کی config میں num_hidden_layers 32 اور num_key_value_heads 8 درج ہیں۔ 32 attention heads میں تقسیم hidden_size 4096 سے ہر head کی dimension 128 بنتی ہے۔ f16 میں ہر element 2 bytes کا ہوتا ہے:
2 * 32 * 8 * 128 * 2 = 131072 bytes = 128 KiB per tokenاسے مطلوبہ context کے سائز سے ضرب دیں، پھر بیک وقت چلائی جانے والی requests کی تعداد سے ضرب دیں۔
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
}
]8k context پر cache ایک request کے لیے 1 GiB ہے۔ 32k پر یہ 4 GiB ہے، جو خود 4-bit weights کے تقریباً اسی range میں ہے۔ model کے مکمل 128k context پر ایک request کے لیے یہ 16 GiB ہے، اور اگر چار requests میں سے ہر ایک پورا context بھر دے تو 64 GiB ہے۔ weights میں کوئی تبدیلی نہیں ہوئی۔ صرف cache کا سائز بدلا ہے۔
Grouped query attention (GQA) اس حساب میں اہم کردار ادا کرتی ہے۔ Llama 3.1 8B میں 8 key/value heads، 32 query heads کو service دیتے ہیں، اس لیے ہر چار query heads ایک ہی stored key/value pair شیئر کرتے ہیں۔ جس model کا num_key_value_heads، num_attention_heads کے برابر ہو، وہ اسی parameter count پر چار گنا cache استعمال کرتا ہے۔ یہ فرض کرنے سے پہلے کہ دو 8B models کو serve کرنے کی لاگت یکساں ہے، اس field کی تصدیق کریں۔
32k پر چلنے والا ماڈل load ہونے سے کیوں انکار کرتا ہے
ماڈل load ہوتے وقت runtime، KV cache کے لیے وہ memory reserve کرتا ہے جو آپ کی configured context length کے مطابق ہوتی ہے، نہ کہ اس prompt کے مطابق جو آپ حقیقت میں بھیجتے ہیں۔ Ollama کی default context window 4096 tokens ہے۔ اسے 32k تک بڑھانے کا مطلب ہے کہ پہلے token کے آنے سے پہلے ہی آپ نے 4 GiB اضافی allocation کی درخواست کر دی ہے۔
OLLAMA_CONTEXT_LENGTH=32768 ollama serveInteractive prompt سے ہر session کے لیے یہی setting یوں مقرر کریں:
ollama run llama3.1:8b
/set parameter num_ctx 32768ہر stack میں failure مختلف دکھائی دیتا ہے۔ vLLM startup کے وقت arithmetic check کرتا ہے اور run ہونے سے انکار کر دیتا ہے:
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.CPU-only VPS پر ایسا check نہیں ہوتا، کیونکہ allocation عام system RAM میں ہوتی ہے۔ اس کے بجائے kernel کا out-of-memory killer process کو terminate کر دیتا ہے، اور اس کے شواہد kernel ring buffer میں چھوڑ دیتا ہے:
dmesg -T | grep -i "killed process"اگر کسی line میں آپ کے serving process کا نام ہو تو اس کا مطلب ہے کہ system نے اپنی دستیاب memory سے زیادہ memory کا وعدہ کیا تھا۔ حل یہ ہے کہ context چھوٹا کریں، نہ کہ swap file بڑی کریں۔ Disk پر paged KV cache ہر generated token کے وقت دوبارہ پڑھی جاتی ہے، اس لیے generation اتنی سست ہو جاتی ہے کہ عملاً ناقابلِ استعمال رہتی ہے۔ مناسب number منتخب کرنے کا طریقہ Ollama میں num_ctx اور context length کے لیے ہماری guide میں بیان کیا گیا ہے۔
تعداد پر concurrency کا اثر
ہر زیرِ تکمیل request اپنی KV cache رکھتی ہے۔ capacity planning میں عموماً یہی بات نظرانداز ہو جاتی ہے۔ 32k context رکھنے والے چار صارفین کو weights کے علاوہ مجموعی طور پر 16 GiB درکار ہوتے ہیں۔
اس معاملے میں runtimes کا رویہ مختلف ہوتا ہے۔ Ollama اور llama.cpp model load ہونے پر آپ کے مقرر کردہ context کے لیے memory reserve کرتے ہیں، اس لیے کوئی اسے استعمال کرے یا نہ کرے، memory commit ہو جاتی ہے۔ vLLM pool کو fixed-size blocks میں تقسیم کرتا ہے اور ہر request کے بڑھنے کے ساتھ blocks فراہم کرتا ہے، اس لیے 500-token request صرف 500 tokens کے برابر جگہ رکھتی ہے۔ دونوں صورتوں میں pool محدود ہوتا ہے۔ جب یہ بھر جائے تو نئی requests چلنے کے بجائے queue میں چلی جاتی ہیں۔ اس queueing سے response times پر کیا اثر پڑتا ہے، اس کی وضاحت self-hosted LLM کتنے concurrent users کو serve کر سکتا ہے میں کی گئی ہے۔
KV cache کو چھوٹا کرنے کے 4 طریقے
- Context length کم کریں۔ یہ سب سے مؤثر اور عموماً سب سے کم خرچ طریقہ ہے۔ زیادہ تر chat workloads کبھی بھی 32k کے قریب نہیں پہنچتے۔
- Cache کو خود quantise کریں۔ Ollama کا
OLLAMA_KV_CACHE_TYPEبطور defaultf16استعمال کرتا ہے اورq8_0قبول کرتا ہے، جو تقریباً نصف memory استعمال کرتا ہے، نیزq4_0، جو تقریباً ایک چوتھائی memory استعمال کرتا ہے۔ llama.cpp میں اس کے مساوی options-ctk q8_0اور-ctv q8_0ہیں۔ - کم key/value heads یا کم layers والا model منتخب کریں۔ 40 GB weights download کرنے سے پہلے
config.jsonپڑھیں۔ - ایک وقت میں کم requests serve کریں اور باقی کو queue میں رکھیں۔
q4_0 پر Llama 3.1 8B کی قدر 128 KiB فی token سے کم ہو کر تقریباً 32 KiB رہ جاتی ہے، اس لیے 32k context کی لاگت 4 GiB کے بجائے تقریباً 1 GiB ہوتی ہے۔ یہ بچت بلا قیمت نہیں ہے۔ Keys اور values کم precision کے ساتھ محفوظ ہوتے ہیں، اس لیے اسے برقرار رکھنے سے پہلے اپنی prompts پر output کا موازنہ کریں۔
Provider prompt caching حقیقت میں کیا فائدہ دیتا ہے
Provider prompt caching ایک مختلف product ہے اور اس میں حساب کی اکائی بھی مختلف ہوتی ہے۔ آپ ایک مستحکم prefix نشان زد کرتے ہیں، provider اسے محفوظ کر لیتا ہے، اور بعد کی وہ calls جو بعینہٖ اسی prefix کو دہراتی ہیں، مکمل input price کے بجائے کم rate پر bill ہوتی ہیں۔
August 2026 تک Anthropic کے شائع کردہ multipliers یہ ہیں: 5-minute cache write کی لاگت base input token price سے 1.25 گنا ہوتی ہے۔ 1-hour write کی لاگت 2 گنا، جبکہ cache read کی لاگت 0.1 گنا ہوتی ہے۔ اگر 20,000-token system prompt کو ان اعداد کے ساتھ رکھیں تو اس deal کی صورتِ حال واضح ہو جاتی ہے۔
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"
}
]اسے arithmetic کے طور پر دیکھیں۔ پہلی call پر 5-minute write premium، 5,000 token equivalents ہے: 25,000، جبکہ اسے uncached بھیجنے پر 20,000 bill ہوتے۔ Window کے اندر ہر بعد کی call کے لیے 20,000 کے بجائے 2,000 bill ہوتے ہیں، یعنی 18,000 کی بچت۔ اس لیے 5-minute cache دوسری call سے فائدہ دینا شروع کر دیتا ہے۔
1-hour cache ایک مختلف فیصلہ ہے۔ Write پر 40,000 bill ہوتے ہیں، یعنی 20,000 token equivalents کا premium۔ اس لیے فائدے میں آنے کے لیے ایک گھنٹے کے اندر دو hits درکار ہیں۔ یہ آپ کے traffic pattern کا سوال ہے، model کا نہیں۔ مکمل calculation، بشمول window منتخب کرنے کا طریقہ، Claude prompt caching کے لیے break-even math میں موجود ہے۔
دو تفصیلات یہ طے کرتی ہیں کہ آپ cache hit حاصل کریں گے یا نہیں۔ پہلی یہ کہ model کی minimum length سے کم prefix کو خاموشی سے cache نہیں کیا جاتا۔ August 2026 تک documented minimum، Claude Opus 5 کے لیے 512 tokens اور Claude Sonnet 5 کے لیے 1,024 tokens ہے، اور اس سے چھوٹی request معمول کے مطابق process ہوتی ہے، کوئی error واپس نہیں کیا جاتا۔ دوسری یہ کہ lifetime اس request کے آغاز سے ناپی جاتی ہے جو entry کو write یا read کرتی ہے، اور ہر read اسے اضافی لاگت کے بغیر refresh کر دیتا ہے۔ اس لیے مصروف endpoint، 5-minute cache کو غیر معینہ مدت تک alive رکھ سکتا ہے۔ ہر دس منٹ میں ایک بار call ہونے والا endpoint ہر بار write premium ادا کرتا ہے اور کبھی cache سے فائدہ نہیں لیتا۔
اندازہ لگانے کے بجائے response چیک کریں۔ usage object، cache_creation_input_tokens اور cache_read_input_tokens report کرتا ہے۔ اگر ہر call پر read count صفر ہو تو اس کا مطلب ہے کہ آپ writes خرید رہے ہیں اور بدلے میں کچھ حاصل نہیں کر رہے۔
جہاں دونوں caches آپس میں ملتے ہیں
ایک طویل system prompt وہ مقام ہے جہاں دونوں ملتے ہیں، اور یہ بیک وقت دونوں طرف لاگت عائد کرتا ہے۔
مقامی طور پر، f16 پر Llama 3.1 8B server میں 20,000-token system prompt تقریباً 2.4 GiB کے KV cache پر مشتمل ہوتا ہے، اور اسے شامل کرنے والی ہر concurrent request کے لیے یہ cache الگ درکار ہوتا ہے۔ ریموٹ طور پر، اسی prefix کے لیے ایک cache write درکار ہوتی ہے، اور اس کے بعد ہر call پر input لاگت کا 0.1 گنا خرچ آتا ہے۔ مقامی لاگت آپ کے users کی تعداد کے ساتھ بڑھتی ہے۔ ریموٹ لاگت آپ کے traffic کے ساتھ بڑھتی ہے اور idle وقت میں دوبارہ reset ہو جاتی ہے۔
ایک مقامی feature ایسا ہے جو provider prompt caching سے مشابہ دکھائی دیتا ہے، اور اسے مسلسل اسی کے ساتھ خلط ملط کیا جاتا ہے: prefix caching۔ vLLM کی documentation automatic prefix caching کو موجودہ queries کے "KV cache کو cache کرنے" کے طور پر بیان کرتی ہے، تاکہ نئی query موجودہ queries میں سے کسی ایک کے ساتھ یکساں prefix رکھنے کی صورت میں KV cache کو براہ راست دوبارہ استعمال کر سکے۔ llama.cpp server بطور default ہر slot کے لیے prompt cache رکھتا ہے، اور --cache-reuse N اس چھوٹے ترین chunk کا تعین کرتا ہے جسے یہ دوبارہ استعمال کرنے کی کوشش کرے گا۔
prefix caching prefill compute کو بچاتی ہے۔ آپ کے 20,000-token system prompt کو ہر request پر دوبارہ process کرنے کے بجائے صرف ایک بار process کیا جاتا ہے، جس سے پہلے token تک پہنچنے کا وقت نمایاں طور پر کم ہو جاتا ہے۔ vLLM میں مشترکہ blocks کو duplicate کرنے کے بجائے دوبارہ استعمال کیا جاتا ہے، اس لیے memory utilization بھی بہتر ہوتی ہے۔ تاہم، یہ کبھی بھی ان tokens کے لیے درکار cache کو کم نہیں کرتی جو اس وقت live ہوں۔ requests کے درمیان weights کو resident رکھنا ایک متعلقہ مگر الگ طریقہ ہے، جس کی وضاحت requests کے درمیان Ollama model کو loaded رکھنا میں کی گئی ہے۔
اپنے سرور پر کیا ناپیں
ماڈل کو اپنے مطلوبہ context پر load کریں، پھر estimate پر بھروسا کرنے کے بجائے حقیقی اعداد پڑھیں۔
ollama ps
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
free -gollama ps loaded model کو اس کے size کے ساتھ دکھاتا ہے اور یہ بھی بتاتا ہے کہ وہ GPU پر چل رہا ہے یا CPU پر۔ اگر آپ کو توقع تھی کہ ماڈل مکمل طور پر GPU پر رہے گا، لیکن output میں CPU split دکھائی دے، تو اس کا مطلب ہے کہ KV cache نے ماڈل کے کچھ حصے کو GPU سے باہر منتقل کر دیا ہے، اور generation speed اسی کے مطابق کم ہو جائے گی۔ nvidia-smi حقیقی VRAM figure دیتا ہے، جبکہ free -g CPU-only VPS پر یہی کام کرتا ہے۔ context کو مرحلہ وار بڑھائیں، ماڈل دوبارہ load کریں، اور دیکھیں کہ number کیسے تبدیل ہوتا ہے۔ آپ کی arithmetic اور reported figure ایک دوسرے کے قریب ہونی چاہئیں۔ جب ایسا نہ ہو، تو فرق عموماً runtime کے اپنے compute buffers کی وجہ سے ہوتا ہے، formula کی غلطی کی وجہ سے نہیں۔
اگر یہ numbers آپ کو ایسے hardware کی طرف لے جائیں جسے آپ rent نہیں کرنا چاہتے، تو pay-per-token کے ساتھ موازنہ GPU VPS بمقابلہ API tokens میں کیا گیا ہے۔
FAQ
کیا KV cache اور prompt caching ایک ہی چیز ہیں؟
نہیں۔ KV cache، serving process کے اندر ہر request کے لیے استعمال ہونے والی memory ہے۔ اس میں موجودہ context کے ہر token کے key اور value vectors محفوظ ہوتے ہیں۔ یہ آپ کی RAM یا VRAM میں رہتی ہے اور request ختم ہونے پر release ہو جاتی ہے۔ Provider prompt caching ایک billing feature ہے۔ یہ provider کے infrastructure پر prompt کے مستحکم prefix کو محفوظ کرتی ہے اور اسے دوبارہ بھیجنے پر کم rate وصول کرتی ہے۔ KV cache ختم ہونے پر model load نہیں ہوتا۔ Prompt cache نہ ملنے سے صرف invoice اور first token تک پہنچنے کا وقت بڑھتا ہے۔
میرا model 2k context پر load ہوتا ہے لیکن 32k پر fail کیوں ہوتا ہے؟
کیونکہ runtime load کے وقت پورا KV cache allocate کرتا ہے۔ اس کا size آپ کے بھیجے گئے prompt کے بجائے configured context length کے مطابق ہوتا ہے۔ Llama 3.1 8B میں f16 کے ساتھ cache فی token 128 KiB ہے۔ اس لیے 2k context کے لیے 0.25 GiB اور 32k کے لیے 4 GiB درکار ہوتے ہیں۔ دونوں صورتوں میں weights fit ہو جاتے ہیں۔ ناکامی reservation کے وقت ہوتی ہے۔ vLLM اسے ValueError کے طور پر report کرتا ہے۔ یہ ValueError ان tokens کی زیادہ سے زیادہ تعداد بتاتا ہے جنہیں وہ محفوظ کر سکتا ہے۔ vLLM gpu_memory_utilization بڑھانے یا max_model_len کم کرنے کی تجویز دیتا ہے۔ صرف CPU والے box پر kernel کا out-of-memory killer اس کے بجائے process ختم کر دیتا ہے۔ آپ اس کی تصدیق dmesg -T | grep -i "killed process" سے کر سکتے ہیں۔
میں اپنے model کے لیے KV cache size کیسے calculate کروں؟
2 کو layer count، key/value heads کی تعداد، head dimension اور فی element bytes سے ضرب دیں۔ اس سے فی token bytes حاصل ہوں گے۔ پھر اسے context length اور concurrent requests کی تعداد سے ضرب دیں۔ Layer اور head counts model کے config.json سے پڑھیں۔ f16 یا bf16 کے لیے فی element 2 bytes استعمال کریں۔ q8_0 cache تقریباً اس کا نصف، جبکہ q4_0 تقریباً اس کا ایک چوتھائی ہوتا ہے۔
کیا prompt caching سے میرے اپنے server کو درکار memory کم ہوتی ہے؟
Provider prompt caching آپ کے hardware کے لیے کچھ نہیں کرتی، کیونکہ storage provider کی طرف ہوتی ہے۔ مقامی متبادل prefix caching ہے، جو vLLM اور llama.cpp server دونوں فراہم کرتے ہیں۔ یہ shared prefix کے لیے پہلے سے calculate کیے گئے key اور value vectors دوبارہ استعمال کرتی ہے۔ اس سے prefill compute کی بچت ہوتی ہے اور first token تک پہنچنے کا وقت کم ہوتا ہے۔ vLLM میں shared blocks duplicate کرنے کے بجائے دوبارہ استعمال ہوتے ہیں، اس لیے memory utilization بھی بہتر ہوتی ہے۔ تاہم دونوں features اس وقت in-flight tokens کے لیے درکار cache کو کم نہیں کرتے۔ اس لیے context اور concurrency کا حساب بدستور کم از کم مطلوبہ memory طے کرتا ہے۔
کیا ایسے prompt کو cache کرنا فائدہ مند ہے جسے میں صرف ایک بار بھیجوں؟
نہیں۔ Cache write کی لاگت plain input سے زیادہ ہوتی ہے۔ August 2026 تک 5-minute option کے لیے یہ base rate کا 1.25 گنا ہے۔ اس لیے ایسا prefix جسے آپ window کے اندر دوبارہ نہ بھیجیں، براہ راست نقصان ہے۔ Caching اس وقت فائدہ دیتی ہے جب ایک ہی prefix بار بار استعمال ہو، مثلاً طویل system prompt یا ایسی document جس کے بارے میں آپ کئی سوالات پوچھنے والے ہوں۔ API response میں cache_read_input_tokens چیک کر کے تصدیق کریں کہ آپ کو hits مل رہے ہیں، نہ کہ writes کی charges ادا کرنی پڑ رہی ہیں۔