KV cache กับ prompt cache ต่างกันอย่างไร สรุปชัดเจน
เข้าใจความแตกต่างระหว่าง KV cache และ prompt cache ในเชิงเทคนิคและค่าใช้จ่าย KV cache คือหน่วยความจำที่ใช้ประมวลผลจริงจนอาจทำให้โมเดลโหลดไม่ขึ้น ส่วน prompt cache คือฟีเจอร์ลดราคา
KV cache กับ prompt cache: คำตอบโดยสรุป
KV cache และ prompt cache ของผู้ให้บริการมีเพียงชื่อที่คล้ายกัน แต่ในทางปฏิบัติแทบไม่มีส่วนใดที่เหมือนกัน KV cache คือหน่วยความจำขณะทำงาน (working memory) สำหรับแต่ละคำขอ (request) โดยจะอยู่ใน RAM หรือ VRAM ของเซิร์ฟเวอร์ตลอดช่วงเวลาของคำขอนั้นๆ และจะมีขนาดเพิ่มขึ้นตามความยาวของบริบท (context length) รวมถึงจำนวนคำขอที่ประมวลผลพร้อมกัน ส่วน prompt caching ของผู้ให้บริการเป็นฟีเจอร์ด้านการเรียกเก็บเงินและลดความหน่วง (latency) โดยส่วนนำของ prompt ที่คงที่ของคุณจะถูกจัดเก็บไว้บนเซิร์ฟเวอร์ของผู้ให้บริการ และจะคิดค่าบริการในราคาพิเศษเมื่อคุณส่ง prompt นั้นซ้ำอีกครั้ง
อย่างหนึ่งคือหน่วยความจำที่คุณซื้อเป็นฮาร์ดแวร์ ส่วนอีกอย่างคือหน่วยความจำที่ผู้อื่นถือครองและเรียกเก็บค่าเช่าจากคุณ
ความแตกต่างในทางปฏิบัติมีความสำคัญมากกว่าคำนิยาม คุณสามารถประสบปัญหา KV cache เต็ม ซึ่งเมื่อเกิดขึ้น โมเดลจะไม่โหลดหรือคำขอจะถูกปฏิเสธ แต่คุณไม่สามารถทำให้ prompt cache เต็มได้ คุณทำได้เพียงแค่เรียกใช้ไม่สำเร็จ (fail to hit) ซึ่งผลที่ตามมาคือคุณเพียงแค่ต้องจ่ายค่าบริการในราคาเต็มตามปกติเท่านั้น
สิ่งที่ KV cache จัดเก็บและเหตุผลที่มีการใช้งาน
Transformer ที่กำลังสร้าง token ลำดับที่ 500 จำเป็นต้องประมวลผล (attend) token ทั้ง 499 ตัวก่อนหน้า สำหรับ token แต่ละตัว ทุกเลเยอร์ต้องการ key vector และ value vector การคำนวณค่าเหล่านี้ใหม่ทั้งหมดสำหรับทุก token ใหม่จะทำให้เวลาที่ใช้ในการสร้างเพิ่มขึ้นเป็นกำลังสองของความยาวลำดับ (square of the length) ดังนั้น runtime จึงจัดเก็บค่าเหล่านี้ไว้แทน พื้นที่จัดเก็บดังกล่าวคือ KV cache (key/value cache)
ข้อมูลนี้เป็นสถานะเฉพาะของแต่ละคำขอ (per-request state) เนื่องจากถูกสร้างขึ้นจากลำดับ token ที่เฉพาะเจาะจงของคำขอนั้นๆ ผู้ใช้สองคนที่ส่ง prompt ต่างกันไม่สามารถใช้ cache ร่วมกันได้ เว้นแต่ runtime จะทำ prefix caching ซึ่งเป็นฟีเจอร์แยกต่างหากที่จะอธิบายในภายหลัง
การให้บริการเกิดขึ้นใน 2 ระยะ ระยะ Prefill จะอ่าน prompt ทั้งหมดของคุณและเติมข้อมูลลงใน cache ซึ่งถูกจำกัดด้วยความสามารถในการคำนวณ (compute) ส่วนระยะ Decode จะสร้าง token ทีละตัวและเพิ่มเข้าไปใน cache ซึ่งถูกจำกัดด้วยแบนด์วิดท์ของหน่วยความจำ (memory bandwidth) การแบ่งระยะเช่นนี้เป็นเหตุผลว่าทำไมการประมวลผล prompt และการสร้าง token จึงแสดงความเร็วที่แตกต่างกันเมื่อคุณ วัดจำนวน token ต่อวินาทีบนเครื่องของคุณเอง
KV cache ใช้หน่วยความจำเท่าใด
ไม่ต้องไปหาตารางจากผู้ผลิต ขนาดของหน่วยความจำคำนวณได้ด้วยสูตรคณิตศาสตร์ที่คุณสามารถทำซ้ำได้กับทุกโมเดล:
bytes per token = 2 * layers * kv_heads * head_dim * bytes per elementเลข 2 หมายถึง key และ value ส่วนตัวเลขอื่นทั้งหมดมาจาก config.json ของโมเดล ซึ่งระบุไว้ในหน้า Hugging Face ของโมเดลนั้น
ลองพิจารณา Llama 3.1 8B โดยที่ config ระบุ num_hidden_layers ไว้ที่ 32 และ num_key_value_heads ไว้ที่ 8 เมื่อนำ hidden_size ขนาด 4096 มากระจายบน attention heads จำนวน 32 หัว จะได้ขนาด head dimension เท่ากับ 128 ที่ความละเอียด f16 แต่ละ element จะใช้พื้นที่ 2 bytes:
2 * 32 * 8 * 128 * 2 = 131072 bytes = 128 KiB per tokenให้นำค่านี้ไปคูณกับ context ที่คุณต้องการใช้งาน จากนั้นคูณด้วยจำนวนคำขอ (requests) ที่ประมวลผลพร้อมกัน
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"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
}
]ที่ context ขนาด 8k ตัว cache จะใช้พื้นที่ 1 GiB และที่ 32k จะใช้พื้นที่ 4 GiB ซึ่งอยู่ในระดับเดียวกับขนาดของ weights แบบ 4-bit เอง สำหรับ context สูงสุดของโมเดลที่ 128k จะใช้พื้นที่ 16 GiB ต่อหนึ่งคำขอ และ 64 GiB หากมีสี่คำขอที่ใช้งานเต็มพื้นที่ดังกล่าว โดยที่ขนาดของ weights ไม่ได้เปลี่ยนแปลง มีเพียงแค่ขนาดของ cache เท่านั้นที่เปลี่ยนไป
Grouped query attention (GQA) มีบทบาทสำคัญอย่างมากต่อตัวเลขนี้ Llama 3.1 8B มี key/value heads จำนวน 8 หัวที่รองรับ query heads 32 หัว ดังนั้น query heads สี่หัวจึงใช้ key/value pair ร่วมกันหนึ่งชุด โมเดลที่มีค่า num_key_value_heads เท่ากับ num_attention_heads จะใช้พื้นที่ cache มากกว่าถึงสี่เท่าแม้จะมีจำนวน parameter เท่ากัน โปรดตรวจสอบฟิลด์นั้นก่อนที่คุณจะสรุปว่าโมเดลขนาด 8B สองโมเดลจะมีต้นทุนในการให้บริการเท่ากัน
เหตุใดโมเดลที่เคยรันที่ 2k ถึงโหลดไม่ขึ้นเมื่อปรับเป็น 32k
เนื่องจาก runtime จะจอง KV cache ไว้ตั้งแต่ตอนโหลดโมเดล โดยขนาดจะอ้างอิงตาม context length ที่คุณตั้งค่าไว้ ไม่ใช่ตามขนาดของ prompt ที่คุณส่งจริง ค่าเริ่มต้นของ Ollama ไม่ได้เป็นตัวเลขเดียวอีกต่อไป นับตั้งแต่เดือนตุลาคม 2026 เอกสารประกอบเรื่อง context length ได้กำหนดค่าตาม VRAM ดังนี้: 4k สำหรับเครื่องที่มี VRAM ต่ำกว่า 24 GiB, 32k สำหรับเครื่องที่มี VRAM ระหว่าง 24 ถึง 48 GiB และ 256k สำหรับเครื่องที่มี VRAM ตั้งแต่ 48 GiB ขึ้นไป ในขณะที่โมเดลบนคลาวด์จะใช้ค่าสูงสุดตามที่โมเดลรองรับเป็นค่าเริ่มต้น สำหรับ VPS ที่ใช้เฉพาะ CPU หรือ GPU ขนาดเล็ก ค่าเริ่มต้นจะอยู่ที่ 4k หากคุณปรับเพิ่มเป็น 32k เท่ากับว่าคุณได้ร้องขอการจัดสรรหน่วยความจำเพิ่มขึ้นอีก 4 GiB ก่อนที่จะเริ่มประมวลผลแม้แต่ token เดียว สำหรับการ์ดจอขนาด 24 GiB นั้น 32k คือค่าเริ่มต้นอยู่แล้ว ดังนั้นการจองหน่วยความจำส่วนนี้จึงเกิดขึ้นไม่ว่าคุณจะร้องขอหรือไม่ก็ตาม
OLLAMA_CONTEXT_LENGTH=32768 ollama serveการตั้งค่าแบบเดียวกันต่อ session จาก interactive prompt:
ollama run llama3.1:8b
/set parameter num_ctx 32768ลักษณะความผิดพลาดจะแตกต่างกันไปตามแต่ละ stack โดย vLLM จะตรวจสอบการคำนวณตั้งแต่ตอนเริ่มต้นและปฏิเสธที่จะรัน:
ValueError: To serve at least one request with the model's max seq len (131072), (16.0 GiB KV cache is needed, which is larger than the available KV cache memory (9.56 GiB). Based on the available memory, the estimated maximum model length is 78336. Try increasing `gpu_memory_utilization` (which also controls CPU memory on the CPU backend) or decreasing `max_model_len` when initializing the engine. See https://docs.vllm.ai/en/latest/configuration/conserving_memory/ for more details.บน VPS ที่ใช้เฉพาะ CPU ซึ่งรัน Ollama หรือ llama.cpp การจัดสรรหน่วยความจำจะเป็นการใช้ system RAM ปกติ และปัญหาหน่วยความจำไม่พออาจไม่ถูกตรวจพบตั้งแต่ตอนเริ่มต้น แต่ตัวจัดการ out-of-memory killer ของ kernel จะเข้ามาจัดการ process นั้นแทน และทิ้งร่องรอยไว้ใน kernel ring buffer:
dmesg -T | grep -i "killed process"หากมีบรรทัดที่ระบุชื่อ process การให้บริการของคุณ แสดงว่าเครื่องได้สัญญาว่าจะจัดสรรหน่วยความจำให้มากกว่าที่มีอยู่จริง วิธีแก้ไขคือการลด context ลง ไม่ใช่การเพิ่มขนาด swap file เพราะหาก KV cache ถูกย้ายไปไว้บนดิสก์ ระบบจะต้องอ่านข้อมูลทุกครั้งที่มีการสร้าง token ใหม่ ซึ่งจะทำให้ความเร็วในการประมวลผลช้าลงจนไม่สามารถใช้งานได้จริง การเลือกตัวเลขที่เหมาะสมได้อธิบายไว้ใน คู่มือเกี่ยวกับ num_ctx และ context length ใน Ollama ของเรา
ผลกระทบของ concurrency ต่อจำนวนตัวเลข
คำขอที่กำลังประมวลผลแต่ละรายการจะมี KV cache เป็นของตนเอง นี่คือจุดที่แผนการจัดสรรทรัพยากรส่วนใหญ่มักมองข้าม ผู้ใช้งาน 4 คนที่ถือ context ขนาด 32k แต่ละคน ต้องการหน่วยความจำรวมกัน 16 GiB นอกเหนือไปจากขนาดของ weights
Runtime แต่ละตัวมีความเข้มงวดในเรื่องนี้ต่างกัน Ollama และ llama.cpp จะจอง context ตามที่คุณระบุไว้ตั้งแต่ตอนโหลดโมเดล ดังนั้นหน่วยความจำจะถูกจองไว้เสมอไม่ว่าจะมีการใช้งานจริงหรือไม่ก็ตาม ในขณะที่ vLLM จะแบ่งหน่วยความจำออกเป็นบล็อกขนาดคงที่และจัดสรรให้ตามการขยายตัวของแต่ละคำขอ ดังนั้นคำขอขนาด 500 token จะใช้พื้นที่เพียงเท่ากับ 500 token เท่านั้น ไม่ว่าจะเป็นวิธีใดก็ตาม พื้นที่หน่วยความจำมีจำกัด และเมื่อเต็มแล้ว คำขอใหม่จะต้องเข้าคิวแทนที่จะได้ประมวลผลทันที ผลกระทบของการเข้าคิวที่มีต่อเวลาในการตอบสนองได้อธิบายไว้ใน จำนวนผู้ใช้งานพร้อมกันที่ LLM แบบ self-hosted รองรับได้
สี่วิธีในการลดขนาด KV cache
- ลดความยาวของ context วิธีนี้เป็นปัจจัยที่มีผลมากที่สุดและมักจะมีต้นทุนต่ำที่สุด งานประเภทแชทส่วนใหญ่ไม่เคยใช้งาน context ถึง 32k
- ทำ Quantization ให้กับตัว cache เอง ค่าเริ่มต้นของ
OLLAMA_KV_CACHE_TYPEใน Ollama คือf16ซึ่งรองรับq8_0ที่ใช้หน่วยความจำลดลงประมาณครึ่งหนึ่ง และq4_0ที่ใช้หน่วยความจำลดลงเหลือประมาณหนึ่งในสี่ ส่วนค่าที่เทียบเท่ากันใน llama.cpp คือ-ctk q8_0และ-ctv q8_0 - เลือกโมเดลที่มีจำนวน key/value heads หรือจำนวนเลเยอร์น้อยลง โปรดอ่าน
config.jsonก่อนที่คุณจะดาวน์โหลดไฟล์ weights ขนาด 40 GB - ให้บริการคำขอจำนวนน้อยลงในคราวเดียวและนำคำขอที่เหลือเข้าคิวไว้
ที่ q4_0 ตัวเลขของ Llama 3.1 8B จะลดลงจาก 128 KiB ต่อ token เหลือประมาณ 32 KiB ดังนั้น context ขนาด 32k จึงใช้หน่วยความจำประมาณ 1 GiB แทนที่จะเป็น 4 GiB การประหยัดหน่วยความจำนี้มีข้อแลกเปลี่ยน เนื่องจาก key และ value จะถูกจัดเก็บด้วยความละเอียดที่ต่ำลง ดังนั้นควรเปรียบเทียบผลลัพธ์จาก prompt ของคุณเองก่อนที่จะตัดสินใจใช้งานจริง
สิ่งที่การทำ prompt caching ของผู้ให้บริการมอบให้จริง ๆ
การทำ prompt caching ของผู้ให้บริการเป็นผลิตภัณฑ์ที่แตกต่างและมีหน่วยการคิดเงินที่ต่างออกไป คุณเพียงกำหนดส่วนนำ (prefix) ที่คงที่ไว้ ผู้ให้บริการจะจัดเก็บข้อมูลนั้นไว้ และการเรียกใช้งานในภายหลังที่ใช้ prefix เดิมซ้ำจะถูกคิดค่าบริการในอัตราที่ลดลงแทนที่จะเป็นราคา input เต็มจำนวน
ตัวคูณที่ Anthropic ประกาศไว้ ณ เดือนตุลาคม 2026 คือ: การเขียน cache ระยะเวลา 5 นาที มีค่าใช้จ่าย 1.25 เท่าของราคา input token ปกติ การเขียนระยะเวลา 1 ชั่วโมงมีค่าใช้จ่าย 2 เท่า และการอ่าน cache มีค่าใช้จ่าย 0.1 เท่าในโมเดลส่วนใหญ่ โมเดลรุ่นใหม่ล่าสุดมีค่าอ่านที่ถูกลงไปอีก คือ 0.05 เท่าใน Claude Opus 5.5 และ Sonnet 5.5 และ 0.025 เท่าใน Claude Fable 5.1 และ Mythos 5.1 หากคุณนำ system prompt ขนาด 20,000 token มาคำนวณตามตัวเลขมาตรฐานนี้ รูปแบบความคุ้มค่าจะปรากฏชัดเจน
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"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"
}
]ให้พิจารณาในเชิงคณิตศาสตร์ ค่าธรรมเนียมการเขียน cache 5 นาทีจะเท่ากับ 25,000 token ในการเรียกครั้งแรก: 25,000 เทียบกับ 20,000 หากส่งข้อมูลโดยไม่ใช้ cache ทุกการเรียกใช้งานหลังจากนั้นภายในช่วงเวลาที่กำหนดจะถูกคิดค่าบริการเพียง 2,000 แทนที่จะเป็น 20,000 ซึ่งประหยัดไปได้ 18,000 token ดังนั้น cache 5 นาทีจะเริ่มคุ้มทุนตั้งแต่การเรียกครั้งที่สองเป็นต้นไป
cache 1 ชั่วโมงเป็นการเดิมพันที่ต่างออกไป โดยจะคิดค่าบริการ 40,000 ในการเขียน ซึ่งเป็นค่าธรรมเนียมส่วนเพิ่ม 20,000 token ดังนั้นจึงต้องมีการเรียกใช้งานซ้ำอย่างน้อยสองครั้งภายในหนึ่งชั่วโมงจึงจะเริ่มคุ้มทุน นี่เป็นเรื่องของรูปแบบ traffic ของคุณ ไม่ใช่เรื่องของตัวโมเดล การคำนวณแบบเต็มรูปแบบ รวมถึงวิธีการเลือกช่วงเวลาที่เหมาะสม อยู่ใน การคำนวณจุดคุ้มทุนสำหรับ Claude prompt caching
รายละเอียดสองประการเป็นตัวตัดสินว่าคุณจะใช้งาน cache ได้หรือไม่ ประการแรก prefix ที่มีความยาวต่ำกว่าเกณฑ์ขั้นต่ำของโมเดลจะไม่ถูกเก็บลง cache โดยไม่มีการแจ้งเตือน: ณ เดือนตุลาคม 2026 เกณฑ์ขั้นต่ำที่ระบุไว้คือ 512 token สำหรับ Claude Opus 5, Opus 5.5 และ Sonnet 5.5 และ 1,024 token สำหรับ Claude Sonnet 5 หากคำขอสั้นกว่านี้ ระบบจะประมวลผลตามปกติโดยไม่ส่งข้อผิดพลาดกลับมา ประการที่สอง อายุของ cache จะนับจากจุดเริ่มต้นของคำขอที่เขียนหรืออ่านรายการนั้น และทุกการอ่านจะรีเฟรชอายุของ cache โดยไม่มีค่าใช้จ่ายเพิ่มเติม ดังนั้น endpoint ที่มีการใช้งานหนาแน่นจะสามารถรักษา cache 5 นาทีให้คงอยู่ได้ตลอดไป ในขณะที่ endpoint ที่ถูกเรียกใช้งานทุก ๆ สิบนาทีจะต้องจ่ายค่าธรรมเนียมการเขียนทุกครั้งและไม่ได้รับประโยชน์จากการประหยัดต้นทุนเลย
ให้ตรวจสอบการตอบกลับแทนการคาดเดา วัตถุ usage จะรายงานค่า cache_creation_input_tokens และ cache_read_input_tokens หากค่า read count เป็นศูนย์ในการเรียกใช้งานทุกครั้ง นั่นหมายความว่าคุณกำลังจ่ายเงินซื้อการเขียนแต่ไม่ได้รับผลตอบแทนใด ๆ กลับมา
จุดที่แคชทั้งสองมาบรรจบกัน
System prompt ที่ยาวคือจุดที่แคชทั้งสองมาพบกัน และมันจะคิดค่าใช้จ่ายคุณจากทั้งสองฝั่งพร้อมกัน
ในฝั่ง local นั้น system prompt ขนาด 20,000 token จะใช้พื้นที่ KV cache ประมาณ 2.4 GiB บนเซิร์ฟเวอร์ Llama 3.1 8B ที่ความละเอียด f16 และจะถูกใช้แยกกันสำหรับทุกคำขอที่ทำงานพร้อมกัน ในฝั่ง remote นั้น prefix เดียวกันนี้จะมีค่าใช้จ่ายในการเขียนแคชหนึ่งครั้ง และหลังจากนั้นจะคิดค่าใช้จ่าย 0.1 เท่าของ input ในการเรียกใช้แต่ละครั้ง หรือน้อยกว่านั้นในโมเดลรุ่นใหม่ล่าสุด ค่าใช้จ่ายฝั่ง local จะแปรผันตามจำนวนผู้ใช้งานของคุณ ส่วนค่าใช้จ่ายฝั่ง remote จะแปรผันตามปริมาณ traffic และจะถูกรีเซ็ตในช่วงเวลาที่คุณไม่มีการใช้งาน
มีฟีเจอร์ฝั่ง local อย่างหนึ่งที่มีลักษณะคล้ายกับ prompt caching ของผู้ให้บริการและมักจะถูกเข้าใจผิดอยู่เสมอ นั่นคือ prefix caching เอกสารของ vLLM อธิบายว่า automatic prefix caching คือการแคช "KV cache ของคำถามที่มีอยู่ เพื่อให้คำถามใหม่สามารถนำ KV cache กลับมาใช้ใหม่ได้โดยตรงหากมี prefix เดียวกับคำถามที่มีอยู่เดิม" ปัจจุบัน vLLM เปิดใช้งานฟีเจอร์นี้เป็นค่าเริ่มต้น ส่วนเซิร์ฟเวอร์ llama.cpp จะเก็บ prompt cache แยกตาม slot เป็นค่าเริ่มต้น และ --cache-reuse N จะเป็นตัวกำหนดขนาด chunk เล็กที่สุดที่จะพยายามนำกลับมาใช้ใหม่
สิ่งที่ prefix caching ช่วยประหยัดได้คือการคำนวณในช่วง prefill โดย system prompt ขนาด 20,000 token ของคุณจะถูกประมวลผลเพียงครั้งเดียวแทนที่จะทำทุกครั้งที่มีคำขอเข้ามา ซึ่งช่วยลดเวลาในการรอ token แรกได้อย่างมาก ใน vLLM บล็อกที่แชร์กันจะถูกนำกลับมาใช้ใหม่แทนที่จะถูกคัดลอกซ้ำ ทำให้การใช้หน่วยความจำมีประสิทธิภาพมากขึ้นด้วย แต่สิ่งที่มันไม่เคยทำคือการลดขนาดแคชที่คุณต้องสำรองไว้สำหรับ token ที่กำลังใช้งานอยู่ การคงน้ำหนัก (weights) ไว้ในหน่วยความจำระหว่างคำขอเป็นอีกกลไกหนึ่งที่เกี่ยวข้องแต่แยกส่วนกัน ซึ่งครอบคลุมอยู่ใน การคงโมเดล Ollama ไว้ในหน่วยความจำระหว่างคำขอ
สิ่งที่ควรวัดผลบนเซิร์ฟเวอร์ของคุณ
ให้โหลดโมเดลที่บริบท (context) เป้าหมายของคุณ จากนั้นอ่านค่าตัวเลขจริงแทนการเชื่อค่าประมาณการ
ollama ps
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
free -gollama ps จะแสดงรายการโมเดลที่โหลดอยู่พร้อมขนาด, บริบทที่ใช้โหลด และสถานะว่ากำลังทำงานบน GPU หรือ CPU ให้ตรวจสอบคอลัมน์บริบทก่อน เนื่องจากค่าเริ่มต้นในปัจจุบันขึ้นอยู่กับ VRAM ของคุณ หากโมเดลที่คุณคาดว่าจะอยู่บน GPU ทั้งหมดแสดงผลว่ามีการแบ่งไปใช้ CPU นั่นหมายความว่า KV cache ได้ผลักส่วนหนึ่งของโมเดลออกไป และความเร็วในการสร้างข้อความจะลดลงตามนั้น nvidia-smi จะแสดงตัวเลข VRAM ที่แท้จริง และ free -g จะทำหน้าที่เดียวกันบน VPS ที่ใช้เฉพาะ CPU ให้ค่อยๆ เพิ่มบริบททีละขั้น โหลดใหม่ และสังเกตการเปลี่ยนแปลงของตัวเลข ค่าที่คุณคำนวณได้กับตัวเลขที่รายงานควรจะใกล้เคียงกัน หากไม่ตรงกัน ช่องว่างที่เกิดขึ้นมักเป็นผลมาจากบัฟเฟอร์การคำนวณของรันไทม์เอง ไม่ใช่ข้อผิดพลาดในสูตรการคำนวณ
หากตัวเลขเหล่านั้นผลักดันให้คุณต้องใช้ฮาร์ดแวร์ที่คุณไม่ต้องการเช่า การเปรียบเทียบกับการจ่ายเงินตามจำนวน token สามารถดูได้ที่ GPU VPS เทียบกับ API tokens
FAQ
KV cache เหมือนกับ prompt caching หรือไม่?
ไม่เหมือนกัน KV cache คือหน่วยความจำต่อหนึ่งคำขอ (per-request) ภายในกระบวนการทำงานของเซิร์ฟเวอร์ ซึ่งเก็บเวกเตอร์ key และ value สำหรับทุกโทเค็นในบริบทปัจจุบัน มันอยู่ใน RAM หรือ VRAM ของคุณและจะถูกปล่อยทิ้งเมื่อคำขอนั้นสิ้นสุดลง ส่วน prompt caching ของผู้ให้บริการเป็นฟีเจอร์ด้านการเรียกเก็บเงินที่จัดเก็บส่วนนำของ prompt ที่คงที่ไว้บนโครงสร้างพื้นฐานของผู้ให้บริการ และคิดค่าบริการในอัตราที่ลดลงเมื่อคุณส่ง prompt นั้นอีกครั้ง การที่ KV cache เต็มจะทำให้โมเดลไม่สามารถโหลดได้ แต่การไม่มี prompt cache จะส่งผลเพียงแค่ค่าใช้จ่ายที่สูงขึ้นและเวลาในการประมวลผลโทเค็นแรกที่นานขึ้นเท่านั้น
ทำไมโมเดลของฉันโหลดที่ context 2k ได้ แต่ล้มเหลวที่ 32k?
เพราะ runtime จะจอง KV cache ทั้งหมดไว้ตั้งแต่ตอนโหลด โดยกำหนดขนาดตามความยาวของ context ที่คุณตั้งค่าไว้ ไม่ใช่ตามขนาดของ prompt ที่คุณส่งจริง สำหรับ Llama 3.1 8B ที่ f16 แคชจะใช้พื้นที่ 128 KiB ต่อหนึ่งโทเค็น ดังนั้น context ขนาด 2k จะใช้พื้นที่ 0.25 GiB และ 32k จะใช้ 4 GiB ในขณะที่น้ำหนักของโมเดล (weights) นั้นมีขนาดเท่าเดิมในทั้งสองกรณี สิ่งที่ล้มเหลวคือการจองหน่วยความจำ vLLM จะรายงานเรื่องนี้ผ่าน ValueError โดยระบุว่าต้องการหน่วยความจำ KV cache เท่าใดเทียบกับที่มีอยู่ พร้อมประเมินความยาวสูงสุดของโมเดล และแนะนำให้เพิ่ม gpu_memory_utilization หรือลด max_model_len หากรันบนเครื่องที่ใช้เฉพาะ CPU ด้วย Ollama หรือ llama.cpp ตัว kernel out-of-memory killer อาจเข้ามาปิดกระบวนการทำงานของคุณแทน ซึ่งคุณสามารถตรวจสอบได้ด้วย dmesg -T | grep -i "killed process"
ฉันจะคำนวณขนาด KV cache สำหรับโมเดลของฉันได้อย่างไร?
ให้นำ 2 คูณด้วยจำนวน layer, จำนวน key/value heads, ขนาดของ head และจำนวนไบต์ต่อหนึ่ง element ผลลัพธ์ที่ได้คือจำนวนไบต์ต่อหนึ่งโทเค็น จากนั้นให้นำไปคูณกับความยาวของ context และจำนวนคำขอที่ทำงานพร้อมกัน คุณสามารถอ่านค่าจำนวน layer และ head ได้จาก config.json ของโมเดล ให้ใช้ 2 ไบต์ต่อหนึ่ง element สำหรับ f16 หรือ bf16 หากเป็นแคชแบบ q8_0 จะใช้พื้นที่ประมาณครึ่งหนึ่ง และ q4_0 จะใช้ประมาณหนึ่งในสี่
prompt caching ช่วยลดหน่วยความจำที่เซิร์ฟเวอร์ของฉันต้องใช้หรือไม่?
prompt caching ของผู้ให้บริการไม่ได้ช่วยเรื่องฮาร์ดแวร์ของคุณ เพราะการจัดเก็บเกิดขึ้นที่ฝั่งผู้ให้บริการ สิ่งที่เทียบเคียงได้ในระดับ local คือ prefix caching ซึ่งมีให้ใช้งานทั้งใน vLLM และ llama.cpp server โดยฟีเจอร์นี้จะนำเวกเตอร์ key และ value ที่คำนวณไว้แล้วสำหรับ prefix ที่ใช้ร่วมกันกลับมาใช้ใหม่ ซึ่งช่วยประหยัดการคำนวณในช่วง prefill และลดเวลาในการประมวลผลโทเค็นแรก ใน vLLM บล็อกที่ใช้ร่วมกันจะถูกนำกลับมาใช้ใหม่แทนการทำซ้ำ จึงช่วยประหยัดหน่วยความจำได้ด้วย อย่างไรก็ตาม ทั้งสองฟีเจอร์นี้ไม่ได้ลดขนาดแคชที่จำเป็นสำหรับโทเค็นที่กำลังประมวลผลอยู่ ดังนั้นการคำนวณตาม context และจำนวนคำขอพร้อมกันของคุณยังคงเป็นเกณฑ์ขั้นต่ำที่ต้องใช้
คุ้มค่าหรือไม่ที่จะแคช prompt ที่ฉันส่งเพียงครั้งเดียว?
ไม่คุ้มค่า การเขียนลงแคชมีต้นทุนสูงกว่าการส่ง input ปกติ โดยอยู่ที่ 1.25 เท่าของอัตราพื้นฐานสำหรับตัวเลือก 5 นาที ณ เดือนตุลาคม 2026 ดังนั้น prefix ที่คุณไม่เคยส่งซ้ำภายในช่วงเวลาดังกล่าวจึงถือเป็นการขาดทุนโดยตรง การแคชจะคุ้มค่าเมื่อมีการใช้ prefix เดิมซ้ำ เช่น system prompt ที่ยาวมาก หรือเอกสารที่คุณจะถามคำถามเกี่ยวกับมันหลายครั้ง ให้ตรวจสอบ cache_read_input_tokens ในการตอบกลับของ API เพื่อยืนยันว่าคุณได้รับผลลัพธ์จากการดึงข้อมูลจากแคช (hits) แทนที่จะต้องเสียค่าใช้จ่ายในการเขียนข้อมูลใหม่