Arm CPUs पर, 8-bit 4-bit को पीछे छोड़ सकता है
Arm सर्वरों पर LLMs चलाने से जुड़ा एक ऐसा नतीजा जो सहज अनुमान के विपरीत है: 8-bit अक्सर 4-bit की तुलना में प्रीफ़िल ज़्यादा तेज़ी से करता है, और ज़्यादातर बिल्ड मुफ़्त मिलने वाले int8 स्पीडअप को बंद ही छोड़ देते हैं।
जब कोई लैंग्वेज मॉडल किसी CPU पर बहुत धीमा चलता है, तो उसका सबसे स्वाभाविक त्वरित उपाय उसे और ज़्यादा क्वांटाइज़ करना होता है। वेट्स को 16 बिट से घटाकर 8 पर लाएँ, और अगर यह अब भी धीमा है, तो घटाकर 4 पर ले आएँ। छोटे वेट्स, कम मेमोरी, तेज़ गणित। सहज अनुमान यही कहता है, और किसी Arm सर्वर पर यह अक्सर ग़लत होता है। आठ-बिट वाले वेट्स इनफ़रेंस के भारी कंप्यूट वाले हिस्से को चार-बिट वाले वेट्स की तुलना में ज़्यादा तेज़ी से चला सकते हैं, और आपके सामने मौजूद सबसे बड़ा स्पीडअप आमतौर पर क्वांटाइज़ेशन के बजाय एक ऐसा बिल्ड फ़्लैग होता है जिसे सेट करना आप भूल गए थे।
समय असल में कहाँ लगता है
किसी मॉडल को चलाने के दो चरण होते हैं जिनकी अड़चनें एक-दूसरे के बिल्कुल विपरीत होती हैं, और उन्हें एक मान लेने से ही ज़्यादातर उलझन शुरू होती है। प्रीफ़िल वह चरण है जब मॉडल आपके प्रॉम्प्ट को पढ़ता है। इसमें शुरू से आख़िर तक मैट्रिक्स मल्टीप्लिकेशन होता है, और यह इस बात से सीमित होता है कि चिप वह गणित कितनी तेज़ी से कर सकती है। डिकोड वह चरण है जब मॉडल एक-एक टोकन करके अपना जवाब लिखता है, और यह मेमोरी बैंडविड्थ से सीमित होता है, क्योंकि हर एक टोकन के लिए पूरे मॉडल को मेमोरी से बाहर स्ट्रीम करना पड़ता है। Arm की अपनी प्रोफ़ाइलिंग के अनुसार, मेमोरी स्टॉल के कारण जाने वाले समय का हिस्सा प्रीफ़िल के दौरान लगभग 10 प्रतिशत और डिकोड के दौरान क़रीब 50 प्रतिशत होता है (Arm)।
क्वांटाइज़ेशन इन दोनों में अलग-अलग तरह से काम करता है। डिकोड में, कम बिट्स का मतलब है प्रति टोकन कम बाइट्स इधर-उधर ले जाना, इसलिए 4-bit मॉडल वाक़ई ज़्यादा तेज़ होता है। प्रीफ़िल में, वेट्स के आकार से ज़्यादा यह मायने रखता है कि हार्डवेयर उन्हें कितनी तेज़ी से गुणा कर सकता है। यहीं पर Arm जवाब बदल देता है।
int8 matmul पाथ
Armv8.6 और उसके बाद के Arm कोर्स में एक इंस्ट्रक्शन, smmla, होता है जो सीधे हार्डवेयर में 8-bit इंटीजर मैट्रिक्स को गुणा करता है (Arm)। प्रीफ़िल के लिए, जो लगभग पूरी तरह से मैट्रिक्स मल्टीप्लिकेशन ही है, यह फ़ास्ट लेन है, और llama.cpp अपने ख़ुद के Arm कर्नल्स और Arm की KleidiAI माइक्रोकर्नल लाइब्रेरी, दोनों के ज़रिए इसका इस्तेमाल करता है।
पेंच यह है कि यह फ़ास्ट लेन केवल कुछ ख़ास आकारों को ही स्वीकार करती है। int8 कर्नल्स उन वेट्स पर काम करते हैं जो सादे 8-bit ब्लॉक्स के रूप में स्टोर होते हैं: Q8_0, और 4-bit वाला Q4_0 फ़ॉर्मेट जब उसे रीपैक कर दिया जाता है। लोकप्रिय K-quants, Q4_K_M और Q5_K_M, एक ज़्यादा विस्तृत ब्लॉक लेआउट का इस्तेमाल करते हैं, और ऐतिहासिक रूप से उनके पास कोई int8 कर्नल नहीं था, इसलिए वे एक धीमे सामान्य-उद्देश्य वाले पाथ पर चले जाते थे। KleidiAI का एक्सेलरेटेड पाथ विशेष रूप से Q4_0 और Q8_0 फ़ॉर्मेट्स के लिए है (Arm)।
इसलिए रैंकिंग उलट जाती है। एक Q8_0 मॉडल को int8 फ़ास्ट पाथ मिलता है और वह अपनी लगभग पूरी क्वालिटी बनाए रखता है। एक Q4_K_M मॉडल आकार में आधा होता है, लेकिन प्रीफ़िल के दौरान धीमे रास्ते से गुज़रता है। एक साधारण 2-vCPU Arm बॉक्स पर एक छोटे मॉडल में, आठ-बिट ने प्रॉम्प्ट को लगभग 237 टोकन प्रति सेकंड पर चलाया, जबकि चार-बिट Q4_0 के लिए यह रफ़्तार 171 रही। बड़े वेट्स ज़्यादा तेज़ साबित हुए, क्योंकि int8 कर्नल उन्हें पहले अनपैक करने का चरण छोड़ देता है।
एक ज़रूरी बात, क्योंकि स्टैक के इस हिस्से में बदलाव बहुत तेज़ी से होते हैं: 2025 के मध्य में Arm ने Q4_K और Q6_K के लिए भी int8 कर्नल्स का योगदान दिया है (Arm)। मौजूदा बिल्ड पर यह अंतर ऊपर दिए गए आँकड़ों की तुलना में कम है; किसी पुराने बिल्ड पर यह और ज़्यादा है। और असल में यही मुख्य सीख है। जो कर्नल चलता है वह आपके बिल्ड का गुण है, आपके मॉडल का नहीं, इसलिए वर्ज़न को पिन करें और मापें।
वह मुफ़्त स्पीडअप जिससे ज़्यादातर बिल्ड चूक जाते हैं
कंपाइल करते समय int8 पाथ ऑप्ट-इन होता है, और इसमें ग़लती होना बहुत आसान है। अगर आप सही -march फ़ीचर्स के बिना, या KleidiAI के बिना llama.cpp को बिल्ड करते हैं, तो यह चुपचाप धीमे कर्नल्स पर वापस चला जाता है। आपको कोई चेतावनी नहीं मिलती। उसी मॉडल और उसी मशीन पर int8 पाथ चालू करने से, हमारे एक प्रीफ़िल बेंचमार्क की रफ़्तार लगभग 360 से बढ़कर 500 टोकन प्रति सेकंड पर पहुँच गई, यानी सिर्फ़ एक बिल्ड फ़्लैग की क़ीमत पर क़रीब एक-तिहाई ज़्यादा तेज़। अगर दूसरी दिशा में ग़लती हो जाए तो उसका नुक़सान बहुत भारी पड़ता है: रिपोर्ट की गई एक ग़लत कॉन्फ़िगरेशन ने प्रॉम्प्ट प्रोसेसिंग को 80 प्रतिशत से भी ज़्यादा गिराकर 16.7 से 2.3 टोकन प्रति सेकंड पर ला दिया, और इसकी वजह बताने वाला कोई एरर भी नहीं आया (llama.cpp issue #10662)।
यह एक ऐसी बढ़त है जो किसी मॉडल कार्ड पर कभी दिखाई नहीं देती, क्योंकि इसका संबंध वेट्स से नहीं है। इसका संबंध इस बात से है कि आपने जो बाइनरी बिल्ड की है, क्या वह वाक़ई उन इंस्ट्रक्शंस का इस्तेमाल कर रही है जो आपके CPU में पहले से मौजूद हैं।
तीन बातें जो आपको एक ख़राब बेंचमार्क से बचाती हैं
प्रीफ़िल का नतीजा एक थ्रूपुट नतीजा है। अगर आपके वर्कलोड में लंबे प्रॉम्प्ट और छोटे जवाब शामिल हैं, तो प्रीफ़िल हावी रहता है और int8 पाथ पर Q8_0 को पीछे छोड़ना मुश्किल है। अगर आप एक बार में एक स्ट्रीम के रूप में लंबे पैसेज जनरेट कर रहे हैं, तो डिकोड हावी रहता है, आप बैंडविड्थ से बंधे होते हैं, और एक छोटा क्वांट आगे निकल सकता है। चुनाव करने से पहले यह जान लें कि आप किस स्थिति में काम कर रहे हैं।
मॉडल की मूल प्रेसिजन से क्वांटाइज़ करें। हाल के ज़्यादातर मॉडल bf16 में ट्रेन किए जाते हैं, और किसी bf16 सोर्स से सीधे Q8_0 पर जाने से वे संख्याएँ सुरक्षित रहती हैं, जबकि पहले 16-bit फ़्लोट से होकर गुज़रने पर वे चुपचाप राउंड ऑफ़ हो सकती हैं (llama.cpp quantize docs)।
और असली टार्गेट पर ही मापें। यह पूरा असर Arm सर्वर CPUs पर होता है। किसी Apple Silicon Mac पर, llama.cpp Metal के ज़रिए GPU पर चलता है, जो बिल्कुल ही अलग पाथ है, इसलिए Mac बड़ी आसानी से इस रिग्रेशन को छिपा लेगा और आपको गुमराह कर देगा (bartowski)। अगर आप Graviton या किसी अन्य Neoverse-क्लास सर्वर के लिए शिप कर रहे हैं, तो बेंचमार्क वहीं करें।
मुख्य निष्कर्ष
एक और बिट घटा देने की सहज प्रवृत्ति असल में रफ़्तार का भेष पहने हुए एक मेमोरी ऑप्टिमाइज़ेशन है। किसी Arm CPU पर रफ़्तार इस बात से मिलती है कि आप सिलिकॉन की ख़ूबी से मेल खाएँ, जो कि 8-bit इंटीजर्स को गुणा करना है, और इसे पाने का सबसे सस्ता तरीक़ा है सही ढंग से बिल्ड करना और उसी मशीन पर बेंचमार्क करना जिस पर आप असल में इसे चलाएँगे। छोटा मॉडल हमेशा ज़्यादा तेज़ नहीं होता। सीधे असली हार्डवेयर पर मापें।
संदर्भ और आगे पढ़ने के लिए
- Arm, "Optimize llama.cpp with the Arm i8mm instruction," 2025.
- Arm, "Profiling llama.cpp: prefill vs. decode," learning path.
- Arm, "KleidiAI integration in llama.cpp," learning path.
- llama.cpp, "Quantize documentation."
- llama.cpp, "Issue #10662: i8mm not detected, prompt-processing regression."
- bartowski, "Q4_0_N_M file types are going away."
- AWS, "Graviton getting started: llama.cpp."
ऐसे उद्धृत करें
Aika Labs. 'Arm CPUs पर, 8-bit 4-bit को पीछे छोड़ सकता है.' aikalabs.ai/hi/blog/8-bit-beats-4-bit-arm-cpus, 2026-06-21.