KVSplit - รันคอนเท็กซ์ได้ยาวขึ้น 2-3 เท่าบน Apple Silicon
(github.com/dipampaul17)- KVSplit เป็นโปรเจกต์โอเพนซอร์สที่ช่วยให้รัน LLM ขนาดใหญ่ และหน้าต่างคอนเท็กซ์ที่ยาวขึ้นบน Apple Silicon ได้
- ด้วยการ กำหนด precision แยกกันให้คีย์และแวลู ทำให้ ลดการใช้หน่วยความจำได้สูงสุด 72% และคุณภาพลดลงไม่ถึง 1%
- ปรับแต่งมาสำหรับชิป M1/M2/M3 และเฟรมเวิร์ก Metal
- พิสูจน์การ ปรับปรุงความเร็วในการรัน และการประหยัดหน่วยความจำด้วย benchmark ที่วัดจริงและเครื่องมือ visualization
- ติดตั้งได้ง่าย มีการเปรียบเทียบแบบคำสั่งเดียว และมี เครื่องมือ benchmark และวิเคราะห์ ที่หลากหลาย
บทนำ: ทำไม KVSplit จึงสำคัญ
KVSplit เป็นเครื่องมือโอเพนซอร์สที่ทำให้สามารถรัน LLM ขนาดใหญ่และใช้หน้าต่างคอนเท็กซ์ที่ยาวขึ้นมากบนสภาพแวดล้อม Apple Silicon (M1/M2/M3) ได้ โดยใช้ การ quantize ที่กำหนด precision ต่างกันให้กับคีย์และแวลูภายใน KV cache ซึ่งช่วยก้าวข้ามข้อจำกัดของโปรเจกต์เดิมที่ quantize คีย์และแวลูเหมือนกันทั้งหมด พร้อมทั้ง ลดการใช้หน่วยความจำได้อย่างมาก แต่ยังควบคุมการลดลงของคุณภาพให้อยู่ในระดับที่แทบสังเกตไม่ได้ อีกทั้งยังมีการ เปิดเผย benchmark จริง ความเร็ว และตัวชี้วัดคุณภาพทั้งหมด จึงเชื่อถือได้ และด้วย การรองรับ Metal รวมถึงเครื่องมือเปรียบเทียบและ visualization ที่ใช้งานง่าย จึงช่วยเพิ่มประสิทธิภาพในการพัฒนาได้มาก
ข้อดีหลักเมื่อเทียบกับโปรเจกต์ประเภทเดียวกันมีดังนี้:
- แยก precision ของคีย์-แวลู เพื่อให้จัดการหน่วยความจำได้มีประสิทธิภาพยิ่งขึ้น
- ออกแบบมาเฉพาะสำหรับ Apple Silicon และรองรับการปรับแต่งเต็มรูปแบบกับเฟรมเวิร์ก Metal
- มี benchmark, perplexity, การวัดหน่วยความจำ/ความเร็ว/คุณภาพ และ visualization ให้แบบครบชุด
- ติดตั้งด้วยคำสั่งเดียว, รองรับโมเดล, ผสานรวมกับ llama.cpp
- มีการ แสดงภาพการประหยัดหน่วยความจำแบบเรียลไทม์ และเครื่องมือทดสอบเปรียบเทียบหลากหลาย
คุณสมบัติเด่นและสาระสำคัญ
ภาพรวม
- ใช้ KVSplit แล้วสามารถรัน LLM ที่ใหญ่กว่าเดิมมาก และ ความยาวคอนเท็กซ์ที่ยาวขึ้น บน Apple Silicon ได้
- ด้วยการ กำหนด precision สำหรับคีย์และแวลูแยกกัน จึงได้ทั้งการประหยัดหน่วยความจำและการเพิ่มความเร็ว
- ยืนยันแล้วว่าสามารถ ประหยัดหน่วยความจำได้สูงสุด 72% และ เพิ่มความเร็ว (5-15%↑) โดยคุณภาพลดลงไม่ถึง 1%
- รองรับ Metal อย่างสมบูรณ์ เพื่อให้ได้ ประสิทธิภาพเร่งความเร็วสูงสุดบน Apple Silicon
ผล benchmark หลัก
- ในการตั้งค่า K8V4 (คีย์ 8 บิต, แวลู 4 บิต)
- ประหยัดหน่วยความจำ 59% และ คุณภาพลดลง 0.86% (อิงค่า perplexity)
- เร็วขึ้น 5.7% เมื่อเทียบกับ FP16
- ในการตั้งค่า K4V4 (คีย์/แวลู 4 บิตทั้งคู่)
- ประหยัดหน่วยความจำได้สูงสุด 72%
- แต่คุณภาพลดลงประมาณ 6% แนะนำสำหรับงานที่ไม่ไวต่อคุณภาพมากนัก
การเปรียบเทียบผลการประหยัดหน่วยความจำ
- จากฐาน FP16 ที่ 176MB (8K token)
- K8V8 (คีย์/แวลู 8 บิต) : 93.5MB (47%)
- K8V4 (คีย์ 8 บิต, แวลู 4 บิต) : 71.5MB (41%)
- K4V4 (คีย์/แวลู 4 บิต) : 49.5MB (28%)
ฟีเจอร์หลัก
- ฟังก์ชัน quantize แยกคีย์·แวลูของ KV cache
- ปรับแต่งเต็มรูปแบบสำหรับ Apple Silicon·Metal
- สคริปต์วิเคราะห์ benchmark/คุณภาพ(perplexity)/การใช้หน่วยความจำ
- เครื่องมือ visualization และการสร้างกราฟคุณภาพระดับงานตีพิมพ์
- ตั้งค่าด้วยคำสั่งเดียวและฟังก์ชันเปรียบเทียบแบบเรียลไทม์
โครงสร้างโฟลเดอร์โปรเจกต์
- llama.cpp: รวม build ที่ปรับแต่งสำหรับ Metal
- models: เก็บไฟล์โมเดล
- scripts: รวมสคริปต์สำหรับ benchmark/ติดตั้ง/เปรียบเทียบ/visualization
- results, plots: เก็บผล benchmark และไฟล์ visualization
- README.md
อินไซต์เชิงวิทยาศาสตร์และผลการทดลอง
ปรากฏการณ์สำคัญของ KV cache
- เวกเตอร์คีย์ มี ความไวต่อการ quantize สูงกว่าเวกเตอร์แวลูมาก → จึงต้องให้คีย์มี precision สูงกว่าเพื่อรักษาคุณภาพ
- K8V4 คือ sweet spot: การจัดสรรคีย์ 8 บิต/แวลู 4 บิต ให้จุดสมดุลที่ดีที่สุดระหว่างคุณภาพกับหน่วยความจำ
- ประหยัดหน่วยความจำ 59%, ค่า perplexity แย่ลงเพียง 0.86%, และยังเร็วกว่า FP16
- K4V8 แม้จะใช้จำนวนบิตรวมเท่ากับ K8V4 แต่กลับมี คุณภาพลดลงมากกว่า 7 เท่า → ยืนยันความสำคัญของ precision ฝั่งคีย์
ข้อสรุปโดยรวม
- ทำได้ทั้ง เพิ่มประสิทธิภาพด้านหน่วยความจำ และ รักษาคุณภาพของโมเดล → ช่วยให้ฮาร์ดแวร์ระดับผู้บริโภคสามารถรันคอนเท็กซ์ที่ยาวขึ้นมากและโมเดลที่ใหญ่ขึ้นได้
ตัวอย่างการใช้งานและคำแนะนำการตั้งค่า
ตัวอย่างการรันด้วย precision ของการ quantize แบบต่าง ๆ
- ค่าเริ่มต้น (FP16): ./llama.cpp/build/bin/llama-cli -m models/your-model.gguf -p "พรอมป์ต์" -t 8 --flash-attn
- แนะนำ K8V4: --kvq 8
- K4V8 (DEMO): --kvq-key 4 --kvq-val 8
- K4V4 (ประหยัดสูงสุด): --kvq 4
ตัวอย่างคอนเท็กซ์ยาว
- คอนเท็กซ์ 32K: FP16 ต้องใช้ประมาณ ~1.4GB แต่ K8V4 สามารถรันได้ด้วย ~400MB
คำอธิบาย command-line flags
-t 8: จำนวนเธรด, แนะนำ 8 สำหรับ M1/M2/M3--flash-attn: การปรับแต่งสำหรับ Apple Silicon--kvq N: ตั้งค่าคีย์/แวลูเป็น N บิตทั้งคู่--kvq-key,--kvq-val: รองรับการตั้งค่าแยกกัน-c N: จำนวน token ของคอนเท็กซ์ (ยิ่งยาวยิ่งเห็นผลของ KVSplit ชัด)-n N: จำนวน token ที่จะ generate-f FILE: ไฟล์เอกสารนำเข้า-m MODEL: พาธของโมเดล
Benchmark ขั้นสูงและ visualization
- ใช้ benchmark_kvsplit.py เพื่อวัดคุณลักษณะด้านการตั้งค่าแต่ละแบบ, ความยาว sequence, หน่วยความจำ/ความเร็ว/perplexity/การสเกล
- ใช้ visualize_results.py เพื่อสร้างกราฟระดับงานวิจัย
- บันทึกผลเป็น CSV/JSON อัตโนมัติพร้อมสรุปให้
การปรับแต่งสำหรับ Apple Silicon และการแสดงภาพหน่วยความจำ
- ใช้งาน เฟรมเวิร์ก Metal ได้เต็มรูปแบบ
- ให้ผลชัดเจนอย่างยิ่งกับเครื่อง M1/M2/M3 ที่มีข้อจำกัดด้านหน่วยความจำ
- ใช้ capture_memory.sh เพื่อแสดงภาพการประหยัดหน่วยความจำแบบเรียลไทม์ได้
- การจัดเรียงเพจแบบกำหนดเองอาจทำให้ปริมาณที่ประหยัดได้จริงต่างจากค่าทางทฤษฎีเล็กน้อย
สรุปฟังก์ชันเด่น
- precision บิตของคีย์/แวลูแบบอิสระ และการ quantize แบบปรับแต่งได้
- Apple Silicon และ Metal ที่ปรับแต่งมาอย่างสมบูรณ์
- มี benchmark แบบครบวงจร ด้านหน่วยความจำ/ความเร็ว/คุณภาพ
- รองรับ visualization คุณภาพระดับงานวิจัยและการเปรียบเทียบแบบเรียลไทม์ รวมถึงการจับภาพหน่วยความจำ
- อินเทอร์เฟซติดตั้ง/ใช้งานที่ง่ายมาก
งานอ้างอิงและการวิจัยที่เกี่ยวข้อง
- "More for Keys, Less for Values: Adaptive KV Cache Quantization" (2024)
- "Unifying KV Cache Compression for Large Language Models with LeanKV" (2025)
- อิมพลีเมนเทชันพื้นฐาน: [llama.cpp], โมเดลทดสอบ: [TinyLlama]
คำแนะนำการตั้งค่าและแผนในอนาคต
- K8V4 (คีย์ 8 บิต/แวลู 4 บิต) : คุณภาพลดลง 0.86%, ประหยัดหน่วยความจำ 59%, ความเร็ว +5.7% เป็นสมดุลที่ดีที่สุด
- K4V4: ประหยัดหน่วยความจำได้สูงสุด (72%) แต่คุณภาพลดลงประมาณ 6% เหมาะกับงานที่ให้ความสำคัญกับหน่วยความจำเป็นอันดับแรก
- เด่นเป็นพิเศษสำหรับ การรันคอนเท็กซ์ยาว โดยรองรับคอนเท็กซ์ที่ยาวขึ้นได้ 2-3 เท่า
โรดแมปในอนาคต
- precision แบบปรับตามความสำคัญของ token
- การ quantize แยกตามเลเยอร์
- การปรับแต่งเฉพาะโมเดล (Mistral, Phi-3 เป็นต้น)
- เตรียมรองรับ เว็บเดโม และมือถือ (iOS/iPadOS)
ใบอนุญาตและการมีส่วนร่วม
- ใบอนุญาต MIT
- นักพัฒนา/นักวิจัย AI ทุกคนสามารถร่วมพัฒนาผ่าน Issue และ PR ได้
1 ความคิดเห็น
ความเห็นบน Hacker News
แสดงความสนใจว่าเรื่องนี้น่าสนใจ ถามถึงสัญชาตญาณและเส้นทางการค้นพบว่าทำไมปรากฏการณ์นี้จึงเกิดขึ้น เสนอให้ปรับปรุงความเป็นมิตรต่อผู้ใช้ เช่น ขั้นตอนการใช้แพตช์ในสคริปต์ติดตั้งที่ยังไม่สมบูรณ์และการใช้ git submodule รวมถึงเสนอให้แยก llama.cpp ออกจาก dependency ของ Python เพื่อรองรับสภาพแวดล้อม Python ที่หลากหลาย
ถามว่าแพตช์นี้จะใช้กับ MLX ได้หรือไม่ โดยคาดหวังว่า MLX จะให้ความเร็วได้ดีกว่าและแนวทางนี้จะช่วยให้ผู้ใช้ Mac สนับสนุนบทสนทนายาว ๆ ด้วยความเร็วระดับใช้งานจริงได้
ถามว่ามันต่างจากตัวเลือก
--cache-type-k,--cache-type-vในทางปฏิบัติหรือไม่หลังอ่านโค้ดแล้วสรุปว่าแพตช์นี้ไม่จำเป็น โดยตรวจจากลิงก์ PR ว่าฟังก์ชันนี้ถูกรวมเข้า llama.cpp ตั้งแต่ปี 2023 แล้ว จึงเตือนว่าควรระวังการถูกชักชวนให้รัน install.sh ในลักษณะใช้แพตช์แทนที่จะใช้ fork repository โดยตรง อีกทั้งชี้ว่า repository มีไฟล์แพตช์หลายชุด โค้ดซ้ำซ้อน และมีการเขียนทับไฟล์แพตช์ ทำให้โครงสร้างสับสน ที่จริงแล้วเพิ่มเพียงตัวเลือก
--kvqทั้งที่มีตัวเลือก quantization แยก K/V อยู่แล้ว จึงสงสัยว่าผู้เขียนไม่น่าจะไม่รู้เรื่องฟังก์ชันเดิมนี้ พร้อมแนะนำว่าไม่ควรรันสคริปต์จาก repository ที่มีสคริปต์ซับซ้อนแบบนี้ แม้โพสต์บน HN และจำนวนดาวบน GitHub จะสูง แต่เนื้อหากลับชวนให้เข้าใจผิด และยังน่ากังวลที่ผู้เขียนคอยหลบเลี่ยงคำถาม นอกจากนี้ยังสรุปว่าทั้ง repository และสคริปต์ปะปนกับ codebase llama.cpp รุ่นเก่าและไม่สอดคล้องกับโครงสร้างล่าสุด จึงยิ่งสร้างความสับสนถามว่าสามารถใช้ differential KV quantization (เช่น K8V4) กับโมเดลฟอร์แมต .gguf ที่แปลงไว้แล้วได้หรือไม่ และมีข้อจำกัดเรื่องชนิดของโมเดลหรือการตั้งค่า tokenizer หรือไม่
--kvq-keyและ--kvq-valโดยตนทดสอบสำเร็จกับโมเดลหลายตัว เช่น LLama-3, Mistral, Phi-2/Phi-3, TinyLlama, Qwen เป็นต้น แต่ใช้ได้เฉพาะกับ backend Metal ของ llama.cpp และเนื่องจาก Flash Attention จะข้าม custom KV cache format ในตอนนี้ จึงต้องใช้ตัวเลือก-fa 0นอกนั้นถ้าเป็นโครงสร้าง transformer ที่ใช้ attention ก็ใช้งานได้ทั้งหมดถามว่าแพตช์นี้เร็วขึ้นหรือดีกว่าหรือไม่บน Apple Silicon ที่มีหน่วยความจำสูง เช่น 64GB, 128GB โดยบอกว่าเคยได้ยินว่าการขยาย context window บน Apple Silicon ช้าอยู่แล้ว และสงสัยว่ามันมีความหมายจริงหรือไม่เมื่อมีหน่วยความจำมาก
แสดงความสนใจและขอคำอธิบายในมุมมองที่สูงขึ้นอีกหน่อย ถามว่าสามารถใช้ขยายโมเดล 2048 โทเคนไปเป็น 4~6k ได้หรือไม่ หรือใช้โมเดล context 128k เป็นหน้าต่าง 256k+ ได้หรือไม่ รวมถึงถามถึงกรณีใช้งานที่เหมาะที่สุดของโมเดลโลคัล
ชื่นชมว่าเป็นไอเดียและความพยายามที่ดีมาก พร้อมถามเพิ่มเติมว่าจะใช้กับ GPU ได้หรือไม่ และจะใช้ร่วมกับเทคนิค quantization อื่นได้หรือไม่
--cache-type-k,--cache-type-vอยู่แล้ว แพตช์ปัจจุบันอาจเจาะจงเพื่อ Metal แต่หลักการย้ายไปใช้ได้ตรง ๆ และยังใช้ร่วมกับเทคนิค quantization อื่นได้ เพราะ KV cache quantization ถูกใช้เฉพาะระหว่างรัน ไม่ชนกับ weight quantization เนื่องจากเป็นคนละขั้นของ pipeline อย่างไรก็ตาม engine อย่าง vLLM, TensorRT-LLM ที่มีโครงสร้าง cache ของตัวเองจะต้องมีการพัฒนาแยกต่างหาก และผลที่เด่นที่สุดบน GPU น่าจะเกิดเมื่อรวมเข้ากับสถาปัตยกรรม FlashAttention โดยตรง ซึ่งการประหยัดหน่วยความจำอาจแปลงเป็นความเร็วที่เพิ่มขึ้นได้ระบุว่ายังมีจุดที่ไม่เข้าใจและรู้สึกว่ามีบางอย่างแปลก ๆ พร้อมแนะนำว่าอย่ารันสคริปต์นี้ และแจ้งว่าได้รายงานแล้ว
ถามว่าสมรรถนะเปลี่ยนไปอย่างไร เพราะแม้จะใส่ context ที่ยาวขึ้นในหน่วยความจำได้ สุดท้ายความเร็วคำนวณก็น่าจะเท่าเดิมไม่ใช่หรือ