DeepGEMM: बारीक scaling के जरिए साफ़ और efficient FP8 GEMM kernel
(github.com/deepseek-ai)- DeepGEMM एक high-performance tensor core kernel library है, जो आधुनिक LLMs के मुख्य compute primitive—GEMM, fused MoE, MQA scoring, HyperConnection आदि—को एक CUDA codebase में जोड़ती है
- सभी kernels हल्के JIT module के रूप में runtime पर compile होते हैं; installation के दौरान CUDA compilation की जरूरत नहीं होती, और यह C++20, CUDA Toolkit, PyTorch, CUTLASS 4.0 या ऊपर की मांग करता है
- यह CUTLASS और CuTe की कुछ concepts का उपयोग करता है, लेकिन templates और algebraic structures पर भारी निर्भर नहीं है; सीमित संख्या के core kernel functions के साथ NVIDIA GPU kernel optimization सीखना आसान बनाने के लिए design किया गया है
- support range में FP8, FP4, BF16 GEMM, grouped GEMM, DeepSeek v3.2 के लिए MQA logits kernel, और communication व compute को overlap करने वाला Mega MoE शामिल हैं; SM90 और SM100 पर memory layout constraints अलग हैं
- lightweight design के बावजूद, यह विभिन्न matrix shapes में expert-tuned libraries के बराबर या उससे अधिक performance का लक्ष्य रखता है, और H800 पर अधिकतम 1550 TFLOPS हासिल करने वाला update शामिल है
DeepGEMM का उद्देश्य और design
- DeepGEMM एक tensor core kernel library है, जो latest large language models में इस्तेमाल होने वाले प्रमुख compute primitives को एक CUDA codebase में integrate करती है
- GEMM: FP8, FP4, BF16
- communication overlap वाला fused MoE: Mega MoE
- lightning indexer के लिए MQA scoring
- HyperConnection(HC)
- सभी kernels हल्के Just-In-Time(JIT) module के रूप में runtime पर compile होते हैं
- installation process में CUDA compilation की जरूरत नहीं होती
- CUTLASS और CuTe की कुछ concepts का उपयोग करता है
- लेकिन भारी templates या algebraic structures पर बहुत ज्यादा निर्भर नहीं करता
- core kernel functions की संख्या सीमित रखकर codebase को simple बनाए रखता है
- lightweight design के बावजूद, यह बताता है कि कई matrix shapes में expert-tuned libraries के बराबर या उससे बेहतर performance देता है
मुख्य updates
- 16 अप्रैल 2026 का update Mega MoE, FP8xFP4 GEMM, FP4 Indexer, PDL, तेज JIT compilation आदि शामिल करता है
- 28 सितंबर 2025 का update DeepSeek v3.2 lightning indexer के लिए weighted ReLU MQA logits scoring kernel जोड़ता है
- details #200 में हैं
- 20 जुलाई 2025 का update SM90 और SM100 दोनों को support करता है, और low CPU overhead वाले JIT CPP module के साथ पूरा refactor किया गया है
- NVRTC और compilation के बाद SASS optimization disabled हैं
- NVRTC को बाद में support किए जाने के रूप में दिखाया गया है
- NVCC 12.9 FFMA interleaving अपने-आप करता है, इसलिए post-compilation optimization अब support नहीं है
- details #112 में हैं
- 14 मई 2025 का update dense और MoE backward के लिए weight gradient kernel जोड़ता है
- details #95 में हैं
- 7 मई 2025 का update NVRTC support के साथ अधिकतम 10x compilation speedup देता है
- इसे
DG_JIT_USE_NVRTC=1से enable किया जा सकता है - कुछ मामलों में performance loss हो सकता है
- details #94 में हैं
- इसे
- 18 अप्रैल 2025 का update H800 पर अधिकतम 1550 TFLOPS हासिल करता है
requirements और installation flow
- runtime environment के लिए NVIDIA SM90 या SM100 architecture वाला GPU चाहिए
- software requirements ये हैं
- Python 3.8 या ऊपर
- C++20 support करने वाला compiler
- CUDA Toolkit
- SM90: CUDA 12.3 या ऊपर
- best performance के लिए CUDA 12.9 या ऊपर की strongly recommendation है
- SM100: CUDA 12.9 या ऊपर
- PyTorch 2.1 या ऊपर
- CUTLASS 4.0 या ऊपर
{fmt}library
- development environment में submodule सहित repository clone करने के बाद
develop.shसे जरूरी include linking और CPP JIT module build किया जाता है - installation
install.shचलाने के बाद Python project मेंdeep_gemmimport करने के तरीके से होती है
GEMM interface और layout constraints
- DeepGEMM के GEMM kernel naming convention में
D = C + A @ Bहै - input shape layout NT पर आधारित है
fp8_gemm_ntD = C + A @ B.Tकरता है
- SM90 implementation सिर्फ NT memory layout support करता है
- यह row-major, col-major combination के बराबर है
- SM100 implementation NT, TN, NN, TT सभी memory layouts support करता है
- दोनों architectures में LHS scaling factor TMA-aligned और transposed layout में होना चाहिए
- SM90 scaling factor को FP32 format में मांगता है
- SM100 packed UE8M0 format मांगता है, और 4 UE8M0 को एक
torch.intमें pack करता है
- input transpose या FP8 casting जैसे काम user को अलग से handle करने होंगे
- library simple PyTorch utility functions देती है, लेकिन performance धीमी हो सकती है
- मुख्य focus GEMM kernel optimization है
Dense और Grouped GEMM
- basic non-grouped FP8 GEMM
fp8_gemm_{nt, nn, tn, tt}functions का उपयोग करता है - contiguous layout वाला grouped GEMM, CUTLASS के traditional grouped GEMM से अलग, सिर्फ M axis को group करता है
- N और K fixed होने चाहिए
- design MoE models में experts द्वारा same shape share करने वाली स्थिति के लिए है
- training forward pass या inference prefilling में हर expert द्वारा process किए गए tokens की संख्या अलग हो सकती है
- ऐसे tokens को एक tensor में concatenate किए गए रूप को contiguous layout कहा जाता है
- हर expert segment GEMM M block size से aligned होना चाहिए
- alignment criteria
get_mk_alignment_for_contiguous_layout()से देखा जाता है
- MoE weight backward के लिए K-axis grouped API भी उपलब्ध है
- M और N fixed होने चाहिए
- संबंधित function
k_grouped_fp8_gemm_tn_contiguousहै
- inference decoding stage में जब CUDA graph on हो और CPU expert-wise token count नहीं जान सकता, तो masked grouped GEMM support करता है
- mask tensor देने पर kernel सिर्फ valid regions compute करता है
- function
m_grouped_fp8_gemm_nt_maskedहै - DeepEP के low-latency kernel output को input के रूप में इस्तेमाल करने का example है
DeepSeek v3.2 Indexer के लिए MQA kernel
- V3.2 MQA kernel family non-paged version और paged version देती है
- non-paged prefilling के लिए है
- paged decoding के लिए है
fp8_mqa_logits6 inputs लेता हैq: E4M3 tensor, shape[seq_len, num_heads, head_dim]kv: E4M3 tensor और float scaling factor- tensor shape
[seq_len_kv, head_dim]है - scaling factor shape
[seq_len_kv]है
- tensor shape
weights: float tensor, shape[seq_len, num_heads]cu_seq_len_k_start,cu_seq_len_k_end: int tensor, shape[seq_len]clean_logits: unfilled logits को-infसे clean करना है या नहीं
- output tensor shape
[seq_len, seq_len_kv]है और token-to-token logits दर्शाता है - हर
qtokeni,cu_seq_len_k_start[i]सेcu_seq_len_k_end[i]से पहले तक केkvtokenjपर iterate करता हैkv_jमें scaling factor multiply करता हैq[i, :, :] @ kv_jसे per-head values compute करता है- ReLU apply करने के बाद
weights[i, :]multiply कर sum करता है और scalar logit बनाता है
- paged version function
fp8_paged_mqa_logitsहै
Mega MoE
- Mega MoE कई MoE stages को एक mega-kernel में fuse करता है
- EP dispatch
- linear 1, FP8xFP4
- SwiGLU
- linear 2, FP8xFP4
- EP combine
- Mega MoE NVLink communication और tensor core compute को overlap करता है
- execution के लिए symmetric memory का उपयोग करने वाला multi-process launch जरूरी है
- usage flow इस प्रकार है
deep_gemm.get_symm_buffer_for_mega_moeसे symmetric memory buffer allocate करें- PyTorch 2.9 या ऊपर चाहिए
deep_gemm.transform_weights_for_mega_moeसे FP4 और UE8M0 SF सहित weights को required layout में transform करें- call से पहले input, scaling factor, top-k index, top-k weight को buffer में copy करें
deep_gemm.fp8_fp4_mega_moeसे fused mega MoE kernel run करें
- पूरे multi-process setup और benchmarking example
tests/test_mega_moe.pyमें हैं
utilities और environment variables
- मुख्य utility functions execution resources, alignment, JIT compilation, scaling factor transformation को control करते हैं
deep_gemm.set_num_sms/get_num_sms: इस्तेमाल किए जाने वाले maximum SMs की संख्या set और query करनाdeep_gemm.set_tc_util/get_tc_util: approximate tensor core utilization ratio set और query करनाdeep_gemm.set_pdl/get_pdl: Programmatic Dependent Launch(PDL) enable और disable करनाdeep_gemm.set_mk_alignment_for_contiguous_layout/get_mk_alignment_for_contiguous_layout: contiguous layout की group-level M/K alignment set और query करनाdeep_gemm.transform_sf_into_required_layout: scaling factor को required layout में transform करनाdeep_gemm.get_tma_aligned_size: जरूरी TMA alignment size query करना
- JIT-related environment variables debug output, cache location, compiler selection, profiling options को control करते हैं
DG_JIT_DEBUG: JIT debug information outputDG_PRINT_CONFIGS: हर shape के लिए selected config outputDG_JIT_CACHE_DIR: compiled kernel cache directory, default$HOME/.deep_gemmDG_JIT_USE_NVRTC: NVCC के बजाय NVRTC इस्तेमाल करना; fast compilation possible है, लेकिन कुछ मामलों में performance कम हो सकती हैDG_JIT_NVCC_COMPILER: NVCC compiler pathDG_JIT_CPP_STANDARD: C++ standard version, default20
- debug और profiling environment variables भी दिए गए हैं
DG_JIT_DUMP_ASM,DG_JIT_DUMP_PTX,DG_JIT_DUMP_SASS: PTX और SASS output dumpDG_JIT_WITH_LINEINFO: profiling tools के लिए source line information शामिल करनाDG_COMM_KERNEL_DEBUG: Mega MoE call से पहले symmetric buffer को 0 से initialize करनाDG_USE_NVIDIA_TOOLS: external NVIDIA tools चलाते समय internal profiling skip करना
- build options installation और kernel loading method को control करते हैं
DG_SKIP_CUDA_BUILD: installation के दौरान CUDA extension build skip करनाDG_FORCE_BUILD: pre-built wheel download के बजाय local build force करनाDG_JIT_USE_RUNTIME_API: kernel loading के लिए CUDA Runtime API इस्तेमाल करना, CUDA runtime 12.8 या ऊपर चाहिए
license और citation
- DeepGEMM repository MIT License के तहत open है
- project बताता है कि यह CUTLASS से inspired है
- citation item का title
DeepGEMM: clean and efficient BLAS kernel library on GPUहै
1 टिप्पणियां
Hacker News टिप्पणियाँ
FFMA SASS interleaving वाकई हैरान करने वाले स्तर का लगता है
NVCC 12.2 और 12.3 के बीच CUTLASS FP8 kernel performance बेहतर होने की बात देखकर किसी ने compiled SASS की तुलना की, तो कई FADD instructions में एक bit interleaving pattern की तरह flipped मिला, और open source CUDA assembler implementation को देखकर शायद यह पता चला कि वह bit yield bit है, जो current warp को छोड़कर दूसरे warp को run होने देता है
इसका इस्तेमाल करके compiled binary की FFMA instructions को modify करने वाला script बनाया गया, और सिर्फ yield bit ही नहीं बल्कि warp के yield करने पर register reuse संभव नहीं होता, इसलिए reuse bit भी साथ में flip किया गया ताकि fine-grained scaling FP8 GEMM में MMA instructions और promoted FFMA instructions बेहतर overlap हों; कुछ मामलों में इससे 10% से ज्यादा performance बढ़ी, यह काफी प्रभावशाली है
बस इस खास समस्या के लिए शायद दूसरी AI कंपनियों ने अभी तक इसकी जरूरत महसूस नहीं की थी, और अंततः संभव है कि सभी लगभग इसी निष्कर्ष तक पहुँचें
यह उदाहरण अच्छी तरह दिखाता है कि सिर्फ high-level code से hardware performance निकालने के मामले में मौजूदा compiler अभी कितना पीछे है
यह सोचने वाली बात है कि पारंपरिक compiler techniques या AI-आधारित optimization agents को ऐसे नतीजे पाने के लिए क्या चाहिए होगा
रिपोर्ट की गई speedup संख्याएँ उनके अपने CUTLASS-आधारित baseline की तुलना में हैं
सोच रहा हूँ कि किसी ने cuBLAS के साथ direct performance comparison किया है या नहीं
अब तक मैंने CUTLASS GEMM के जो नतीजे देखे हैं, वे cuBLAS से लगभग 10% के भीतर थे; अगर paper में कही गई 2x~2.5x बढ़त बनी रहती है, तो वह सचमुच प्रभावशाली होगी
पहले तो FP8 जैसी mixed-precision workloads को संभालने के लिए cuBLAS में cuBLASLt extension API चाहिए
फिर A x B में E5M2 x E5M2 जैसी उचित लगने वाली type combinations supported नहीं हैं, लेकिन E5M2 x E4M3 supported है; और Ampere, Hopper, Blackwell में matrix A का layout हमेशा transposed होना चाहिए जैसी पाबंदियाँ भी बनी रहती हैं
मैंने FP8 cuBLASLt benchmark को अपने "Less Slow C++" repository <https://github.com/ashvardanian/less_slow.cpp> में integrate किया है, और उसे मौजूदा cuBLAS तथा हाथ से लिखे CUDA/PTX benchmark सूची में जोड़ दिया है
इसे H200 GPU पर चला रहा हूँ, जिसका performance H100 जैसा होना चाहिए, और square inputs पर throughput लगभग 1.35 Peta-ops पर peak करता है
256 पर 2.68T/s, 512 पर 20.49T/s, 1024 पर 144.23T/s, 2048 पर 665.68T/s, 4096 पर 1.26P/s, 8192 पर 1.34P/s, और 16384 पर लगभग 1.23P/s मिला; यह dense GEMM के लिए NVIDIA द्वारा प्रचारित आँकड़ों <https://resources.nvidia.com/en-us-data-center-overview-mc/e...> का लगभग 67% है
मुझे लगा था कि baseline में cuBLAS और CUTLASS में से जो बेहतर हो, वही चुना गया होगा
इस तरह का open source उद्योग के efficiency हासिल करने के लक्ष्य को बहुत अच्छी तरह दिखाता है
लेकिन इस software का लाभ सीखने-समझने, experiment करने, या consumer hardware पर model serve करने की कोशिश करने वाले सामान्य open source community से अधिक, बड़े पैमाने पर model serve करने वाली बड़ी कंपनियों को, यानी DeepSeek के संभावित प्रतिस्पर्धियों को, ज्यादा मिलेगा
मुझे यकीन नहीं है कि लगातार और कम precision के लिए optimize करना लंबी अवधि में सही दिशा है
इसका मतलब यह है कि model वास्तव में काफी sparse है, और अभी ऐसा हो सकता है, लेकिन मेरा मानना है कि यह मूल रूप से sparse होना जरूरी है इसलिए नहीं, बल्कि training के तरीकों में कुछ खराब विचार मिले हुए हैं, इसलिए ऐसा दिख रहा है
ऐसे बहुत अच्छे models को train करना जो सिर्फ higher precision पर ही संभव हों, यह research problem है; जबकि low-precision training और inference एक engineering problem है
CNN के दौर से, कम से कम 9 साल से, हम यह कर रहे हैं, और मुझे लगता है कि यह काम अभी कुछ साल और चलेगा
Blackwell के native microscaling support MXFP की वजह से यह बेमानी भी हो सकता है
Hopper में इसे एक ज्यादा coarse granularity पर, लेकिन FP32 scaling factors के साथ, manually implement किया गया था
इस तरह के high-quality public demos अच्छी तरह दिखाते हैं कि $NVDA की moat आखिर कहाँ है
general-purpose GPUs इतने flexible हैं कि hardware vendor ने शुरुआत में जिन बातों के बारे में नहीं सोचा था, लेकिन जो पर्याप्त रूप से तर्कसंगत हैं, ऐसे कई काम programming के जरिए कराए जा सकते हैं
लेकिन अगर भविष्य धीरे-धीरे dedicated hardware support की ओर सिमटता जाता है और इस तरह के software optimization की गुंजाइश खत्म हो जाती है, तो तथाकथित CUDA moat टूट जाएगा
इस खेल में बने रहने के लिए NVIDIA जैसे अपनी ही moat को खुद खोदकर कमजोर कर रही है :p
वाह, यह MIT license के तहत है
अच्छा होगा अगर बड़ी कंपनियाँ भी इस तरह के open source collaboration मॉडल को अपनाएँ
मैं अब भी यह सोचता रहता हूँ कि undocumented instructions आखिर मौजूद क्यों हैं
भले वे पूरी तरह stable न हों, फिर भी क्या उन्हें users को उपलब्ध कराना बेहतर नहीं होगा?
लगता है कि ऐसी बातें अंदरूनी तौर पर documented तो होंगी, फिर इन्हें सार्वजनिक क्यों नहीं किया जाता, समझ नहीं आता
अस्पष्टता पर आधारित security काम नहीं करती, और competitors तो वैसे भी सब कुछ reverse-engineer कर लेते हैं
या तो समय की कमी होती है, या फिर unstable या experimental features के लिए support का संकेत नहीं देना चाहते
अगर असर सिर्फ बगल वाली team तक सीमित रहे, तो बाद में बदलना भी कहीं आसान होता है
संभव है कि वे बस architecture design documents या specs जैसी जगहों में ही दर्ज हों, और ऐसे documents को साझा करना वे स्वाभाविक रूप से नहीं चाहेंगे
सच कहूँ तो यह मेरी उपयोग-सीमा और समझ, दोनों से बाहर की बात है
फिर भी ऐसी खोजें और सुधार साझा करके सबको लाभ पहुँचाने का तरीका सच में सराहनीय और ताज़गीभरा है
matrix multiplication और deep learning workloads में यह बहुत महत्वपूर्ण है
NVIDIA के SASS में FFMA instruction 64-bit या 128-bit instruction के रूप में encode होता है, और इसमें कई control bits होते हैं जो उसके सटीक व्यवहार को तय करते हैं
जब yield bit set होती है, तो यह warp scheduler को बताती है कि इस instruction के बाद मौजूदा warp execution छोड़ सकता है, और hardware latency छिपाने के लिए किसी दूसरे warp को चला सकता है
GPU बड़े पैमाने की parallelism से high throughput पाते हैं, और जब एक warp memory wait जैसी वजह से रुक जाता है, तो दूसरा warp आगे बढ़ सकता है
reuse bit यह दिखाती है कि source register को अगली operation में तुरंत reuse किया जा सकता है या नहीं, और अगर yield bit set हो तो इसे अनिवार्य रूप से off रखना पड़ता है
क्योंकि warp के yield करने पर यह ज़रूरी नहीं कि अगला चलने वाला वही warp हो, और कोई दूसरा warp register file state बदल सकता है; इसलिए hardware यह guarantee नहीं कर सकता कि yield के बाद भी register value बनी रहेगी
FFMA instructions पर yield bit को alternating pattern में set करने से compiler explicit scheduling points बना सकता है जहाँ दूसरे warp आगे बढ़ सकें, और correctness बनाए रखने के लिए उस instruction की reuse bit भी साथ में clear करनी पड़ती है
यह बदलाव खास तौर पर matrix multiplication के केंद्र में रहने वाले MMA instructions और FP8 को higher precision में accumulate करने के लिए convert करने वाले promotion FFMA instructions को overlap कराने में मदद करता है
FP8 GEMM में आम तौर पर accumulation के लिए higher precision में conversion और फिर वापस लौटने की प्रक्रिया चाहिए होती है, जिससे अतिरिक्त FFMA बनते हैं; इससे memory bandwidth की मांग तो घटती है, लेकिन promotion/demotion operations के मिश्रण के साथ एक जटिल compute pattern बनता है
“fine-grained scaling” का मतलब शायद computation के कई बिंदुओं पर precision को सावधानी से manage करना है
yield bit में यह छेड़छाड़ compute operations और format conversion को बेहतर तरीके से interleave होने देती है, जिससे GPU execution units का अधिक कुशल उपयोग होता है; इस optimization के बिना warp scheduler शायद स्वाभाविक switching opportunities न ढूँढ पाए और compute resources कम इस्तेमाल हों