<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GGML on kenji.blog</title><link>http://kenji.blog/hi/tags/ggml/</link><description>Recent content in GGML on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>hi</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 17:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/hi/tags/ggml/index.xml" rel="self" type="application/rss+xml"/><item><title>पायथन की आवश्यकता नहीं! केवल C++ के साथ AI इन्फेरेंस इंजन का निर्माण</title><link>http://kenji.blog/hi/p/building-ai-inference-engine-cpp-only/</link><pubDate>Fri, 11 Sep 2026 17:00:00 +0900</pubDate><guid>http://kenji.blog/hi/p/building-ai-inference-engine-cpp-only/</guid><description>&lt;img src="http://kenji.blog/p/building-ai-inference-engine-cpp-only/img/eyecatch.jpg" alt="Featured image of post पायथन की आवश्यकता नहीं! केवल C++ के साथ AI इन्फेरेंस इंजन का निर्माण" />&lt;h2 id="1-परचय-पयथन-क-छडकर-कवल-c-स-ai-इनफरस-इजन-कय-बनए">1. परिचय: पायथन को छोड़कर केवल C++ से AI इन्फेरेंस इंजन क्यों बनाएं?
&lt;/h2>&lt;p>आधुनिक AI विकास में, पायथन एक डे-फैक्टो मानक है। PyTorch और TensorFlow जैसे शक्तिशाली फ्रेमवर्क की बदौलत, आप कोड की कुछ पंक्तियों के साथ जटिल न्यूरल नेटवर्क बना, प्रशिक्षित और अनुमान लगा सकते हैं। हालाँकि, इन फ्रेमवर्क के पीछे, C++ और CUDA जैसी निम्न-स्तरीय भाषाएँ भारी गणना प्रसंस्करण को संभालती हैं। पायथन केवल एक &amp;ldquo;गोंद (glue)&amp;rdquo; की भूमिका निभाता है।&lt;/p>
&lt;p>तो, पायथन को हटाकर केवल C++ के साथ AI इन्फेरेंस इंजन बनाने की क्या आवश्यकता है? इसके कई मजबूत कारण हैं।&lt;/p>
&lt;ol>
&lt;li>&lt;strong>अत्यधिक प्रदर्शन और कम लेटेंसी (Extreme Performance and Low Latency)&lt;/strong>: पायथन के GIL (Global Interpreter Lock) और डायनेमिक टाइपिंग के ओवरहेड को पूरी तरह से समाप्त किया जा सकता है। विशेष रूप से उन प्रणालियों में जहां रीयल-टाइम प्रदर्शन आवश्यक है, मिलीसेकंड की देरी भी घातक हो सकती है।&lt;/li>
&lt;li>&lt;strong>परिनियोजन में आसानी (Ease of Deployment)&lt;/strong>: अंतिम-उपयोगकर्ता के वातावरण में पायथन वातावरण (विशाल लाइब्रेरी, निर्भरताओं का जाल) स्थापित करना बहुत कठिन है। C++ के साथ, आपको केवल एक स्टैटिकली लिंक्ड सिंगल एग्जीक्यूटेबल बाइनरी (&lt;code>.exe&lt;/code> या ELF बाइनरी) वितरित करने की आवश्यकता होती है।&lt;/li>
&lt;li>&lt;strong>एज डिवाइस के लिए समर्थन (Edge Device Support)&lt;/strong>: स्मार्टफोन, एम्बेडेड डिवाइस और रास्पबेरी पाई (Raspberry Pi) जैसे सीमित संसाधनों वाले वातावरण में, कई गीगाबाइट मेमोरी की खपत करने वाले पायथन रनटाइम को चलाने की कोई गुंजाइश नहीं है।&lt;/li>
&lt;li>&lt;strong>हार्डवेयर का सीधा नियंत्रण (Direct Hardware Control)&lt;/strong>: निम्न-स्तरीय नियंत्रण, जैसे मेमोरी आवंटन का समय, SIMD निर्देशों का स्पष्ट उपयोग, और GPU के साथ मेमोरी ट्रांसफर का अनुकूलन, C++ के साथ संभव है।&lt;/li>
&lt;/ol>
&lt;p>इस लेख में, हम Georgi Gerganov द्वारा विकसित &amp;ldquo;GGML&amp;rdquo; लाइब्रेरी के आर्किटेक्चर से काफी प्रेरणा लेते हुए, लार्ज लैंग्वेज मॉडल (LLM) आदि को चलाने के लिए स्क्रैच से केवल C++ का उपयोग करके एक इन्फेरेंस इंजन बनाने की प्रक्रिया को तकनीकी गहराई तक जाकर समझाएंगे।&lt;/p>
&lt;hr>
&lt;h2 id="2-इनफरस-इजन-आरकटकचर-क-समगर-दषटकण">2. इन्फेरेंस इंजन आर्किटेक्चर का समग्र दृष्टिकोण
&lt;/h2>&lt;p>AI इन्फेरेंस प्रक्रिया, अनिवार्य रूप से, &amp;ldquo;विशाल मैट्रिक्स गणनाओं की एक श्रृंखला&amp;rdquo; है। इसे कुशलतापूर्वक निष्पादित करने के लिए, एक इन्फेरेंस इंजन में निम्नलिखित घटक होने चाहिए।&lt;/p>
&lt;div class="mermaid">graph TD
A["इनपुट डेटा (टोकन/छवियाँ)"] --> B["टेंसर प्रबंधन"]
B --> C["कम्प्यूटेशन ग्राफ (DAG)"]
C --> D["मेमोरी एरिना और एलोकेटर"]
C --> E["शेड्यूलर और थ्रेड पूल"]
E --> F["CPU बैकएंड (AVX2/ARM NEON)"]
E --> G["GPU बैकएंड (CUDA/Metal)"]
F --> H["आउटपुट परिणाम"]
G --> H&lt;/div>
&lt;ol>
&lt;li>&lt;strong>टेंसर (Tensor) प्रबंधन&lt;/strong>: बहुआयामी सरणी डेटा संरचना और प्रत्येक आयाम के लिए स्ट्राइड (Stride) का प्रबंधन।&lt;/li>
&lt;li>&lt;strong>कम्प्यूटेशन ग्राफ (Computation Graph)&lt;/strong>: न्यूरल नेटवर्क की प्रत्येक परत के संचालन को एक निर्देशित चक्रीय ग्राफ (Directed Acyclic Graph - DAG) के रूप में दर्शाना।&lt;/li>
&lt;li>&lt;strong>मेमोरी एरिना (Memory Arena)&lt;/strong>: गतिशील मेमोरी आवंटन (&lt;code>malloc&lt;/code> या &lt;code>new&lt;/code>) के ओवरहेड से बचने के लिए एक पूर्व-आवंटित मेमोरी प्रबंधन तंत्र।&lt;/li>
&lt;li>&lt;strong>बैकएंड (Backend)&lt;/strong>: विशिष्ट हार्डवेयर, जैसे CPU या GPU (कर्नेल) के लिए अनुकूलित संचालन का कार्यान्वयन।&lt;/li>
&lt;/ol>
&lt;p>हम इन्हें C++ की शक्तिशाली विशेषताओं (टेम्पलेट, पॉइंटर अरिथमेटिक, RAII, आदि) का उपयोग करके एक साथ जोड़ेंगे।&lt;/p>
&lt;hr>
&lt;h2 id="3-ममर-परबधन-क-रहसय-ममर-एरन-और-simd-अलइनमट">3. मेमोरी प्रबंधन का रहस्य: मेमोरी एरिना और SIMD अलाइनमेंट
&lt;/h2>&lt;p>इन्फेरेंस इंजन में मेमोरी प्रबंधन सबसे महत्वपूर्ण कारकों में से एक है जो सीधे प्रदर्शन को प्रभावित करता है। अनुमान के दौरान, विशेष रूप से जब ट्रांसफॉर्मर मॉडल की प्रत्येक परत से गुजरते हैं, तो भारी मात्रा में मध्यवर्ती टेंसर उत्पन्न होते हैं। यदि हर बार इन्हें मानक &lt;code>malloc&lt;/code> के साथ आवंटित और मुक्त किया जाता है, तो हीप फ्रैग्मेंटेशन और OS कॉन्टेक्स्ट स्विच के कारण गति में भारी गिरावट आएगी।&lt;/p>
&lt;p>इसलिए, हम &amp;ldquo;&lt;strong>मेमोरी एरिना (Memory Arena)&lt;/strong>&amp;rdquo; दृष्टिकोण अपनाते हैं। यह एक ऐसी तकनीक है जहां अनुमान की शुरुआत में आवश्यक अधिकतम मेमोरी की गणना (या निर्धारण) की जाती है और एक ही बार में आवंटित की जाती है, और मेमोरी को केवल पॉइंटर को बढ़ाकर (increment) निकाला जाता है।&lt;/p>
&lt;h3 id="31-अलइनमट-क-महतव">3.1 अलाइनमेंट का महत्व
&lt;/h3>&lt;p>आधुनिक CPU, SIMD (Single Instruction, Multiple Data) निर्देशों का समर्थन करते हैं। उदाहरण के लिए Intel/AMD का AVX2/AVX-512 और ARM का NEON। ये निर्देश एक ही बार में 256 बिट्स (32 बाइट्स) या 512 बिट्स (64 बाइट्स) डेटा संसाधित करते हैं, लेकिन संसाधित की जाने वाली डेटा मेमोरी को एक विशिष्ट बाइट सीमा (आमतौर पर 32 बाइट्स या 64 बाइट्स) पर अलाइन (align) होना चाहिए।&lt;/p>
&lt;p>नीचे अलाइनमेंट को ध्यान में रखते हुए मेमोरी एरिना का C++ कार्यान्वयन उदाहरण दिया गया है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cstdint&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cstddef&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">MemoryArena&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MemoryArena&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// POSIX सिस्टम के लिए posix_memalign, Windows के लिए _aligned_malloc का उपयोग करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#ifdef _WIN32
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">*&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">_aligned_malloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">posix_memalign&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">reinterpret_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="o">**&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">bad_alloc&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">MemoryArena&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#ifdef _WIN32
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">_aligned_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">allocate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">bytes&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">alignment&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// अलाइनमेंट की गणना (पैडिंग ज्ञात करना)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pad&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">alignment&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">offset&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">alignment&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">alignment&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">offset&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">pad&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">bytes&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">runtime_error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;OOM: MemoryArena out of memory&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">offset&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">pad&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">offset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">offset&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">bytes&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">reset&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">offset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// मेमोरी मुक्त करने के लिए बस पॉइंटर को रीसेट करें (O(1))
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>इस प्रकार, टेंसर बनाते समय हम हमेशा इस एरिना के माध्यम से मेमोरी प्राप्त करते हैं। अनुमान के प्रत्येक चरण (जैसे प्रत्येक टोकन जनरेशन) के समाप्त होने पर बस &lt;code>reset()&lt;/code> कॉल करके, हम तुरंत मेमोरी का पुन: उपयोग कर सकते हैं।&lt;/p>
&lt;hr>
&lt;h2 id="4-टसर-डट-सरचन-और-सटरइड-क-जद">4. टेंसर डेटा संरचना और स्ट्राइड का जादू
&lt;/h2>&lt;p>टेंसर स्केलर, वेक्टर और मैट्रिक्स की एक सामान्यीकृत अवधारणा है। कार्यान्वयन में जो महत्वपूर्ण है वह यह है कि वास्तविक डेटा को मेमोरी में &lt;strong>1-आयामी सन्निहित सरणी (contiguous array)&lt;/strong> के रूप में रखा जाता है, जबकि इसे बहुआयामी रूप में व्याख्या करने के लिए &amp;ldquo;स्ट्राइड (Stride)&amp;rdquo; की अवधारणा होती है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">enum&lt;/span> &lt;span class="k">class&lt;/span> &lt;span class="nc">DataType&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FP32&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FP16&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">INT8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// क्वांटिज़ेशन के लिए
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">INT4&lt;/span> &lt;span class="c1">// क्वांटिज़ेशन के लिए
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Tensor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_dims&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// आयामों की संख्या
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// प्रत्येक आयाम में तत्वों की संख्या (Number of Elements)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">nb&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// प्रत्येक आयाम के लिए स्ट्राइड (Number of Bytes)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">DataType&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// डेटा प्रकार
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// पेलोड के लिए पॉइंटर
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// कम्प्यूटेशन ग्राफ के लिए
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">enum&lt;/span> &lt;span class="nc">OpType&lt;/span> &lt;span class="n">op&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>स्ट्राइड &lt;code>nb[i]&lt;/code> आयाम &lt;code>i&lt;/code> में आसन्न तत्वों के बीच मेमोरी में बाइट दूरी को दर्शाता है।
उदाहरण के लिए, यदि $M \times N$ तत्वों का एक मैट्रिक्स (FP32, 1 तत्व 4 बाइट्स) Row-Major (पंक्ति-प्रमुख) में संग्रहीत किया गया है, तो स्ट्राइड इस प्रकार होगा:&lt;/p>
&lt;ul>
&lt;li>&lt;code>nb[0]&lt;/code> = 4 (बाइट्स) : कॉलम दिशा में गति&lt;/li>
&lt;li>&lt;code>nb[1]&lt;/code> = $N \times 4$ (बाइट्स) : पंक्ति दिशा में गति&lt;/li>
&lt;/ul>
&lt;p>इसका उपयोग करके, &amp;ldquo;ट्रांसपोज़ (Transpose)&amp;rdquo; और &amp;ldquo;व्यू (View)&amp;rdquo; जैसे संचालन, मेमोरी कॉपी के बिना, केवल स्ट्राइड मानों को स्वैप करके प्राप्त किए जा सकते हैं। यह बहुत ही सुरुचिपूर्ण और तेज़ है।&lt;/p>
&lt;hr>
&lt;h2 id="5-कमपयटशन-गरफ-dag-क-नरमण-और-लज-इवलयएशन">5. कम्प्यूटेशन ग्राफ (DAG) का निर्माण और लेज़ी इवैल्यूएशन
&lt;/h2>&lt;p>PyTorch आदि के समान, हमारा इन्फेरेंस इंजन भी &amp;ldquo;Define-by-Run&amp;rdquo; के करीब एक लेज़ी इवैल्यूएशन (Lazy Evaluation) को अपनाता है। यानी, जब गणितीय फलन को बुलाया जाता है तो गणना नहीं की जाती है, बल्कि केवल ग्राफ (नोड्स के बीच निर्भरता) बनाया जाता है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">tensor_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">MemoryArena&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">create_tensor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">n_dims&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpType&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ADD&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">tensor_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">MemoryArena&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// b अक्सर ट्रांसपोज़ किया हुआ होता है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">create_tensor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arena&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ne&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpType&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MUL_MAT&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">src1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>इन्फेरेंस प्रक्रिया का प्रवाह इस प्रकार है:&lt;/p>
&lt;div class="mermaid">graph LR
A["टेंसर को परिभाषित करें"] --> B["ऑप्स के माध्यम से ग्राफ बनाएं"]
B --> C["टोपोलॉजिकल सॉर्ट"]
C --> D["आउटपुट के लिए मेमोरी आवंटित करें"]
D --> E["नोड्स को क्रम में निष्पादित करें"]&lt;/div>
&lt;p>ग्राफ का मूल्यांकन करते समय (फॉरवर्ड पास), टोपोलॉजिकल सॉर्ट का उपयोग उन नोड्स को संसाधित करने के लिए किया जाता है जिनमें कोई निर्भरता नहीं है। यदि यह केवल इन्फेरेंस के लिए है, तो बैकप्रोपेगेशन के लिए ग्रेडिएंट रखने की आवश्यकता नहीं होती है, इसलिए मेमोरी प्रबंधन बहुत सरल हो जाता है।&lt;/p>
&lt;hr>
&lt;h2 id="6-गणत-और-अनकलन-क-मल-मटरकस-गणन-gemm">6. गणित और अनुकूलन का मूल: मैट्रिक्स गुणन (GEMM)
&lt;/h2>&lt;p>AI अनुमान के लिए 90% से अधिक कम्प्यूटेशन समय मैट्रिक्स गुणन (GEMM: General Matrix Multiply) पर खर्च होता है। ट्रांसफॉर्मर मॉडल के मूल में अटेंशन मैकेनिज्म और फीडफॉरवर्ड नेटवर्क (FFN) दोनों अंततः विशाल मैट्रिक्स गुणन ही हैं।&lt;/p>
&lt;p>2 मैट्रिक्स $A$ (आकार $M \times K$) और $B$ (आकार $K \times N$) का गुणनफल $C = A B$ (आकार $M \times N$) को सूत्र के रूप में इस प्रकार व्यक्त किया जाता है:&lt;/p>
$$
C_{i,j} = \sum_{k=0}^{K-1} A_{i,k} \cdot B_{k,j}
$$
&lt;p>यदि इसे साधारण ट्रिपल लूप के साथ लागू किया जाता है, तो कैश मिस (cache miss) बार-बार होगा और प्रदर्शन बिल्कुल भी नहीं मिलेगा।&lt;/p>
&lt;h3 id="61-cpu-पर-कश-बलकग-और-simd-अनकलन">6.1 CPU पर कैश ब्लॉकिंग और SIMD अनुकूलन
&lt;/h3>&lt;p>CPU पर GEMM को गति देने की बुनियादी रणनीति इस प्रकार है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>लूप टाइलिंग (कैश ब्लॉकिंग)&lt;/strong>: मैट्रिक्स को छोटे ब्लॉकों में विभाजित करें जो गणना के लिए L1/L2 कैश में फिट होते हैं।&lt;/li>
&lt;li>&lt;strong>डेटा पैकिंग&lt;/strong>: मेमोरी एक्सेस पैटर्न को सन्निहित (contiguous) बनाने के लिए आंतरिक रूप से डेटा को पुनर्व्यवस्थित करें।&lt;/li>
&lt;li>&lt;strong>SIMD का उपयोग&lt;/strong>: AVX-512 में &lt;code>_mm512_fmadd_ps&lt;/code> जैसे FMA (Fused Multiply-Add) निर्देशों का उपयोग करके एक ही घड़ी चक्र (clock cycle) में कई गुणा-जोड़ कार्य करें।&lt;/li>
&lt;/ol>
&lt;p>नीचे C++ और SIMD इंट्रिंसिक्स का उपयोग करते हुए एक सरलीकृत वेक्टर डॉट उत्पाद (Dot Product) का उदाहरण दिया गया है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;immintrin.h&amp;gt;&lt;/span>&lt;span class="cp"> &lt;/span>&lt;span class="c1">// AVX निर्देशों के लिए
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// AVX2 का उपयोग करके FP32 के लिए तेज़ डॉट उत्पाद
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">float&lt;/span> &lt;span class="nf">dot_product_avx2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">__m256&lt;/span> &lt;span class="n">sum256&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_setzero_ps&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// एक बार में 8 तत्वों को संसाधित करें (256 बिट्स = 32 बाइट्स = 8 * 4 बाइट्स)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">__m256&lt;/span> &lt;span class="n">va&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_loadu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">__m256&lt;/span> &lt;span class="n">vb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_loadu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// FMA निर्देश: sum256 = va * vb + sum256
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sum256&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">_mm256_fmadd_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">va&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vb&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sum256&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// SIMD रजिस्टर में मानों का क्षैतिज योग (Horizontal Add)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">float&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">_mm256_storeu_ps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sum256&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">float&lt;/span> &lt;span class="n">dot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// शेष तत्वों को संभालना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">dot&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">dot&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>यहां तक कि यह छोटा सा प्रयास भी एक भोले-भाले (naive) कार्यान्वयन की तुलना में गति में कई गुना सुधार कर सकता है।&lt;/p>
&lt;hr>
&lt;h2 id="7-हरडवयर-बधओ-क-पर-करन-cuda-और-metal-बकएड-क-एककरण">7. हार्डवेयर बाधाओं को पार करना: CUDA और Metal बैकएंड का एकीकरण
&lt;/h2>&lt;p>हालाँकि एक शुद्ध C++ कार्यान्वयन CPU पर ठीक-ठाक काम करता है, लेकिन LLM जैसे विशाल मॉडलों को व्यावहारिक गति (उदा. 20 टोकन प्रति सेकंड उत्पन्न करना) से चलाने के लिए, GPU की समानांतर गणना (parallel computing) क्षमता अपरिहार्य है। इसलिए, हम अपने इंजन में बैकएंड एब्स्ट्रैक्शन लेयर पेश करते हैं।&lt;/p>
&lt;h3 id="71-बकएड-एबसटरकशन">7.1 बैकएंड एब्स्ट्रैक्शन
&lt;/h3>&lt;p>हम C++ के पॉलीमोर्फिज्म (polymorphism) का उपयोग करते हैं ताकि गणनाओं के निष्पादक (Executor) को स्विच किया जा सके।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Backend&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">Backend&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">alloc_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">free_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">copy_to_device&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">copy_to_host&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// विभिन्न परिचालनों का निष्पादन
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">compute_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">compute_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="72-nvidia-cuda-बकएड-क-करयनवयन">7.2 NVIDIA CUDA बैकएंड का कार्यान्वयन
&lt;/h3>&lt;p>NVIDIA GPU का लाभ उठाने के लिए, हम CUDA C++ एक्सटेंशन का उपयोग करके बैकएंड लागू करते हैं। यद्यपि अपना स्वयं का कर्नेल लिखना संभव है, लेकिन मैट्रिक्स गुणन के लिए NVIDIA द्वारा प्रदान की गई सर्वोच्च लाइब्रेरी &amp;ldquo;cuBLAS&amp;rdquo; का उपयोग करना सबसे अच्छा दृष्टिकोण है।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cublas_v2.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cuda_runtime.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">CUDABackend&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">public&lt;/span> &lt;span class="n">Backend&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cublasHandle_t&lt;/span> &lt;span class="n">handle&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CUDABackend&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cublasCreate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">CUDABackend&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cublasDestroy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">compute_mul_mat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Tensor&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">dst&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">override&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// CUDA में डिफ़ॉल्ट रूप से Column-Major होता है, इसलिए मापदंडों पर ध्यान दें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span> &lt;span class="n">alpha&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">1.0f&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span> &lt;span class="n">beta&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0f&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">src1&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ne&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// मानते हुए कि src1 ट्रांसपोज़ किया गया है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cublasSgemm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CUBLAS_OP_T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CUBLAS_OP_N&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">alpha&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">src0&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">src1&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">beta&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">dst&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cudaDeviceSynchronize&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>CUDA मेमोरी और होस्ट (CPU) मेमोरी के बीच डेटा ट्रांसफर (&lt;code>cudaMemcpy&lt;/code>) बहुत भारी (heavy) होता है, इसलिए यह महत्वपूर्ण है कि इन्फेरेंस के दौरान VRAM पर सभी वेट (वजन टेंसर) और मध्यवर्ती टेंसर को यथासंभव बनाए रखा जाए।&lt;/p>
&lt;h3 id="73-apple-silicon-metal-बकएड">7.3 Apple Silicon (Metal) बैकएंड
&lt;/h3>&lt;p>हाल के वर्षों में, Mac के M1/M2/M3 चिप्स (Apple Silicon) AI इन्फेरेंस मशीन के रूप में उत्कृष्ट हैं। इसका कारण &amp;ldquo;यूनिफाइड मेमोरी (Unified Memory)&amp;rdquo; है। चूँकि CPU और GPU एक ही मेमोरी स्पेस साझा करते हैं, ऊपर बताए गए CUDA की तरह PCIe बस पर उच्च-लागत वाले होस्ट-टू-डिवाइस मेमोरी ट्रांसफर की बिल्कुल आवश्यकता नहीं होती है।&lt;/p>
&lt;p>C++ से Metal को कॉल करने极, ऑब्जेक्टिव-C++ (&lt;code>.mm&lt;/code> फ़ाइलें) को ब्रिज के रूप में उपयोग करें या &lt;code>metal-cpp&lt;/code> लाइब्रेरी का उपयोग करें।
Metal Compute Shader का उपयोग करके कर्नेल लिखें (जिसे &lt;code>.metal&lt;/code> फ़ाइल में C++ की तरह लिखा गया है)।&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Metal शेडर (kernel.metal)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;metal_stdlib&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">metal&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">kernel&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">mul_mat_kernel&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="p">[[&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)]],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="na">[[buffer(1)]]&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device&lt;/span> &lt;span class="kt">float&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="na">[[buffer(2)]]&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">constant&lt;/span> &lt;span class="n">uint3&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">dims&lt;/span> &lt;span class="na">[[buffer(3)]]&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uint2&lt;/span> &lt;span class="n">gid&lt;/span> &lt;span class="na">[[thread_position_in_grid]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uint&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dims&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">z&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uint&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gid&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">uint&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gid&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">col&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">float&lt;/span> &lt;span class="n">sum&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0.0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">uint&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sum&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">k&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">col&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// सरलीकृत
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">C&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">row&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">col&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sum&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Apple Silicon वातावरण में, MPS (Metal Performance Shaders) नामक मैट्रिक्स गुणन के लिए एक अनुकूलित लाइब्रेरी भी प्रदान की जाती है, इसलिए उत्पादन में इसका उपयोग करके अद्भुत इन्फेरेंस गति प्राप्त की जा सकती है।&lt;/p>
&lt;hr>
&lt;h2 id="8-टरसफरमर-मडल-वशषट-परससकरण-अटशन-और-kv-कश">8. ट्रांसफॉर्मर मॉडल विशिष्ट प्रसंस्करण: अटेंशन और KV कैश
&lt;/h2>&lt;p>LLaMA 2/3 और GPT जैसे अत्याधुनिक LLM ट्रांसफॉर्मर आर्किटेक्चर पर आधारित हैं। C++ में इसे लागू करने के लिए, निम्नलिखित सूत्र द्वारा दर्शाए गए &amp;ldquo;स्केल्ड डॉट-प्रोडक्ट अटेंशन (Scaled Dot-Product Attention)&amp;rdquo; का निर्माण आवश्यक है:&lt;/p>
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
&lt;p>इसके अलावा, ऑटोरेग्रेसिव (Autoregressive) टोकन जनरेशन में, पिछले टोकन (Key और Value) के गणना परिणामों को बनाए रखना आवश्यक है। इसे &amp;ldquo;&lt;strong>KV कैश (Key-Value Cache)&lt;/strong>&amp;rdquo; कहा जाता है।&lt;/p>
&lt;div class="mermaid">graph TD
T["वर्तमान टोकन"] --> Q["क्वेरी (Query)"]
T --> K["कुंजी (Key)"]
T --> V["मान (Value)"]
K --> KCache["KV कैश में जोड़ें"]
V --> VCache["KV कैश में जोड़ें"]
Q --> Dot1["Q * K_Cache^T"]
KCache --> Dot1
Dot1 --> Scale["स्केल (1/sqrt(d))"]
Scale --> Softmax["सॉफ्टमैक्स (Softmax)"]
Softmax --> Dot2["SoftmaxOut * V_Cache"]
VCache --> Dot2
Dot2 --> Out["संदर्भ वेक्टर (Context Vector)"]&lt;/div>
&lt;p>KV कैश मेमोरी का आवंटन भी एक रिंग बफर की तरह काम करता है, जो एरिना में पहले से अधिकतम संदर्भ लंबाई (उदा. 4096 या 8192 टोकन) के लिए मेमोरी स्पेस आरक्षित करता है। यह प्रत्येक जनरेशन चरण में पुनर्आवंटन को रोकता है।&lt;/p>
&lt;p>स्थिति एन्कोडिंग (Positional Encoding) के लिए, हम &amp;ldquo;RoPE (Rotary Position Embedding)&amp;rdquo; लागू करते हैं, जो हाल के वर्षों में मुख्यधारा बन गया है। यह वह तकनीक है जो जटिल स्थान (complex space) में घूर्णन वैक्टर के रूप में स्थितीय जानकारी को एम्बेड करती है। C++ में &lt;code>sin&lt;/code> और &lt;code>cos&lt;/code> फ़ंक्शन कॉल (जैसे लुकअप टेबल) का अनुकूलन प्रदर्शन की कुंजी है।&lt;/p>
&lt;hr>
&lt;h2 id="9-मडल-कवटजशन-quantization-क-मधयम-स-चरम-अनकलन">9. मॉडल क्वांटिज़ेशन (Quantization) के माध्यम से चरम अनुकूलन
&lt;/h2>&lt;p>यदि आप एक बड़े पैमाने के मॉडल (उदाहरण के लिए, 7 बिलियन पैरामीटर वाला LLaMA मॉडल) को FP32 (32-बिट फ्लोटिंग पॉइंट) के रूप में लोड करते हैं, तो यह अकेले वज़न के लिए लगभग 28GB मेमोरी (VRAM) की खपत करता है। यदि आप KV कैश और इन्फेरेंस बफ़र्स को शामिल करते हैं, तो यह आसानी से 30GB से अधिक हो जाता है, जिससे इसे सामान्य उपभोक्ता GPU पर चलाना असंभव हो जाता है।&lt;/p>
&lt;p>यहीं पर &amp;ldquo;&lt;strong>क्वांटिज़ेशन (Quantization)&lt;/strong>&amp;rdquo; अपरिहार्य हो जाता है। यह GGML प्रारूप का असली मूल्य है।&lt;/p>
&lt;p>क्वांटिज़ेशन जानबूझकर वजन की सटीकता को कम करने की तकनीक है।&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FP16 (16-बिट)&lt;/strong>: आकार आधा। सटीकता में लगभग कोई गिरावट नहीं।&lt;/li>
&lt;li>&lt;strong>INT8 (8-बिट)&lt;/strong>: आकार 1/4। मामूली गिरावट।&lt;/li>
&lt;li>&lt;strong>INT4 (4-बिट)&lt;/strong>: आकार 1/8। अद्वितीय ब्लॉकिंग और स्केलिंग कारकों का उपयोग करके व्यावहारिक इन्फेरेंस संभव है।&lt;/li>
&lt;/ul>
&lt;p>इन्फेरेंस इंजन की तरफ से, यह मेमोरी से INT4 (या INT8) में संपीड़ित (compressed) वजन पढ़ता है, और &lt;strong>इसे CPU या GPU रजिस्टर में लोड करने के ठीक बाद, गणना करने के लिए इसे FP16 या FP32 (Dequantize) में विस्तारित करता है&lt;/strong>।&lt;/p>
&lt;p>हैरानी की बात है कि मेमोरी से पढ़े जाने वाले डेटा की मात्रा को कम करना, भले ही इससे गणना की मात्रा बढ़ जाए, तेज़ होता है। ऐसा इसलिए है क्योंकि आधुनिक हार्डवेयर में, इन्फेरेंस कार्यों की बाधा (bottleneck) &amp;ldquo;कंप्यूट बॉउंड (Compute Bound)&amp;rdquo; नहीं बल्कि &amp;ldquo;&lt;strong>मेमोरी बैंडविड्थ बॉउंड (Memory Bandwidth Bound)&lt;/strong>&amp;rdquo; है। INT4 क्वांटिज़ेशन वाले C++ कार्यान्वयन इंजन के साथ, 8GB VRAM वाले MacBook Air पर भी सुचारू रूप से लोकल LLM चलाना संभव है।&lt;/p>
&lt;hr>
&lt;h2 id="10-परदरशन-टयनग-numa-आरकटकचर-और-थरड-पल">10. प्रदर्शन ट्यूनिंग: NUMA आर्किटेक्चर और थ्रेड पूल
&lt;/h2>&lt;p>CPU का उपयोग करके इन्फेरेंस करते समय, मल्टी-थ्रेडिंग आवश्यक है। हालाँकि, केवल कई &lt;code>std::thread&lt;/code> लॉन्च करना इष्टतम नहीं है।&lt;/p>
&lt;p>आधुनिक मल्टी-सॉकेट सर्वर और हाई-एंड CPU जैसे Ryzen Threadripper, &lt;strong>NUMA (Non-Uniform Memory Access)&lt;/strong> आर्किटेक्चर को अपनाते हैं। किसी निश्चित CPU कोर से भौतिक रूप से करीब (लोकल मेमोरी) मेमोरी तक पहुंच तेज़ होती है, लेकिन दूसरे प्रोसेसर से जुड़ी मेमोरी तक पहुंच बेहद धीमी होती है।&lt;/p>
&lt;p>उन्नत C++ इन्फेरेंस इंजन में निम्नलिखित तकनीकों का उपयोग किया जाता है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>थ्रेड पिनिंग (Thread Pinning)&lt;/strong>: कॉन्टेक्स्ट स्विचिंग के कारण कैश के अमान्य होने को रोकने के लिए प्रत्येक थ्रेड को एक विशिष्ट CPU कोर (एफिनिटी सेट करना) पर पिन करना।&lt;/li>
&lt;li>&lt;strong>NUMA-अवेयर आवंटन&lt;/strong>: डेटा को संसाधित करने वाले थ्रेड के समान NUMA नोड पर मेमोरी आवंटित करना।&lt;/li>
&lt;li>&lt;strong>वर्क-स्टीलिंग थ्रेड पूल&lt;/strong>: एक कुशल शेड्यूलर लागू करना जो कम्प्यूटेशन ग्राफ के प्रत्येक नोड को छोटे कार्यों में विभाजित करता है, और निष्क्रिय थ्रेड स्वचालित रूप से कार्यों को चुराते और निष्पादित करते हैं।&lt;/li>
&lt;/ol>
&lt;p>इनका पूरा उपयोग करके, आप CPU उपयोग को 100% के करीब रख सकते हैं और सैद्धांतिक मान के करीब थ्रूपुट (throughput) प्राप्त कर सकते हैं।&lt;/p>
&lt;hr>
&lt;h2 id="11-नषकरष-c-क-मसपशय-क-सथ-ai-क-चलन-क-मज">11. निष्कर्ष: C++ की &amp;ldquo;मांसपेशियों&amp;rdquo; के साथ AI को चलाने का मज़ा
&lt;/h2>&lt;p>पायथन निश्चित रूप से सुविधाजनक है। अनुसंधान, विकास और प्रोटोटाइपिंग में, उत्पादकता के मामले में कोई भी भाषा इसके बराबर नहीं है। हालाँकि, जिस क्षण आप पूर्ण किए गए मॉडल को &amp;ldquo;वास्तविक दुनिया में, कुशलतापूर्वक, किसी भी डिवाइस पर चलाने&amp;rdquo; के चरण में जाते हैं, C++ का समय आ जाता है।&lt;/p>
&lt;p>मेमोरी के बाइट्स में सीधे हेरफेर करना, SIMD निर्देशों के साथ रजिस्टरों को उनकी सीमा तक धकेलना, और GPU की VRAM बैंडविड्थ से जूझते हुए बनाए गए इन्फेरेंस इंजन को कंसोल पर एक के बाद एक प्राकृतिक टेक्स्ट (टोकन) उत्पन्न करते हुए देखने पर जो उपलब्धि की भावना मिलती है, वह पायथन फ्रेमवर्क में &lt;code>model.generate()&lt;/code> को कॉल करने पर कभी प्राप्त नहीं हो सकती। यह &amp;ldquo;एक इंजीनियर के रूप में शुद्ध आनंद&amp;rdquo; है।&lt;/p>
&lt;p>AI तकनीक, जो एक &amp;ldquo;ब्लैक बॉक्स (Black Box)&amp;rdquo; बन जाती है, को टेंसर संचालन से लेकर मेमोरी आवंटन तक सब कुछ अपने हाथों से C++ में लिखकर, आप गहराई से समझ सकते हैं कि LLM कैसे &amp;ldquo;सोचता&amp;rdquo; है और इसके सही तंत्र क्या हैं।&lt;/p>
&lt;p>यदि आपको C++ का बुनियादी ज्ञान है और वर्तमान AI तकनीक में आपकी गहरी रुचि है, तो कृपया अपना खुद का इन्फेरेंस इंजन विकसित करने का प्रयास करें। GGML और llama.cpp का सोर्स कोड सबसे अच्छी जीवित पाठ्यपुस्तकें (living textbooks) होंगी।&lt;/p>
&lt;p>&lt;strong>तो चलिए, पायथन के भारी रनटाइम को छोड़ दें, और C++ की मांसपेशियों के साथ अत्याधुनिक AI चलाएं!&lt;/strong>&lt;/p></description></item><item><title>C++ के साथ छोटे AI मॉडल (जैसे TinyLLaMA) विकसित करने की प्रक्रिया</title><link>http://kenji.blog/hi/p/cpp-small-ai-model-tinyllama-dev-guide/</link><pubDate>Fri, 11 Sep 2026 14:00:00 +0900</pubDate><guid>http://kenji.blog/hi/p/cpp-small-ai-model-tinyllama-dev-guide/</guid><description>&lt;img src="http://kenji.blog/p/cpp-small-ai-model-tinyllama-dev-guide/img/eyecatch.jpg" alt="Featured image of post C++ के साथ छोटे AI मॉडल (जैसे TinyLLaMA) विकसित करने की प्रक्रिया" />&lt;h1 id="c-क-सथ-छट-ai-मडल-जस-tinyllama-वकसत-करन-क-परकरय">C++ के साथ छोटे AI मॉडल (जैसे TinyLLaMA) विकसित करने की प्रक्रिया
&lt;/h1>&lt;p>हाल के वर्षों में, स्थानीय वातावरण में बड़े भाषा मॉडल (LLM) चलाने में रुचि तेजी से बढ़ी है। विशेष रूप से, TinyLLaMA (1.1B पैरामीटर) जैसे छोटे मॉडल सीमित संसाधनों वाले एज डिवाइस और सामान्य लैपटॉप (Windows वातावरण सहित) पर भी व्यावहारिक गति से अनुमान लगाने में सक्षम हैं। जहाँ Python और PyTorch का उपयोग करके विकास मुख्यधारा है, वहीं जब अंतिम प्रदर्शन और मेमोरी दक्षता की बात आती है, तो C++ और C-आधारित टेंसर लाइब्रेरी &amp;ldquo;ggml&amp;rdquo; का संयोजन वास्तविक मानक बन गया है।&lt;/p>
&lt;p>इस लेख में, हम C++ का उपयोग करके TinyLLaMA को लोड करने और पाठ निर्माण के लिए एक अनुमान इंजन को शून्य से बनाने (या मौजूदा llama.cpp की आंतरिक संरचना को गहराई से समझने) के लिए एक बहुत ही विस्तृत विकास प्रक्रिया की व्याख्या करेंगे।&lt;/p>
&lt;hr>
&lt;h2 id="1-c-और-ggml-ह-कय">1. C++ और ggml ही क्यों?
&lt;/h2>&lt;p>AI के प्रशिक्षण चरण में, Python अपने लचीलेपन और समृद्ध इकोसिस्टम के कारण अत्यधिक लाभप्रद है। हालाँकि, परिनियोजन (डिप्लॉयमेंट) या &amp;ldquo;अनुमान (Inference)&amp;rdquo; के चरण में, निम्नलिखित कारणों से C++ एक शक्तिशाली विकल्प बन जाता है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>ओवरहेड में कमी&lt;/strong>: Python के ग्लोबल इंटरप्रेटर लॉक (GIL) और रनटाइम ओवरहेड को पूरी तरह से समाप्त किया जा सकता है।&lt;/li>
&lt;li>&lt;strong>मेमोरी दक्षता और एरिना एलोकेशन&lt;/strong>: चूँकि मेमोरी के आवंटन और मुक्ति को मैन्युअल रूप से नियंत्रित किया जा सकता है, इसलिए गार्बेज कलेक्शन के कारण होने वाले अप्रत्याशित स्पाइक्स को रोका जा सकता है।&lt;/li>
&lt;li>&lt;strong>हार्डवेयर तक सीधी पहुँच&lt;/strong>: AVX-512, AVX2, और ARM NEON जैसे SIMD इंट्रिंसिक्स (Intrinsics) को सीधे कॉल किया जा सकता है, जिससे CPU की गणना क्षमता को अधिकतम किया जा सकता है।&lt;/li>
&lt;li>&lt;strong>निर्भरता का उन्मूलन&lt;/strong>: ggml शून्य-निर्भरता (Zero dependencies) वाली एक C/C++ लाइब्रेरी है, और इसे केवल एक कंपाइलर के साथ Windows पर MSVC वातावरण में भी आसानी से बनाया (बिल्ड किया) जा सकता है।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="2-वसतकल-क-समगर-चतर-आरकटकचर-ओवरवय">2. वास्तुकला का समग्र चित्र (आर्किटेक्चर ओवरव्यू)
&lt;/h2>&lt;p>संपूर्ण अनुमान पाइपलाइन का प्रवाह नीचे दिए गए Mermaid आरेख में दिखाया गया है। यह उपयोगकर्ता के इनपुट पाठ से शुरू होकर अंततः अगले टोकन के उत्पन्न होने तक की एक श्रृंखला है।&lt;/p>
&lt;div class="mermaid">graph TD
A["उपयोगकर्ता इनपुट पाठ"] --> B["BPE टोकनाइज़र"]
B --> C["टोकन आईडी एरे"]
C --> D["एम्बेडिंग लेयर लुकअप"]
D --> E["ट्रांसफॉर्मर ब्लॉक्स"]
E --> F["RMSNorm"]
F --> G["LM हेड लेयर"]
G --> H["लॉजिट्स एरे"]
H --> I["सैंपलर मॉड्यूल"]
I --> J["अगला टोकन आईडी"]
J --> K["डिटोकनाइज़र"]
K --> L["आउटपुट टेक्स्ट चंक"]
J -.-> |"संदर्भ में जोड़ें"| C&lt;/div>
&lt;p>चूँकि यह एक ऑटो-रिग्रेसिव मॉडल है, इसलिए आउटपुट टोकन को फिर से संदर्भ (कॉन्टेक्स्ट) में जोड़ा जाता है और यह अगले टोकन की भविष्यवाणी के लिए इनपुट के रूप में चक्रित होता है (आरेख में बिंदीदार रेखा वाला भाग)।&lt;/p>
&lt;hr>
&lt;h2 id="3-मडल-पररप-और-ममर-मपग-mmap">3. मॉडल प्रारूप और मेमोरी मैपिंग (mmap)
&lt;/h2>&lt;p>विशाल न्यूरल नेटवर्क के वेट्स (weights) को संभालने में सबसे बड़ी बाधा डिस्क I/O और मेमोरी की खपत है। C++ कार्यान्वयन में इसे &lt;strong>मेमोरी मैपिंग (mmap)&lt;/strong> से हल किया जाता है।&lt;/p>
&lt;h3 id="31-ममर-मपग-क-ततर-और-windows-म-करयनवयन">3.1 मेमोरी मैपिंग का तंत्र और Windows में कार्यान्वयन
&lt;/h3>&lt;p>mmap का उपयोग करने से, फ़ाइल की सामग्री को सीधे प्रक्रिया के वर्चुअल मेमोरी स्पेस में मैप किया जा सकता है।&lt;/p>
&lt;ul>
&lt;li>&lt;strong>ज़ीरो-कॉपी (Zero-copy)&lt;/strong>: डेटा सीधे डिस्क से कर्नेल के पेज कैश में पढ़ा जाता है, जिससे यूज़र स्पेस में कोई अतिरिक्त कॉपी नहीं होती।&lt;/li>
&lt;li>&lt;strong>ऑन-डिमांड लोड (Page Fault)&lt;/strong>: जब CPU वास्तव में उस मेमोरी एड्रेस तक पहुँचता है, तभी एक पेज फॉल्ट होता है, और केवल आवश्यक चंक (आमतौर पर 4KB) भौतिक मेमोरी में लोड होता है।&lt;/li>
&lt;/ul>
&lt;p>Windows वातावरण में, POSIX के &lt;code>mmap&lt;/code> के बजाय Win32 API के &lt;code>CreateFileMapping&lt;/code> और &lt;code>MapViewOfFile&lt;/code> का उपयोग किया जाता है।&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant OS["Windows OS"]
participant RAM["भौतिक मेमोरी"]
participant App["C++ एप्लिकेशन"]
App->>OS: "CreateFileMapping / MapViewOfFile"
OS-->>App: "वर्चुअल मेमोरी एड्रेस पॉइंटर"
App->>App: "पॉइंटर पर टेंसर डेटा पढ़ें"
OS->>RAM: "पेज फॉल्ट / डिस्क से पेज लोड करें"
RAM-->>App: "SIMD गणना के लिए डेटा तैयार है"&lt;/div>
&lt;h3 id="32-gguf-पररप-क-बइनर-सरचन">3.2 GGUF प्रारूप की बाइनरी संरचना
&lt;/h3>&lt;p>Hugging Face जैसे प्लेटफार्मों से &lt;code>.safetensors&lt;/code> प्रारूप से परिवर्तित &lt;strong>GGUF (GPT-Generated Unified Format)&lt;/strong> अनुमान के लिए अंतिम प्रारूप है। इसका एक सख्त बाइनरी लेआउट है जैसा कि नीचे दिया गया है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>मैजिक बाइट्स (Magic Bytes)&lt;/strong>: &lt;code>0x46554747&lt;/code> (GGUF)।&lt;/li>
&lt;li>&lt;strong>संस्करण (Version)&lt;/strong>: प्रारूप का संस्करण क्रमांक।&lt;/li>
&lt;li>&lt;strong>टेंसर गणना और मेटाडेटा गणना&lt;/strong>: टेंसर की संख्या और मेटाडेटा के की-वैल्यू पेयर की संख्या।&lt;/li>
&lt;li>&lt;strong>मेटाडेटा (Key-Value Pairs)&lt;/strong>: स्ट्रिंग लेंथ प्रीफिक्स के साथ की (Key), और टाइप की गई वैल्यू।&lt;/li>
&lt;li>&lt;strong>टेंसर इन्फो (Tensor Info)&lt;/strong>: प्रत्येक टेंसर का नाम, आयामों की संख्या, डेटा प्रकार (FP16, Q4_K आदि), और फ़ाइल के भीतर ऑफ़सेट स्थिति।&lt;/li>
&lt;li>&lt;strong>पैडिंग (Padding)&lt;/strong>: पैडिंग डाली जाती है ताकि टेंसर डेटा एक विशिष्ट सीमा (आमतौर पर 32 बाइट्स या 64 बाइट्स) पर संरेखित (aligned) हो। यह SIMD निर्देशों (विशेष रूप से AVX) में उच्च गति मेमोरी एक्सेस के लिए आवश्यक है।&lt;/li>
&lt;li>&lt;strong>टेंसर डेटा&lt;/strong>: संरेखित वास्तविक वेट (weight) डेटा एरे।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-tinyllama-क-गणतय-आधर-और-c-एलगरदम">4. TinyLLaMA का गणितीय आधार और C++ एल्गोरिदम
&lt;/h2>&lt;p>TinyLLaMA दक्षता के लिए कई उन्नत आर्किटेक्चरल तकनीकों को शामिल करता है। C++ में इन्हें सही ढंग से लागू करने के लिए हम गणितीय अभिव्यक्तियों की व्याख्या करेंगे।&lt;/p>
&lt;h3 id="41-rmsnorm-root-mean-square-normalization">4.1 RMSNorm (Root Mean Square Normalization)
&lt;/h3>&lt;p>LayerNorm से माध्य (mean) की सेंटरिंग को हटाकर और केवल वेरिएंस स्केलिंग करके गणना लागत को कम किया जाता है।&lt;/p>
$$ \text{RMSNorm}(x) = \frac{x}{\sqrt{\frac{1}{d}\sum_{i=1}^{d} x_i^2 + \epsilon}} \odot \gamma $$
&lt;p>$d$ आयामों की संख्या है, $\gamma$ सीखा हुआ स्केलिंग टेंसर है।
C++ में इसे लागू करते समय, एरे के वर्ग का योग पहले AVX2 के &lt;code>_mm256_fmadd_ps&lt;/code> आदि के साथ उच्च गति से गणना किया जाता है, और फिर व्युत्क्रम वर्गमूल (जैसे &lt;code>_mm256_rsqrt_ps&lt;/code> निर्देश) से गुणा करके इसे अनुकूलित किया जाता है।&lt;/p>
&lt;h3 id="42-rope-rotary-position-embedding">4.2 RoPE (Rotary Position Embedding)
&lt;/h3>&lt;p>यह एक ऐसी तकनीक है जो टेंसर स्पेस में रोटेशन (Rotate) के रूप में टोकन की स्थितिगत जानकारी लागू करती है। इसे जटिल संख्या तल (complex plane) पर रोटेशन माना जा सकता है, और वेक्टर $x$ के आसन्न आयाम जोड़े $(x_1, x_2)$ पर निम्नलिखित रोटेशन लागू किया जाता है।&lt;/p>
$$ \text{RoPE}(x, m) = \begin{pmatrix} x_{1} \cos(m\theta) - x_{2} \sin(m\theta) \\ x_{1} \sin(m\theta) + x_{2} \cos(m\theta) \end{pmatrix} $$
&lt;p>यहाँ, $m$ टोकन का पूर्ण स्थिति सूचकांक है, और $\theta$ पूर्व-गणना की गई मूल आवृत्ति है। ggml में, अनुमान ग्राफ के निर्माण के दौरान &lt;code>ggml_rope&lt;/code> ऑपरेटर जोड़ने से यह समानांतर रूप से निष्पादित होता है।&lt;/p>
&lt;h3 id="43-grouped-query-attention-gqa">4.3 Grouped-Query Attention (GQA)
&lt;/h3>&lt;p>सामान्य Multi-Head Attention (MHA) में, Query, Key और Value प्रत्येक के लिए समान संख्या में हेड्स होते हैं। हालाँकि, TinyLLaMA मेमोरी बैंडविड्थ और KV कैश खपत को भारी मात्रा में कम करने के लिए &lt;strong>Grouped-Query Attention (GQA)&lt;/strong> का उपयोग करता है।&lt;/p>
$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V $$
&lt;p>GQA में, कई Query हेड्स एक ही Key/Value हेड साझा shared करते हैं। C++ कार्यान्वयन में, मैट्रिक्स गुणा &lt;code>ggml_mul_mat&lt;/code> निष्पादित करने से पहले, Query की संख्या से मेल खाने के लिए KV टेंसर को ब्रॉडकास्ट करने की आवश्यकता होती है।&lt;/p>
&lt;h3 id="44-swiglu-एकटवशन-फकशन">4.4 SwiGLU एक्टिवेशन फ़ंक्शन
&lt;/h3>&lt;p>Feed-Forward Network (FFN) लेयर में, GELU के बजाय SwiGLU का उपयोग किया जाता है।&lt;/p>
$$ \text{SwiGLU}(x) = \text{Swish}(x W_{\text{gate}}) \otimes (x W_{\text{up}}) $$
$$ \text{Swish}(z) = z \cdot \sigma(z) = z \cdot \frac{1}{1 + e^{-z}} $$
&lt;p>कम्प्यूटेशन ग्राफ में, इसे &lt;code>ggml_silu&lt;/code> ऑपरेटर और &lt;code>ggml_mul&lt;/code> के संयोजन से दर्शाया जाता है।&lt;/p>
&lt;hr>
&lt;h2 id="5-ggml-क-सथ-कमपयटशन-गरफ-क-नरमण-और-ममर-परबधन">5. ggml के साथ कम्प्यूटेशन ग्राफ का निर्माण और मेमोरी प्रबंधन
&lt;/h2>&lt;p>ggml &amp;ldquo;Define-and-Run&amp;rdquo; दृष्टिकोण अपनाता है, जहाँ यह अनुमान के लिए एक स्थिर कम्प्यूटेशन ग्राफ बनाता है और बाद में उसका मूल्यांकन (evaluate) करता है।&lt;/p>
&lt;h3 id="51-ggml_context-और-एरन-एलकटर">5.1 ggml_context और एरिना एलोकेटर
&lt;/h3>&lt;p>ggml की सबसे अनूठी विशेषता &amp;ldquo;एरिना एलोकेशन&amp;rdquo; है, जो अनुमान लूप के भीतर कोई डायनामिक मेमोरी आवंटन (&lt;code>malloc&lt;/code> या &lt;code>new&lt;/code>) नहीं करता है।
प्रारंभिकरण के दौरान, एक विशाल निरंतर मेमोरी क्षेत्र (एरिना) सुरक्षित किया जाता है, और जब भी &lt;code>ggml_new_tensor&lt;/code> आदि को कॉल किया जाता है, तो इस क्षेत्र का पॉइंटर बढ़ा (increment) दिया जाता है। एक अनुमान चरण के पूरा होने के बाद, आवंटन पॉइंटर को प्रारंभिक स्थिति में रीसेट करने से, अगले अनुमान चरण के लिए मेमोरी आवंटन तुरंत पूरा हो जाता है।&lt;/p>
&lt;h3 id="52-गरफ-नरमण-क-वशषट-उदहरण">5.2 ग्राफ निर्माण का विशिष्ट उदाहरण
&lt;/h3>&lt;p>प्रत्येक अनुमान चरण के लिए, मेमोरी में निम्नलिखित कम्प्यूटेशन ग्राफ बनाया जाता है।&lt;/p>
&lt;div class="mermaid">graph TD
A["टोकन इनपुट आईडी"] --> B["एम्बेड लुकअप"]
B --> C["ggml_rms_norm"]
C --> D["Q / K / V प्रोजेक्शन्स"]
D --> E["ggml_rope पोजीशनल"]
E --> F["KV कैश स्टोर"]
E --> G["KV कैश लोड"]
G --> H["सेल्फ अटेंशन"]
H --> I["स्केल और सॉफ्टमैक्स"]
I --> J["अटेंशन आउटपुट"]
J --> K["आउट प्रोजेक्शन"]
K --> L["अवशिष्ट जोड़ें (Add Residual)"]&lt;/div>
&lt;hr>
&lt;h2 id="6-कवटइजशन-quantization-और-windows--simd-ऑपटमइजशन">6. क्वांटाइज़ेशन (Quantization) और Windows / SIMD ऑप्टिमाइज़ेशन
&lt;/h2>&lt;p>TinyLLaMA (1.1B) को FP16 में सँभालने के लिए लगभग 2.2GB मेमोरी की आवश्यकता होती है, लेकिन 4-बिट क्वांटाइज़ेशन (जैसे Q4_K) के साथ इसे नाटकीय रूप से लगभग 600MB तक संपीड़ित किया जा सकता है।&lt;/p>
&lt;h3 id="61-बलक-कवटइजशन-आरकटकचर">6.1 ब्लॉक क्वांटाइज़ेशन आर्किटेक्चर
&lt;/h3>&lt;p>ggml पूरे टेंसर को एक साथ क्वांटाइज़ करने के बजाय इसे &amp;ldquo;ब्लॉक&amp;rdquo; के आधार पर करता है।
&lt;code>Q4_0&lt;/code> प्रारूप में, 32 FP16 मानों को एक ब्लॉक में समूहीकृत किया जाता है।&lt;/p>
&lt;ul>
&lt;li>&lt;strong>स्केल फैक्टर&lt;/strong>: 1 FP16 मान (2 बाइट्स)&lt;/li>
&lt;li>&lt;strong>क्वांटाइज़्ड डेटा&lt;/strong>: 32 4-बिट मान (16 बाइट्स)
यह स्थानीय आउटलायर्स के प्रभाव को कम करता है।&lt;/li>
&lt;/ul>
&lt;h3 id="62-avx2-क-सथ-डट-उतपद-क-तवरण">6.2 AVX2 के साथ डॉट उत्पाद का त्वरण
&lt;/h3>&lt;p>Windows वातावरण में नवीनतम x86 CPU के लिए बिल्ड करते समय, &lt;code>/arch:AVX2&lt;/code> जैसे कंपाइलर फ्लैग्स का उपयोग करके SIMD प्रोसेसिंग निम्नलिखित प्रवाह में की जाती है:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>लोड&lt;/strong>: मेमोरी से 4-बिट क्वांटाइज़्ड डेटा को 256-बिट AVX रजिस्टर में लोड करना।&lt;/li>
&lt;li>&lt;strong>विस्तार और अनपैक&lt;/strong>: बिट मास्क और शिफ्ट ऑपरेशंस का उपयोग करके 4-बिट मानों को Int8 या Int16 में विस्तारित करना।&lt;/li>
&lt;li>&lt;strong>डीक्वांटाइज़ेशन&lt;/strong>: फ्लोटिंग पॉइंट में बदलने के लिए स्केल फैक्टर से गुणा करना।&lt;/li>
&lt;li>&lt;strong>FMA ऑपरेशंस&lt;/strong>: एक्टिवेशन मानों और &lt;code>_mm256_fmadd_ps&lt;/code> (Fused Multiply-Add) के साथ समानांतर में मल्टीप्लाई-ऐड (multiply-add) ऑपरेशंस निष्पादित करना।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="7-kv-कश-करयनवयन-क-ववरण">7. KV कैश कार्यान्वयन का विवरण
&lt;/h2>&lt;p>ऑटो-रिग्रेसिव जनरेशन में, पिछले टोकनों के Key और Value की गणना को छोड़ने के लिए &amp;ldquo;KV कैश&amp;rdquo; एक आवश्यक विशेषता है।&lt;/p>
&lt;p>C++ में इसे लागू करते समय मुख्य बिंदु इस प्रकार हैं:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>टेंसर का पूर्व-आवंटन&lt;/strong>: KV कैश के लिए अधिकतम संदर्भ लंबाई (उदा: 2048 टोकन) के लिए एक विशाल टेंसर को इनिशियलाइज़ किया जाता है (FP16 अनुशंसित है)।&lt;/li>
&lt;li>&lt;strong>ऑफ़सेट कॉपी&lt;/strong>: जब टोकन स्थिति $N$ के लिए गणना की जाती है, तो उस चरण पर प्राप्त K और V वेक्टर्स को &lt;code>ggml_cpy&lt;/code> आदि का उपयोग करके KV कैश टेंसर की $N$-वीं पंक्ति में स्टोर किया जाता है।&lt;/li>
&lt;li>&lt;strong>अटेंशन के दौरान व्यू बनाना&lt;/strong>: अटेंशन की गणना करते समय, एक &amp;ldquo;व्यू (view)&amp;rdquo; बनाया जाता है जो केवल 0 से $N$वें टोकन भाग को इंगित करता है और उसे मैट्रिक्स गुणन में पास किया जाता है।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-bpe-टकनइजर-और-डकडग">8. BPE टोकनाइज़र और डिकोडिंग
&lt;/h2>&lt;p>इनपुट स्ट्रिंग को UTF-8 बाइट्स के अनुक्रम के रूप में माना जाता है और पूर्वनिर्धारित शब्दावली के विरुद्ध मिलान किया जाता है। C++ में, शब्दावली खोज को तेज करने के लिए &lt;strong>ट्राई ट्री (प्रिफिक्स ट्री)&lt;/strong> या प्राथमिकता कतारों (priority queues) का उपयोग करने वाले एल्गोरिदम लागू किए जाते हैं।&lt;/p>
&lt;p>LM Head से आउटपुट लॉजिट्स (logits) से, संभावितताओं को Temperature पैरामीटर का उपयोग करके स्केल किया जाता है, उम्मीदवारों को Top-K निष्कर्षण या Top-P (न्यूक्लियस सैंपलिंग) विधियों का उपयोग करके कम किया जाता है, और यादृच्छिक संख्याओं का उपयोग करके अंतिम अगला टोकन निर्धारित किया जाता है।&lt;/p>
&lt;hr>
&lt;h2 id="9-c-परजकट-सट-अप-करन-windows--powershell-वतवरण">9. C++ प्रोजेक्ट सेट अप करना (Windows / PowerShell वातावरण)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.14&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">TinyLLaMACpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">17&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Windows (MSVC) के लिए ऑप्टिमाइज़ेशन और AVX2 फ्लैग की सेटिंग
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MSVC&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">/O2&lt;/span> &lt;span class="s">/arch:AVX2&lt;/span> &lt;span class="s">/fp:fast&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">/STACK:8388608&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">else&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">add_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">-O3&lt;/span> &lt;span class="s">-march=native&lt;/span> &lt;span class="s">-ffast-math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ggml&lt;/span> &lt;span class="s">OBJECT&lt;/span> &lt;span class="s">ggml/ggml.c&lt;/span> &lt;span class="s">ggml/ggml-alloc.c&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_compile_definitions&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ggml&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">GGML_USE_AVX2&lt;/span> &lt;span class="s">GGML_USE_F16C&lt;/span> &lt;span class="s">GGML_USE_FMA&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">main&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">main&lt;/span> &lt;span class="s">ggml&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>PowerShell में बिल्ड कमांड का उदाहरण:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="n">mkdir&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd &lt;/span>&lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">..&lt;/span> &lt;span class="n">-G&lt;/span> &lt;span class="s2">&amp;#34;Visual Studio 17 2022&amp;#34;&lt;/span> &lt;span class="n">-A&lt;/span> &lt;span class="n">x64&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cmake&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-build&lt;/span> &lt;span class="p">.&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="n">-config&lt;/span> &lt;span class="n">Release&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="10-नषकरष">10. निष्कर्ष
&lt;/h2>&lt;p>C++ और ggml का उपयोग करके TinyLLaMA जैसे छोटे AI मॉडल के लिए शून्य से एक अनुमान इंजन लागू करना डीप लर्निंग के ब्लैक बॉक्स को खोलने और निम्न-स्तरीय हार्डवेयर नियंत्रण की सुंदरता सीखने का एक उत्कृष्ट अवसर है। मेमोरी मैपिंग का उपयोग करके ज़ीरो-कॉपी लोडिंग, SIMD ऑप्टिमाइज़ेशन और KV कैश के निर्माण जैसी सिस्टम प्रोग्रामिंग के सार का आनंद लेते हुए, आइए एज AI के भविष्य का मार्ग प्रशस्त करें।&lt;/p></description></item></channel></rss>