- KVSplit का लक्ष्य Apple Silicon पर LLM के attention KV cache में key और value के लिए अलग-अलग quantization precision लागू करके उसी memory budget में लंबे context और भारी models चलाना है
- मुख्य परिणाम K8V4 configuration है, जिसमें 8K tokens पर FP16 के 176.00MB की तुलना में memory घटकर 71.50MB हो जाती है, token processing speed 54,360 tokens/sec से बढ़कर 57,438 tokens/sec होती है, और perplexity बदलाव +0.86% बताया गया है
- इस निष्कर्ष के आधार पर कि key, value की तुलना में quantization के प्रति अधिक संवेदनशील है, समान कुल bit count इस्तेमाल करने वाला K4V8, K8V4 की तुलना में लगभग 7 गुना अधिक quality degradation दिखाता है
- उपलब्ध features में llama.cpp patch लागू करना, Metal-supported build, memory·speed·perplexity benchmarks, CSV/JSON result saving, visualization tools, और Activity Monitor आधारित memory reduction capture शामिल हैं
- recommended configuration quality और memory saving के balance के लिए K8V4 है; अगर maximum memory saving चाहिए, तो K4V4 के साथ 72% saving और लगभग 6% quality loss स्वीकार करने का विकल्प है
KVSplit जिस समस्या को हल करना चाहता है
- KVSplit Apple Silicon Mac पर LLM inference के दौरान KV cache memory कम करने का project है
- attention mechanism के KV cache में key और value पर अलग-अलग quantization precision लागू करता है
- लक्ष्य इस प्रकार हैं
- memory usage में अधिकतम 72% reduction
- समान memory budget में 2-3 गुना लंबे context चलाना
- FP16 की तुलना में inference speed बनाए रखना या सुधारना
- Apple Silicon के लिए tuned Metal support देना
मुख्य benchmark results
- 8K tokens के आधार पर configuration-wise results इस प्रकार हैं
- FP16: 176.00MB, 54,360 tokens/sec
- K8V8: 93.50MB, 51,503 tokens/sec, perplexity +0.03%
- K8V4: 71.50MB, 57,438 tokens/sec, perplexity +0.86%
- K4V8: 71.50MB, 58,690 tokens/sec, perplexity +6.06%
- K4V4: 49.50MB, 55,193 tokens/sec, perplexity +6.15%
- memory reduction table में K8V4 को 8K tokens पर 59% saving, और K4V4 को 72% saving के रूप में दिखाया गया है
- performance table में K8V4 FP16 की तुलना में +5.7%, K4V8 +8.0%, और K4V4 +1.5% speed improvement दिखाते हैं
- K8V8 FP16 की तुलना में memory घटाता है, लेकिन speed -5.3% तक कम हो जाती है
sequence length के अनुसार memory usage
- context length जितनी लंबी होती है, KV cache memory reduction का असर उतना बड़ा होता है
- 8192 tokens पर memory usage इस प्रकार है
- FP16: 176.00MB
- K8V8: 93.50MB
- K8V4: 71.50MB
- K4V8: 71.50MB
- K4V4: 49.50MB
- 4096 tokens पर भी FP16 88.00MB की तुलना में K8V4/K4V8 35.75MB, और K4V4 24.75MB इस्तेमाल करता है
- 128 tokens पर FP16 5.50MB, K8V4/K4V8 2.23MB, और K4V4 1.55MB बताया गया है
key और value की asymmetry
- KV cache memory में हर token के key vector और value vector का storage प्रमुख हिस्सा होता है
- project का मुख्य observation यह है कि key, value की तुलना में quantization के प्रति कहीं अधिक संवेदनशील है
- K8V4 8-bit key और 4-bit value इस्तेमाल करके यह balance point देता है
- FP16 की तुलना में perplexity degradation 0.86%
- memory reduction 59%
- FP16 से तेज inference speed
- K4V8, K8V4 जितने ही कुल bits इस्तेमाल करता है, लेकिन quality degradation K8V4 से लगभग 7 गुना अधिक बताया गया है
- बताया गया है कि इसी asymmetry की वजह से consumer hardware पर लंबे context और बड़े models चलाना संभव होता है
installation और integration तरीका
- installation repository clone करने के बाद
scripts/install_kvsplit.sh चलाने के तरीके से होता है
git clone https://github.com/dipampaul17/KVSplit.git
cd kvsplit
chmod +x scripts/install_kvsplit.sh
./scripts/install_kvsplit.sh
- installation script Python environment setup का तरीका चुनने देता है
- Virtual Environment: project folder के अंदर स्वतंत्र Python environment बनाना
- System Python: मौजूदा Python installation इस्तेमाल करना
- Skip Python Setup: user खुद Python environment manage करे
- llama.cpp integration method भी चुना जा सकता है
- standard method: llama.cpp clone करके KV split patch लागू करना
- Git submodule method: developers या advanced users के लिए llama.cpp को submodule के रूप में जोड़ना
- installation process में Apple Silicon के लिए Metal-supported llama.cpp setup, differentiated KV cache quantization enable करना, optional test model download, और visualization tool setup शामिल हैं
usage examples और CLI options
- quick comparison user के अपने GGUF model से चलाया जा सकता है
python scripts/quick_compare.py --model models/your-model.gguf
- comparison targets FP16, K8V8, K8V4, K4V8, K4V4 हैं और memory, speed, quality metrics साथ में दिखाते हैं
- README का execution example
llama-cli में --flash-attn और KV quantization options साथ में इस्तेमाल करता है
./llama.cpp/build/bin/llama-cli -m models/your-model.gguf -p "Your prompt" \
-t 8 --flash-attn --kvq 8
- K4V8 example key और value bits अलग-अलग specify करता है
./llama.cpp/build/bin/llama-cli -m models/your-model.gguf -p "Your prompt" \
-t 8 --flash-attn --kvq-key 4 --kvq-val 8
- 32K context example में FP16 के लिए लगभग 1.4GB, और K8V4 के लिए लगभग 400MB जरूरत बताई गई है
./llama.cpp/build/bin/llama-cli -m models/your-model.gguf \
-c 32768 -n 4096 -t 8 --flash-attn --kvq 8 \
-f your-long-document.txt
- मुख्य CLI flags इस प्रकार हैं
-t 8: thread count, अधिकांश Apple Silicon chips पर 8 recommended
--flash-attn: optimized attention enable करना, Apple Silicon पर recommended
--kvq N: key और value bit setting
--kvq-key N: केवल key bits set करना
--kvq-val N: केवल value bits set करना
-c N: context size
-n N: generate किए जाने वाले tokens की संख्या
-f FILE: input file
-m MODEL: .gguf model file path
benchmark और visualization tools
- full benchmark
scripts/benchmark_kvsplit.py से चलाया जाता है
python scripts/benchmark_kvsplit.py
python scripts/benchmark_kvsplit.py --config K8V4 --seq-len 4096
- visualization
scripts/visualize_results.py से generate होती है
python scripts/visualize_results.py
- benchmark निम्न items measure करता है
- Memory Usage: VRAM और KV cache memory
- Performance: sequence length के अनुसार tokens/sec
- Quality:
llama-perplexity इस्तेमाल करके perplexity
- Scaling: sequence length के अनुसार memory और performance changes
- results CSV/JSON format में save होते हैं और automatic summary statistics तथा visualization plots generate करते हैं
capture_memory.sh Activity Monitor में memory reduction capture करने का tool है
Apple Silicon optimization और constraints
- KVSplit Apple के Metal framework के लिए optimize किया गया है
- Apple Silicon M series जैसे memory-constrained devices में memory efficiency पर जोर देता है
- README बताता है कि llama.cpp के 256B page alignment की वजह से actual memory reduction theoretical calculation से थोड़ा अलग हो सकता है
- supported targets में M1, M2, M3, M4 chips शामिल हैं
recommended configuration और roadmap
- recommended configuration K8V4 है
- 8-bit key, 4-bit value
- 59% memory reduction
- 0.86% quality loss
- FP16 की तुलना में +5.7% inference speed
- maximum memory reduction K4V4 है
- 4-bit key और 4-bit value
- 72% memory reduction
- लगभग 6% quality loss
- कम sensitive applications के लिए उपयुक्त बताया गया है
- बहुत लंबे context के लिए K8V4 या K4V4 recommended हैं, और context length बढ़ने के साथ memory savings accumulate होती हैं
- future plans इस प्रकार हैं
- token importance आधारित Adaptive Precision
- layer-wise अलग precision इस्तेमाल करने वाला Layer-Specific Quantization
- Mistral, Phi-3 आदि के लिए model-specific optimization
- web demo
- iOS और iPadOS support
- license MIT है, और contributions issue या pull request के रूप में लिए जा सकते हैं
1 टिप्पणियां
Hacker News की राय
दिलचस्प। उत्सुकता है कि ऐसे नतीजे क्यों आते हैं, इस पर कोई intuition है या नहीं। यह भी जानना चाहूंगा कि इसे उसी intuition से खोजा गया, या random experiments से मिला।
installation script के "apply patch" चरण में अभी भी placeholder बचे हुए लगते हैं।
git cloneके बाद patch लगवाने के बजाय llama.cpp को fork करके उसे Git submodule के रूप में शामिल करना users के लिए ज्यादा friendly होगा।साथ ही हर किसी का local Python setup अलग-अलग होता है, इसलिए Homebrew Python dependency hardcode करने के बजाय llama.cpp वाले हिस्से और Python वाले हिस्से को अलग रखने की सुविधा हो तो अच्छा होगा।
keys तय करती हैं कि किन tokens पर ध्यान देना है, और similarity calculation के जरिए असली attention pattern बनाती हैं। values बस attention तय हो जाने के बाद भेजी जाने वाली जानकारी को store करती हैं।
key vectors को बहुत aggressive तरीके से quantize करने पर सभी token interactions की similarity calculation बिगड़ जाती है। key में छोटी error भी attention को बिल्कुल गलत token की ओर मोड़ सकती है।
values काफी ज्यादा tolerant होती हैं। value vector quantization error attention pattern पहले से तय हो जाने के बाद सिर्फ उस single token की information content को प्रभावित करती है।
यह library catalog system और किताबों के बीच फर्क जैसा है। catalog number (key) खराब हो जाए तो आप पूरी तरह गलत shelf देखने लगेंगे, लेकिन किताब के कुछ शब्द (value) धुंधले हो जाएं तो भी आप सही किताब पढ़ रहे होते हैं और बस कभी-कभी noise आता है।
गणितीय रूप से keys softmax calculation में जाती हैं, और छोटी errors normalization process में exponentially amplify हो जाती हैं। values सिर्फ linear weighted average से गुजरती हैं, इसलिए errors अक्सर cancel out हो जाती हैं।
शुरुआत में इस asymmetry के बारे में "More for Keys, Less for Values", "KV-AdaQuant" जैसे papers से पता चला, और मैं quantify करना चाहता था कि Apple Silicon inference में इसका असर ठीक कितना है। समान memory पर K8V4 और K4V8 के बीच quality gap 7x होना प्रभावशाली था।
installation feedback के लिए भी धन्यवाद, placeholder ठीक करूंगा और Python dependencies को ज्यादा flexible बनाऊंगा।
arg.cppमें move हो गई थी।फिर भी फर्क नहीं पड़ता, क्योंकि K और V quantization set करने वाले options llama.cpp में पहले ही 2023 में add हो चुके थे।
समझ नहीं आता यह patch मौजूद क्यों है। पहले से मौजूद settings को दूसरे command-line arguments में बदलकर नया जैसा दिखाने के अलावा कोई कारण नहीं दिखता।
ऐसे नए repository की
install.shfile किसी को भी न चलाने की मेरी कड़ी सलाह है। खासकर जब patch file apply करने जैसा साधारण काम हो और उसके लिए यह unnecessary हो।क्या यह
--cache-type-kऔर--cache-type-vइस्तेमाल करने से अलग है?repository की दूसरी अजीब बातों के बारे में मैंने कुछ दूसरे comment में लिखा है।
इसलिए पुराने
type_k/vतरीके और Apple GPU पर जितना नीचे जा सकते थे, वह 16-bit f16/bf16 रहा होगा। हालांकि मैं llama.cpp internals expert नहीं हूं, इसलिए गलत भी हो सकता हूं।सोच रहा हूं कि क्या यह patch MLX में भी किया जा सकता है। MLX में speed बेहतर मिल रही है, इसलिए अगर यह approach उसके साथ जुड़ जाए तो Mac users भी usable speed पर long conversations कर सकेंगे।
व्यक्तिगत रूप से मुझे जिस चीज़ की सबसे ज्यादा उम्मीद है, यकीन करना मुश्किल होगा, वह Haskell bindings हैं। कुछ दिन पहले किसी ने बताया कि Haskell की lazy evaluation इस paradigm के साथ काफी अच्छी तरह fit होती है, और compile graph के लिए लगभग pure functional approach भी मददगार है। Haskell में machine learning करना मजेदार होगा।
उत्सुकता है कि differential KV quantization (जैसे K8V4) को पहले से
.ggufformat में convert किए गए model पर apply किया जा सकता है या नहीं। या model को special support डालकर फिर से build करना पड़ेगा?अगर यह किसी भी
.gguffile के साथ compatible है, तो model types (Mistral, Phi-3 आदि) या tokenizer settings पर कोई restriction है या नहीं, यह भी जानना चाहूंगा।.ggufmodels को reconstruct या special convert किए बिना सीधे इस्तेमाल किया जा सकता है। quantization model loading या conversion के दौरान नहीं, बल्कि runtime KV cache में होती है।KV cache tokens process करते समय inference के दौरान बनता है और model weights से पूरी तरह अलग होता है, इसलिए यह संभव है।
--kvq-keyऔर--kvq-valflags llama.cpp को सिर्फ यह बताते हैं कि इन intermediate tensors को memory में कैसे store करना है।Llama-3, Mistral, Phi-2/Phi-3, TinyLlama, Qwen variants पर सफलतापूर्वक test किया है।
सिर्फ restriction यह है कि llama.cpp का Metal backend चाहिए, और अभी llama.cpp का Flash Attention implementation custom KV cache format को bypass करता है, इसलिए
-fa 0से Flash Attention बंद करना होगा। technique अपने-आप में standard attention mechanism इस्तेमाल करने वाली किसी भी transformer architecture पर काम करनी चाहिए।कोड पढ़ने का समय मिला। अगर मैंने इस PR को सही समझा है, तो यह patch गैर-ज़रूरी है, क्योंकि यह feature llama.cpp में 2023 से ही मौजूद था: https://github.com/ggml-org/llama.cpp/pull/4312
changes को commit के रूप में apply किए हुए llama.cpp fork देने के बजाय, repository
install.shscript चलवाती है। यह script कोई revision specify किए बिना llama.cpp की master branch checkout करती है और फिर एक छोटा patch apply करती है। सिर्फ यही बात भी कुछ गड़बड़ होने का warning sign हैrepository में 4 अलग-अलग patch files हैं, और install script के अंदर Heredoc के रूप में embedded एक और extra patch version है। script में repository clone करने और patch लगाने की कोशिश करने वाले code के भी दो versions हैं
install.shमेंcp patch/split_kv_quant.diff patch/fixed_kv_patch.diffline से एक patch file दूसरी patch file पर overwrite हो जाती है। इसलिए repository में checked-infixed_kv_patch.diffapply होने से पहले ही overwrite हो जाती हैमुझे लगता है मूल रूप से यह patch इस्तेमाल करने की मंशा थी: https://github.com/dipampaul17/KVSplit/blob/main/patch/split... (सुधार: आखिर की comments देखें तो असल में शायद यह वाला है: https://github.com/dipampaul17/KVSplit/blob/main/patch/fixed... )
यह patch सिर्फ
--kvqargument जोड़ता है, जो K और V quantization को एक साथ set करता है, जबकि ठीक ऊपर K और V quantization को अलग-अलग set करने वाले built-in arguments पहले से मौजूद हैं। क्या ऐसा हो सकता है कि इन patches को इधर-उधर करते समय लेखक ने यह नोटिस ही न किया हो कि feature पहले से मौजूद है?ऐसे नए repository के shell scripts चलाने से मैं strongly मना करूंगा। खासकर अगर script इतनी complex हो
HN post को 200 से ज़्यादा upvotes मिले हैं और GitHub repository को भी 200 से ज़्यादा stars मिले हैं और बढ़ते जा रहे हैं, लेकिन content misleading लगता है। इस thread में issue point out करते हुए बहुत flag हुए comment असल में सही था। यह भी चिंता की बात है कि लेखक इस thread में लगातार जवाब दे रहा है, लेकिन feature पहले से मौजूद होने वाले सवाल से बच रहा है
सुधार: मैंने shell script गलत पढ़ी थी। असल में यह patch apply करता लगता है: https://github.com/dipampaul17/KVSplit/blob/main/patch/fixed... patch apply करने के बाद अजीब तरह से
fixed_kv_patch.diffकोsplit_kv_quant.diffसे overwrite करता है, लेकिन उसके बाद कुछ नहीं करता। यह vibe coding का नतीजा है या बस careless code editing, पता नहीं, लेकिन मैं दोहराना चाहता हूं कि अनजान repository के ऐसे shell scripts नहीं चलाने चाहिएसुधार 2: और भी confusing है।
install.shscript llama.cpp repository के पुराने URL(https://github.com/ggerganov/llama.cpp) को refer करती है, जो काफी समय पहले बदल चुका है और अब redirect होता है। patchescommon.cppमें argument parsing modify करने की कोशिश करते हैं, लेकिन वह code 8 महीने पहलेarg.cppमें move हो चुका था(https://github.com/ggml-org/llama.cpp/commit/bfe76d4a17228bf...)। तो यह install script और repository 2024 के आसपास के code पर आधारित हैं, और 2023 के आसपास llama.cpp में जोड़ा गया option इस्तेमाल कर रहे हैं। आखिर हो क्या रहा है?warning sign बहुत हैं। अच्छा सोचें तो भी यह ऐसा व्यक्ति लगता है जो LLM-generated code से अपना GitHub profile inflate करना चाहता है। उस profile की 12 मई की activity ही देख लें
लेकिन original poster की पूरी GitHub activity ही suspicious है। 12 मई को उसने कई popular projects में LLM slop PRs भेजे, और सिर्फ JAX ने reject किया। फिर भी इसके जरिए वह popular projects को अपने profile पर ऐसे pin कर पाया मानो contributor हो
यह कितना घिनौना है, शब्दों में कहना मुश्किल है। AI field में काम करने वाला हर व्यक्ति information pollution में सहभागी है, और उसके नतीजे अभी predict भी नहीं किए जा सकते। dead internet और AI slop की बाढ़ तो बस शुरुआत है
64GB या 128GB Apple Silicon पर क्या ये 36GB या 48GB की तुलना में वाकई काफ़ी तेज़ या बेहतर हैं?
मैंने पढ़ा है कि बड़े context और बड़े model, पैसे से खरीदे जा सकने वाले सबसे तेज़ और बड़े Apple Silicon पर भी बेहद धीमे होते हैं
इसलिए सोच रहा हूँ कि क्या यह बड़ी memory का बेहतर इस्तेमाल करवाता है, या व्यावहारिक रूप से Apple Silicon पर अभी भी अपेक्षाकृत छोटे model ही सही जवाब हैं
हालांकि KVSplit compute speed को मूल रूप से नहीं बदलता, सिर्फ़ memory efficiency बदलता है। benchmark में K8V4 से throughput 14.5% बेहतर हुआ, लेकिन यह compute कम होने की वजह से नहीं, memory locality बेहतर होने की वजह से है
Apple Silicon पर बड़े model के "बेहद धीमे" होने की मुख्य वजह memory constraint नहीं, बल्कि compute performance की सीमा है। 70B parameter model उपलब्ध RAM या KV cache optimization से अलग, लगभग वैसी ही token generation speed पर चलेगा
KVSplit उपलब्ध memory का बेहतर इस्तेमाल करने देता है। यह खास तौर पर तब valuable है जब bottleneck model size के बजाय context length हो
practical Apple Silicon use में अभी भी छोटे model (7B~13B) के साथ extended context window लगाना sweet spot है। इससे reasonable generation speed बनाए रखते हुए कहीं ज़्यादा text process किया जा सकता है
अगर आपके workflow को विशाल context और बड़े model दोनों चाहिए, तो अभी भी server-grade GPU पर विचार करना होगा, लेकिन KVSplit Apple hardware पर संभव दायरे को थोड़ा और आगे बढ़ा देता है
शानदार काम है और बहुत दिलचस्प दिखता है, लेकिन समझने के लिए थोड़ी और high-level explanation चाहिए
उदाहरण के लिए, क्या यह 2048-token context window वाले model को 4~6K context window पर चला पाने देता है? या gemma3 जैसे 128K model को 256K+ context window पर चला पाने देता है?
local model का ideal use case क्या है?
practical तौर पर इसका मतलब है कि MacBook पर पूरी किताब एक बार में process करना, files को तोड़े बिना बड़े codebase का analysis करना, या chat application में लंबी conversation history बनाए रखना संभव हो सकता है
memory बचत context length के साथ linear रूप से proportional है। context window जितनी लंबी होगी, absolute memory saving उतनी बड़ी होगी। मेरे M4 MacBook पर 8K context में KV cache 176MB से घटकर 72MB हो गया। 128K context पर इसी ratio की saving gigabytes में memory खाली कर देगी
यह optimization तब सबसे valuable है जब आप model parameter limit के बजाय context window limit से टकरा रहे हों। अगर बड़े model weights नहीं बल्कि लंबे input की वजह से out-of-memory error आ रहा है, तो KVSplit सीधे bottleneck हल करता है
training के बाद context window बढ़ाना आसान नहीं है, इसलिए अगर आपको ठीक-ठीक पता नहीं है कि आप क्या कर रहे हैं, तो बेहतर है कि बड़े context window पर trained model ढूँढें
local model के use cases कई हैं, जैसे offline work, privacy/security आदि। हालांकि ज़्यादातर लोग model को tune करते हुए experiments के लिए इस्तेमाल करते हैं
कुछ अजीब चल रहा है, इसलिए बेहतर होगा कि इसे install न करें या वह script न चलाएँ
submission को flag कर दिया है
बढ़िया idea और प्रयास है। क्या यह GPU पर भी लागू होता है? और लगता है कि यह दूसरी quantization techniques के साथ भी compatible होगा; क्या शायद हर एक के लिए अलग patch चाहिए होगा?
llama.cpp का CUDA backend पहले से
--cache-type-kऔर--cache-type-vflags के साथ अलग cache type settings support करता है। यह specific patch Metal-only optimization पर focused है, लेकिन core technique ज्यों की त्यों port हो सकती हैदूसरी quantization methods के साथ भी compatibility है। यह KV cache optimization model weight quantization (Q4_K_M, GPTQ, AWQ आदि) के साथ complementary है। asymmetric KV cache precision को किसी भी model weight format के साथ इस्तेमाल किया जा सकता है
KV cache quantization token processing के दौरान runtime पर होता है और model weights से अलग है, इसलिए model खुद कैसे quantize हुआ है, उससे conflict नहीं करता। यह inference pipeline के अलग हिस्सों में काम करता है
जहाँ extra work चाहिए, वह vLLM या TensorRT-LLM जैसे special inference engines के साथ integration है जिनमें custom KV cache handling होती है। हर एक में asymmetric KV precision अलग से implement करनी होगी
GPU पर सबसे immediate gain शायद इस insight को FlashAttention implementation में सीधे integrate करने से आएगा। CUDA hardware पर memory bandwidth बचत और बड़ी speedup में बदल सकती है
छोटे context size पर perplexity +0.86% काफ़ी बड़ा नहीं है? 64~128K जैसे ज़्यादा realistic context sizes पर कैसा है?
या फिर बची हुई memory को IDE जैसे दूसरे use cases में इस्तेमाल किया जा सकता है