- बड़े LLM को GPU memory limits की वजह से deploy करना मुश्किल होता है, लेकिन DFloat11 BFloat16 weights को लगभग 70% आकार तक घटाते हुए भी मूल के साथ bit-for-bit समान output बनाए रखता है
- इसका मुख्य विचार यह है कि BFloat16 का 8-bit exponent वास्तव में केवल लगभग 2.6 bit जानकारी रखता है; sign और mantissa को जस का तस रखते हुए सिर्फ exponent को Huffman coding से compress किया जाता है
- dynamic-length encoding GPU पर bottleneck बन सकता है, इसलिए DFloat11 hierarchical LUT, 2-stage kernel, और transformer block-स्तर decompression के जरिए parallel inference के लिए अनुकूलित है
- Llama 3.3, Qwen 3, Mistral 3, DeepSeek R1 Distilled, FLUX.1, Stable Diffusion 3.5 आदि पर लगभग 30% model size reduction और मूल output के संरक्षण की पुष्टि हुई
- CPU offload विकल्पों की तुलना में token generation throughput 2.3–46.2 गुना अधिक है, और 8×80GB GPU single node पर 810GB आकार के Llama 3.1 405B का lossless inference संभव बनाता है
DFloat11 जिस memory bottleneck को लक्ष्य करता है
- LLM और Diffusion Model जैसे foundation model तेज़ी से बड़े होते जा रहे हैं, इसलिए memory-constrained hardware पर इन्हें efficient तरीके से deploy करना कठिन है
- Llama 3.1 405B, 405 अरब parameters को BFloat16 format में store करता है और full inference के लिए लगभग 810GB memory चाहिए
- यह 8×80GB GPU वाले सामान्य high-end GPU server की capacity से भी अधिक है
- अगर कई node चाहिए हों, तो deployment cost और accessibility का बोझ बढ़ जाता है
- DFloat11 का लक्ष्य BFloat16 model को उसके मूल आकार के लगभग 70% तक compress करना है, जबकि किसी भी task में accuracy को 100% सुरक्षित रखा जाए
lossy quantization से अलग दृष्टिकोण
- Quantization weights की precision घटाकर memory कम करने वाला lossy compression तरीका है
- यह memory usage को काफी कम कर सकता है और inference speed बढ़ा सकता है, लेकिन approximation error पैदा करता है
- accuracy loss base model, quantization method, evaluation benchmark, और target bit-width पर निर्भर करता है, इसलिए इसकी भविष्यवाणी करना मुश्किल है
- उदाहरण के लिए, DeepSeek-R1-Distill-Qwen-1.5B पर 8-bit SmoothQuant लागू करने से reasoning task की औसत accuracy 9.09% घट जाती है
- भले ही overall accuracy metric समान दिखे, quantized model मूल मॉडल से अलग answer behavior दिखा सकता है
- Dutta et al. ने flips की घटना देखी, जहाँ सही उत्तर गलत हो जाता है, या गलत सही में बदल जाता है
- W8A16 GPTQ से quantize किया गया Qwen2-1.5B, GSM8K 8-shot accuracy में केवल 0.3% गिरावट दिखाता है, लेकिन 6.37% उत्तरों में सही-गलत स्थिति बदल जाती है
- finance और healthcare जैसे क्षेत्रों में quantized model के output में बदलाव regulation और reliability की आवश्यकताओं को पूरा करना कठिन बना सकते हैं
- मौजूदा lossless model compression अधिकतर checkpoint storage efficiency, model hub download time कम करने, या FPGA जैसे विशेष hardware पर केंद्रित रहा है, इसलिए सामान्य GPU inference में इसका लाभ सीमित रहा है
BFloat16 exponent में बची हुई compression की गुंजाइश
- BFloat16, 16 bit को sign 1 bit, exponent 8 bit, mantissa 7 bit में बाँटता है
- DFloat11 की शुरुआत LLM weights के BFloat16 components के Shannon entropy विश्लेषण से होती है
- sign और mantissa की entropy उनकी bit-width के क़रीब है, इसलिए उनमें compression की गुंजाइश सीमित है
- exponent को 8 bit मिले हैं, लेकिन उसकी entropy केवल लगभग 2.6 bit है
- exponent values का distribution बहुत असंतुलित है
- संभावित 256 8-bit values में से केवल लगभग 40 ही उपयोग होती हैं
- बाकी values कभी दिखाई ही नहीं देतीं
- frequency ranking भी बहुत तेज़ी से घटती है
- कम entropy की वजह से exponent lossless compression के लिए उपयुक्त बनता है, और लगभग 5.4 bit exponent जानकारी compress की जा सकती है
DFloat11 format
- DFloat11 या DF11 एक dynamic-length floating-point format है जो BFloat16 weights के केवल exponent को entropy coding से compress करता है
- Huffman tree मॉडल weights के exponent distribution के आधार पर बनाया जाता है
- जो exponent values ज़्यादा बार आती हैं, उन्हें छोटे code दिए जाते हैं
- दुर्लभ values को लंबे code मिलते हैं
- sign और mantissa को मूल रूप में सुरक्षित रखा जाता है
- exponent को
EncodedExponentbyte array में bit-packed रूप में store किया जाता है - sign और mantissa को
PackedSignMantissabyte array में अलग से store किया जाता है
- exponent को
- नतीजतन BFloat16 weights औसतन लगभग 11 bit तक सिमट जाते हैं, और precision loss के बिना मूल BFloat16 values में restore किए जा सकते हैं
GPU inference के लिए अनुकूल decompression
- entropy-coded weights dynamic-length encoding का उपयोग करते हैं, इसलिए उन्हें सीधे matrix multiplication में नहीं डाला जा सकता
- ज़रूरी weight matrix को ठीक उसी समय मूल BFloat16 में decompress करना पड़ता है
- matrix multiplication खत्म होते ही BFloat16 matrix को GPU memory बचाने के लिए तुरंत discard कर दिया जाता है
- सामान्य Huffman decoding bit स्तर पर tree को sequentially traverse करता है, जो GPU की parallel architecture के अनुकूल नहीं है
- अगर एक ही thread decompression संभाले, तो GPU utilization कम और latency अधिक हो जाती है
hierarchical LUT आधारित decoding
- DFloat11, Huffman tree traversal की जगह lookup table आधारित decoding का उपयोग करता है
- अगर अधिकतम Huffman code length को L मानें, तो single LUT के लिए
2^Lआकार चाहिए- LLM में L आमतौर पर 24–32 के बीच होता है
2^32entries वाला LUT GPU SRAM में रखना कठिन है
- इससे बचने के लिए Huffman tree को height 8 वाले non-overlapping subtree में बाँटा जाता है, और हर subtree को 256-entry compact LUT में बदला जाता है
- hierarchical LUT में कुछ entries को lower LUT की ओर point करने वाले reference की तरह काम करना पड़ता है
- यह इस तथ्य का उपयोग करता है कि LLM exponent में कई values उपयोग ही नहीं होतीं
- 240–255 range की unused exponent values को internal pointer के रूप में फिर से इस्तेमाल किया जाता है
- ये values ±2^113 से ±2^128 स्तर के बहुत बड़े magnitude दिखाती हैं, जो LLM weights में नहीं आतीं
- प्रयोगों में BFloat16 exponent Huffman tree के compact LUT की संख्या k 4–8 के बीच रही
CodeLengthsके साथ अधिकतम(8 + 1) × 256 bytesmemory लगती है- यह आकार SRAM में फिट हो जाता है और repeated lookup को तेज़ बनाता है
2-stage GPU kernel और सहायक metadata
- हर GPU thread encoded exponent के लगातार n byte वाले segment को संभालता है
- प्रयोगों में n = 8 इस्तेमाल किया गया
- thread अपने segment के भीतर शुरू होने वाले Huffman code को decode करता है
- dynamic-length code की वजह से दो समस्याएँ पैदा होती हैं
- हर thread का सही starting bit position स्पष्ट नहीं होता
- पहले thread को छोड़कर decoded element का output index पता लगाना कठिन होता है
- पहली समस्या को Gaps array से हल किया जाता है
- Gaps में हर thread के लिए एक entry होती है
- हर entry, thread के starting byte के सापेक्ष पहले valid Huffman code का bit offset दिखाती है
- अधिकतम code length 32 bit होने पर offset
[0, 31]range में होता है और 5 bit में store किया जाता है
- output position की समस्या को thread block स्तर पर position store करके memory overhead कम किया जाता है
- अगर हर thread के लिए 32-bit output position store की जाए, तो प्रति weight matrix हज़ारों threads पर overhead बहुत बढ़ जाएगा
- DFloat11 केवल हर thread block के पहले element की output position store करता है
- kernel दो चरणों में काम करता है
- पहले चरण में हर thread अपने segment को decode करता है, लेकिन केवल element count गिनता है और HBM में कुछ नहीं लिखता
- block के भीतर threads Blelloch algorithm से prefix sum चलाकर हर thread की output position निकालते हैं
- दूसरे चरण में वही segment दोबारा decode किया जाता है, और निकाली गई position के अनुसार decoded values SRAM write buffer में लिखी जाती हैं
- duplicate global memory access से बचने के लिए encoded exponent को पहले pass से पहले SRAM में load कर लिया जाता है
- जब सभी decoded exponent SRAM में लिख दिए जाते हैं, तब HBM में एक बार coalesced write किया जाता है
Transformer block-स्तर decompression
- किसी एक weight matrix का decompression आकार में छोटा हो सकता है, इसलिए वह GPU resources का पूरा उपयोग नहीं कर पाता
- matrix का आकार बढ़ने पर DFloat11 decompression throughput बेहतर होता है
- throughput बढ़ाने और latency छिपाने के लिए कई matrix को साथ में decompress किया जाता है
- transformer block के भीतर सभी DFloat11 weight matrix को एक batch के रूप में decompress किया जाता है
- यह batched decompression उस transformer block के forward pass से ठीक पहले किया जाता है
- LLM के token embedding और language modeling head भी compression target हैं
- ये matrix इतने बड़े होते हैं कि GPU resources को saturate कर देते हैं, इसलिए इनके लिए अलग batching की ज़रूरत नहीं होती
मूल्यांकन परिणाम और वास्तविक प्रभाव
- DFloat11 का मूल्यांकन Llama 3, Qwen 3, Mistral 3, DeepSeek R1 Distilled, FLUX.1, Stable Diffusion 3.5 समेत LLM और diffusion transformer पर किया गया
- परिणाम लगभग 30% model size reduction और मूल output के पूर्ण संरक्षण को दिखाते हैं
- output मूल मॉडल के साथ bit-for-bit समान है
- क्योंकि यह lossy compression नहीं है, इसलिए मूल BFloat16 weight precision बनी रहती है
- memory constraints पूरा करने के लिए uncompressed model के कुछ हिस्से को CPU पर offload करने वाले विकल्प की तुलना में, DFloat11 token generation में 2.3–46.2 गुना अधिक throughput हासिल करता है
- तय GPU memory budget पर यह uncompressed model की तुलना में 5.7–14.9 गुना लंबी generation length संभव बनाता है
- Llama 3.1 405B, 810GB आकार का मॉडल है, लेकिन DFloat11 8×80GB A100 GPU single node पर lossless inference संभव बनाता है
- यह दिखाता है कि Llama-3.1-405B चलाने के लिए आवश्यक hardware requirements को आधा किया जा सकता है, और वह भी accuracy loss के बिना inference के साथ
1 टिप्पणियां
Hacker News की रायें
यह बस इस तथ्य का नतीजा है कि bfloat16 की dynamic range बहुत बड़ी है, लेकिन असल में उस पूरी range का इस्तेमाल नहीं होता
लोग hyperparameter को 10^10 के बजाय 0.01 जैसा दिखना पसंद करते हैं, लेकिन हर exponent के लिए वही relative precision इस्तेमाल की जा सकती है। नेटवर्क के hyperparameter, initialized weights, training data आदि सबको 10^6 गुना कर दें, तब भी upper range का बहुत कम इस्तेमाल होता है, इसलिए व्यवहार आम तौर पर लगभग वैसा ही रहता है। हालांकि कुछ special functions अपवाद हो सकते हैं
weights और activations में दिखने वाले bfloat16 values की typical entropy करीब 10–12 bits होती है, और असल में value range का लगभग 65–75% ही इस्तेमाल होता है। sign और mantissa bits ऐसे noise जैसे हैं जिन्हें compress करना मुश्किल है
इस गुण का classic high-performance computing और AI, दोनों में पहले भी कई बार फायदा उठाया गया है। Martin Burtscher lab का lossless compression काम(https://userweb.cs.txstate.edu/~burtscher/), LLNL का fpzip(https://computing.llnl.gov/projects/fpzip), और 2021 में बनाई गई मेरी library dietgpu(https://github.com/facebookresearch/dietgpu) इसके उदाहरण हैं। हमने बड़े GPU clusters में भेजने से पहले सभी data—जैसे gradients या backup से आए weights—को losslessly compress किया और receive करने पर decompress किया, जिससे कुल training wall-clock time करीब 10% घटा; और क्योंकि यह lossless था, compute results पहले जैसे ही रहे
साथ ही rANS, Huffman coding की तुलना में SIMD-जैसे instruction sets पर ज्यादा efficient है और implement करना भी आसान है। DFloat11 में भी arithmetic operations से पहले decompress करना पड़ता है, इसलिए latency और throughput loss कम किया जा सकता है
Quantization local LLM runners के लिए एक key tool है, और आम तौर पर RAM bottleneck होता है। BF16 weights के लिए कोई बेहतर lossless compression है या नहीं, यह भी जानना चाहूंगा
DFloat11 existing quantization workflow में अपेक्षाकृत आसानी से fit हो सकता लगता है, लेकिन paper इसे लेकर काफी skeptical लगता है, इसलिए समझना चाहता हूं कि मैं क्या miss कर रहा हूं
neural network layers में input को weights से multiply और add किया जाता है, फिर वह output अगली layer का input बनता है, और यह process सौ से ज्यादा बार repeat हो सकता है। final output layer तक पहुंचते-पहुंचते वह 10^6 factor कई बार लागू होकर 10^600 के स्तर तक snowball हो जाएगा
DFloat11 में tokens per second सिर्फ तब ज्यादा था जब तुलना कुछ layers को CPU पर offload करके की गई inference से थी
यह typical computer science वाला space-speed tradeoff है, और कोई free lunch नहीं है
फिर भी काटकर zero से fill करने की cost कम है
सबसे ज्यादा ध्यान खींचने वाली चीज इसके practical implications हैं। 405B parameter model को 8×80GB GPU वाले single node पर lossless inference के लिए चला पाना काफी हैरान करने वाला है
बिना विशाल infrastructure cost के frontier models चलाना चाहने वाली labs और startups, दोनों के लिए यह बड़ा unlock हो सकता है
शुक्र है कि हम इतने दिलचस्प दौर में जी रहे हैं। HN खोलते ही machine learning और transformer models से जुड़ी नई खबरें लगातार दिखती रहती हैं
और गहराई से पढ़ना पड़ेगा, लेकिन सोच रहा हूं कि llama.cpp cuBLAS के साथ किसी तरह का custom kernel इस्तेमाल करता है, या बस cuBLAS kernels का अच्छा उपयोग करता है
2 हफ्ते? दो महीने? दो दिन? 2 मिनट?
कभी-कभी सब सही होते हैं। वाकई दिलचस्प दौर है
जब यह weight format war settle हो जाएगी, तो hardware को उसे support करने के लिए बनाया जा सकेगा। जो भी reasonably optimal weight format तय हो, उसके हिसाब से optimized matrix multiplication hardware की जरूरत होगी
असली agent use cases में quality, cost और performance का balance बनाना अक्सर मुश्किल होता है। यह technique agent cost optimize करते समय quantization techniques द्वारा बनाए गए tradeoffs से बचने में मदद कर सकती है, जिनमें unpredictable results भी शामिल हैं
अगर DFloat11 से इन्हें सस्ते GPUs में fit किया जा सके, तो कुछ मामलों में cost savings काफी हो सकती हैं। मैं xmad.ai में काम करता हूं
मेमोरी constraints की वजह से uncompressed मॉडल के कुछ हिस्से CPU पर offload करने वाले विकल्प से तुलना करें, तो कहा गया है कि DFloat11 में token generation throughput 1.9~38.8 गुना ज़्यादा है। fixed GPU memory budget में यह uncompressed मॉडल की तुलना में 5.3~13.17 गुना लंबी context length संभव बनाता है
सिर्फ़ context length के आधार पर भी, भले ही मॉडल मेमोरी में फिट हो जाए, यह उपयोगी लगता है; लेकिन LLM अक्सर memory bandwidth से बंधे होते हैं—इस बुनियादी समझ के हिसाब से सोचूँ तो उत्सुकता है कि सब कुछ GPU पर होने पर भी tokens per second सुधरते हैं या नहीं
पेपर में A100 पर 200GB/s से कम होने का दावा है, और benchmark के हिसाब से GPU और मॉडल पर निर्भर करते हुए batch size 1 पर यह 1.5~4 गुना धीमा दिखता है। बेशक batch size पर्याप्त बड़ा हो जाए तो यह overhead ज़्यादातर गायब हो जाता है
दूसरे lossless codecs उसी hardware पर 600GB/s तक पहुँच सकते हैं, इसलिए improvement की गुंजाइश दिखती है। लेकिन A100 की raw memory bandwidth 1.6TB/s है
क्या इसका मतलब है कि यह unquantized LLM की memory requirements को सामान्य तौर पर 30% घटा सकता है? अगर सच है तो यह काफ़ी बड़ा है
अगर इसे मौजूदा quantization के ऊपर जोड़ा जा सके तो यह निश्चित रूप से दिलचस्प है, लेकिन K quantization भी overall perplexity impact के आधार पर अलग-अलग layers में अलग precision इस्तेमाल करता है। उदाहरण के लिए Q6 में 4-bit और 8-bit को मिलाकर इस्तेमाल किया जाता है, जो यहाँ इस्तेमाल entropy metric जैसा ही है। calibrated imatrix तक को ध्यान में रखें तो conceptually यह FFT जैसे तरीके से और ज़्यादा aggressively compress करता है
क्या यह ZipNN से अलग है? https://arxiv.org/pdf/2411.05239
ज़िक्र तो दिख रहा है, लेकिन समझ नहीं आ रहा कि यह उसी पर आधारित है या अलग/बेहतर है
लेकिन LZ-family compressors neural network weights के लिए खास मायने रखते नहीं दिखते। repetition-heavy अधिकतर text data जितनी redundancy इनमें नहीं होती, और अगर data बहुत sparse नहीं है तो dictionary overhead से बचने लायक repetitions भी बहुत ज़्यादा नहीं हो सकते
LZ-family compressor जोड़कर उसे inference के critical path में डालने से decompression काफ़ी धीमा हो जाएगा। decompression को compute kernel के साथ fuse करना सबसे अच्छा होगा। उदाहरण के लिए इसे ऐसे GEMM जैसा बनाया जा सकता है जो arithmetic operations से पहले हर tile को decompress करे, और decompression routine जितना सरल होगा यह उतना आसान होगा
यह सब कितनी तेज़ी से आगे बढ़ रहा है, यह देखना काफ़ी शानदार है। ऐसा लगता है कि हर हफ्ते कोई नई efficiency technique या hardware upgrade आ रहा है
ऐसे improvements आसानी से ध्यान खींच लेते हैं
क्या इसे नए models पर भी run किया जा सकता है? अगर मैं गलत नहीं समझ रहा, तो code सिर्फ़ inference के लिए दिखता है