<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>C++ on kenji.blog</title><link>http://kenji.blog/hi/categories/c++/</link><description>Recent content in C++ 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/categories/c++/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><item><title>llama.cpp का उपयोग और C++ में कस्टमाइज़ेशन: एक परिचय</title><link>http://kenji.blog/hi/p/llama-cpp-cxx-customization/</link><pubDate>Fri, 11 Sep 2026 11:00:00 +0900</pubDate><guid>http://kenji.blog/hi/p/llama-cpp-cxx-customization/</guid><description>&lt;img src="http://kenji.blog/p/llama-cpp-cxx-customization/img/eyecatch.jpg" alt="Featured image of post llama.cpp का उपयोग और C++ में कस्टमाइज़ेशन: एक परिचय" />&lt;p>हाल के वर्षों में, बड़े भाषा मॉडल (Large Language Models या LLM) का विकास उल्लेखनीय रहा है, और उनके अनुप्रयोग का दायरा हर दिन बढ़ता जा रहा है। हालांकि, अरबों और दसियों अरबों मापदंडों (parameters) वाले मॉडल को स्थानीय वातावरण (local environment) में चलाने के लिए आमतौर पर विशाल VRAM वाले हाई-एंड GPU की आवश्यकता होती है। इस &amp;ldquo;हार्डवेयर बाधा&amp;rdquo; को तोड़ते हुए सामान्य PC, Mac और यहां तक कि Raspberry Pi जैसे उपकरणों पर LLM का व्यावहारिक अनुमान (inference) संभव बनाने वाला टूल &lt;strong>llama.cpp&lt;/strong> है।&lt;/p>
&lt;p>इस लेख में, हम न केवल कमांड लाइन टूल के उपयोग पर चर्चा करेंगे, बल्कि इसकी मूलभूत तकनीक &lt;code>ggml&lt;/code> के आर्किटेक्चर, ट्रांसफॉर्मर और क्वांटाइज़ेशन (Quantization) की गणितीय पृष्ठभूमि, और C++ API का उपयोग करके अपने स्वयं के एप्लिकेशन में LLM को शामिल करने और कस्टमाइज़ करने के तरीकों के बारे में इंजीनियरों के लिए अत्यंत विस्तृत व्याख्या करेंगे।&lt;/p>
&lt;hr>
&lt;h2 id="1-llamacpp-और-ggml-क-अवलकन">1. llama.cpp और ggml का अवलोकन
&lt;/h2>&lt;p>&lt;code>llama.cpp&lt;/code> Georgi Gerganov द्वारा विकसित C/C++ में लिखा गया एक हल्का LLM अनुमान इंजन (inference engine) है। यह मूल रूप से Meta के LLaMA मॉडल को Apple Silicon (M1/M2 Mac) पर उच्च गति से चलाने के उद्देश्य से बनाया गया था, लेकिन अब यह विभिन्न आर्किटेक्चर और मॉडलों का समर्थन करता है।&lt;/p>
&lt;p>इसकी सबसे बड़ी विशेषता यह है कि यह &lt;strong>बाहरी निर्भरता के बिना एक शुद्ध C/C++ कार्यान्वयन (implementation)&lt;/strong> है। चूंकि इसे Python या PyTorch जैसे विशाल इकोसिस्टम की आवश्यकता नहीं है और इसे एकल निष्पादन योग्य फ़ाइल (single executable file) के रूप में संकलित (compile) किया जा सकता है, इसलिए इसे डिप्लॉय करना बहुत आसान है।&lt;/p>
&lt;p>इस &lt;code>llama.cpp&lt;/code> का हृदय टेंसर गणितीय लाइब्रेरी &lt;strong>ggml&lt;/strong> है। ggml को मशीन लर्निंग में मैट्रिक्स संचालन को CPU (और कुछ GPU) पर अत्यधिक अनुकूलित (optimize) करने के लिए शून्य से डिज़ाइन किया गया है।&lt;/p>
&lt;h3 id="11-llamacpp-इतन-तज-कय-ह">1.1 llama.cpp इतना तेज़ क्यों है?
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>मेमोरी मैपिंग (mmap) का उपयोग&lt;/strong>: मॉडल के वज़न (weights) को मेमोरी में लोड करते समय, OS के &lt;code>mmap&lt;/code> का उपयोग करके RAM में पूरा लोड करने से बचा जाता है, जिससे तेज़ स्टार्टअप और कम मेमोरी की खपत प्राप्त होती है।&lt;/li>
&lt;li>&lt;strong>SIMD निर्देशों का संपूर्ण अनुकूलन (Optimization)&lt;/strong>: AVX2, AVX-512, ARM NEON, Apple AMX जैसे CPU-विशिष्ट निर्देश सेट का लाभ उठाकर मैट्रिक्स गुणा को अत्यधिक तेज़ किया गया है।&lt;/li>
&lt;li>&lt;strong>क्वांटाइज़ेशन (Quantization)&lt;/strong>: 16-बिट फ़्लोटिंग-पॉइंट नंबर (FP16) के वज़न को 4-बिट, 5-बिट, और 8-बिट पूर्णांक (integers) में संकुचित करके मेमोरी बैंडविड्थ की बाधा को समाप्त किया गया है (विवरण नीचे दिया गया है)।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="2-गणतय-पषठभम-टरसफरमर-transformer-और-कवटइजशन-quantization">2. गणितीय पृष्ठभूमि: ट्रांसफॉर्मर (Transformer) और क्वांटाइज़ेशन (Quantization)
&lt;/h2>&lt;p>llama.cpp को गहराई से समझने के लिए, यह जानना आवश्यक है कि यह किन गणितीय सूत्रों (formulas) की गणना कर रहा है और यह गणनाओं का अनुमान कैसे लगाता है।&lt;/p>
&lt;h3 id="21-टरसफरमर-अनमन-परकरय-inference-process">2.1 ट्रांसफॉर्मर अनुमान प्रक्रिया (Inference Process)
&lt;/h3>&lt;p>LLaMA जैसे मॉडल ऑटो-रिग्रेसिव (Auto-regressive) ट्रांसफॉर्मर डिकोडर आर्किटेक्चर को अपनाते हैं। टेक्स्ट जनरेशन का मूल &lt;strong>Self-Attention&lt;/strong> तंत्र है।&lt;/p>
&lt;p>इनपुट के रूप में छिपी हुई स्थिति (hidden state) के मैट्रिक्स $X \in \mathbb{R}^{N \times d}$ के लिए, क्वेरी $Q$, कुंजी $K$, और वैल्यू $V$ की गणना वज़न मैट्रिक्स (weight matrix) के गुणन से की जाती है।&lt;/p>
$$
Q = X W_Q, \quad K = X W_K, \quad V = X W_V
$$
&lt;p>यहाँ, Attention का आउटपुट इस प्रकार परिभाषित किया गया है:&lt;/p>
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
&lt;p>llama.cpp के अनुमान लूप (inference loop) में, अड़चन (bottleneck) यह विशाल मैट्रिक्स $W_Q, W_K, W_V$ और फीड-फॉरवर्ड नेटवर्क (FFN) के वज़न मैट्रिक्स और वेक्टर $X$ का गुणन है (क्योंकि जनरेशन चरण में प्रति टोकन संसाधित किया जाता है, $N=1$), यानी &lt;strong>GEMV (General Matrix-Vector Multiplication)&lt;/strong>।&lt;/p>
&lt;h3 id="22-कवटइजशन-quantization-क-गणतय-आधर">2.2 क्वांटाइज़ेशन (Quantization) का गणितीय आधार
&lt;/h3>&lt;p>मेमोरी एक्सेस बैंडविड्थ अनुमान (inference) में एक बाधा बन जाती है, इसके लिए वज़न मापदंडों (weight parameters) को छोटे बिट नंबरों में दर्शाने वाला क्वांटाइज़ेशन अनिवार्य है। हम llama.cpp में व्यापक रूप से उपयोग किए जाने वाले ब्लॉक-आधारित क्वांटाइज़ेशन (उदाहरण के लिए &lt;code>Q4_K&lt;/code> या &lt;code>Q4_0&lt;/code>) के मूल सिद्धांत की व्याख्या करेंगे।&lt;/p>
&lt;p>मान लीजिए कि FP16 वज़न मैट्रिक्स $W$ का एक हिस्सा ब्लॉक $w = [w_1, w_2, \dots, w_B]$ है, जिसकी लंबाई $B$ (आमतौर पर 32 या 64) है। यह ब्लॉक 4-बिट पूर्णांक $q_i \in [-8, 7]$ और एकल स्केलिंग फैक्टर $\Delta$ (FP16 या FP32) के अनुमानित रूप में होता है।&lt;/p>
$$
w_i \approx \Delta \times q_i
$$
&lt;p>$\Delta$ का निर्धारण ब्लॉक में अधिकतम पूर्ण मान (absolute value) के आधार पर किया जाता है।&lt;/p>
$$
\Delta = \frac{\max_i |w_i|}{7}
$$
&lt;p>क्वांटाइज़्ड वज़न का उपयोग करके डॉट गुणनफल (dot product) $y = w \cdot x$ की गणना करते समय, इनपुट वेक्टर $x$ को भी उसी तरह क्वांटाइज़ करके $x_i \approx \Delta_x \times q_{x, i}$ माना जाता है:&lt;/p>
$$
y = \sum_{i=1}^{B} w_i x_i \approx \Delta \Delta_x \sum_{i=1}^{B} q_i q_{x, i}
$$
&lt;p>यह $\sum q_i q_{x, i}$ भाग &lt;strong>शुद्ध पूर्णांक संचालन (pure integer arithmetic)&lt;/strong> बन जाता है, जिसे SIMD निर्देशों का उपयोग करके बहुत तेज़ी से समानांतर (parallel) रूप में गणना की जा सकती है। यही वह गणितीय रहस्य है जो llama.cpp को CPU पर आश्चर्यजनक गति प्रदान करता है।&lt;/p>
&lt;hr>
&lt;h2 id="3-आरकटकचर-और-अनमन-परवह-inference-flow">3. आर्किटेक्चर और अनुमान प्रवाह (Inference Flow)
&lt;/h2>&lt;p>llama.cpp के आंतरिक कामकाज को समझने के लिए, नीचे दिया गया Mermaid आरेख (diagram) पूरे सिस्टम के आर्किटेक्चर और डेटा प्रवाह को दर्शाता है।&lt;/p>
&lt;div class="mermaid">graph TD
A["उपयोगकर्ता इनपुट (स्ट्रिंग)"] --> B["llama.cpp टोकनाइज़र"]
B --> C["टोकन IDs (int32 ऐरे)"]
C --> D["संदर्भ बफ़र (KV कैश)"]
D --> E["ggml गणना ग्राफ"]
E --> F["ट्रांसफॉर्मर लेयर्स"]
subgraph "ggml इंजन"
F --> G["सेल्फ-अटेंशन (RoPE)"]
G --> H["फीड फॉरवर्ड नेटवर्क"]
H --> F
end
F --> I["लॉजिट्स (शब्दावली का आकार)"]
I --> J["सैम्पलर (टेम्परेचर, Top-K, Top-P)"]
J --> K["चयनित टोकन ID"]
K --> L["llama.cpp डिटोकनाइज़र"]
L --> M["आउटपुट स्ट्रिंग"]
K -. "ऑटो-रिग्रेसिव लूप" .-> D&lt;/div>
&lt;p>टेक्स्ट जनरेशन एक ऑटो-रिग्रेसिव लूप है जहाँ प्रत्येक नया टोकन आउटपुट होने पर इसे KV Cache में अगले इनपुट के रूप में जोड़ा जाता है और फिर से गणना ग्राफ से गुज़रता है।&lt;/p>
&lt;hr>
&lt;h2 id="4-परयवरण-सटअप-और-बलड-वध">4. पर्यावरण सेटअप और बिल्ड विधि
&lt;/h2>&lt;p>llama.cpp को C++ प्रोजेक्ट में शामिल करने से पहले, आइए सबसे पहले सोर्स कोड को बिल्ड करें।&lt;/p>
&lt;h3 id="41-रपजटर-क-कलनग">4.1 रिपॉजिटरी की क्लोनिंग
&lt;/h3>&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/ggerganov/llama.cpp.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> llama.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="42-cmake-क-उपयग-करक-बलड-करन">4.2 CMake का उपयोग करके बिल्ड करना
&lt;/h3>&lt;p>जब C++ प्रोजेक्ट के रूप में इसे अन्य ऐप्स में शामिल किया जाता है, तो CMake का उपयोग करना सबसे मानक है। प्लेटफ़ॉर्म-विशिष्ट एक्सेलेरेटर (बैकएंड) को सक्षम करके, गणनाओं को तेज़ किया जा सकता है।&lt;/p>
&lt;p>&lt;strong>केवल CPU (बुनियादी बिल्ड):&lt;/strong>&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>NVIDIA GPU (CUDA) का उपयोग करते समय:&lt;/strong>&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake .. -DGGML_CUDA&lt;span class="o">=&lt;/span>ON
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Apple Silicon (Metal) का उपयोग करते समय:&lt;/strong>&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;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir build &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake .. -DGGML_METAL&lt;span class="o">=&lt;/span>ON
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build . --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>यदि बिल्ड सफल होता है, तो &lt;code>build/bin/&lt;/code> निर्देशिका में &lt;code>llama-cli&lt;/code> जैसी निष्पादन योग्य फ़ाइलें और बाद में वर्णित C++ API के साथ लिंक करने के लिए &lt;code>llama&lt;/code> लाइब्रेरी (और &lt;code>ggml&lt;/code> लाइब्रेरी) तैयार हो जाएँगी।&lt;/p>
&lt;hr>
&lt;h2 id="5-c-म-कसटमइजशन-परचय-llamacpp-api-क-उपयग">5. C++ में कस्टमाइज़ेशन परिचय: llama.cpp API का उपयोग
&lt;/h2>&lt;p>यहाँ से हम इस लेख के मुख्य विषय पर चर्चा करेंगे: C++ कोड के माध्यम से llama.cpp का नियंत्रण।
केवल कमांड लाइन टूल का उपयोग करने के अलावा, अपने स्वयं के एप्लिकेशन (जैसे गेम इंजन, डेस्कटॉप ऐप, एंबेडेड सिस्टम, आदि) में LLM को शामिल करने के लिए C++ API को सीधे कॉल करना आवश्यक है।&lt;/p>
&lt;p>llama.cpp मुख्य रूप से &lt;code>llama.h&lt;/code> नामक हेडर फ़ाइल के माध्यम से C भाषा इंटरफ़ेस प्रदान करता है। C++ से कॉल करते समय भी इसी इंटरफ़ेस का उपयोग किया जाता है।&lt;/p>
&lt;h3 id="51-नयनतम-आवशयक-इनकलड-और-सटगस">5.1 न्यूनतम आवश्यक इन्क्लूड और सेटिंग्स
&lt;/h3>&lt;p>अपने प्रोजेक्ट में llama.cpp का उपयोग करते समय, निम्नलिखित शामिल करें:&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;/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;#34;llama.h&amp;#34;&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">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&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;string&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">&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="cp">#define LLAMA_ASSERT(x) \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> do { \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> if (!(x)) { \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> std::cerr &amp;lt;&amp;lt; &amp;#34;Assertion failed: &amp;#34; &amp;lt;&amp;lt; #x &amp;lt;&amp;lt; std::endl; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp"> std::terminate(); \
&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="cp"> } while (0)
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-मडल-लड-करन-और-सदरभ-context-इनशयलइज-करन">5.2 मॉडल लोड करना और संदर्भ (Context) इनिशियलाइज़ करना
&lt;/h3>&lt;p>सबसे पहले, &lt;code>.gguf&lt;/code> प्रारूप की मॉडल फ़ाइल लोड करें और अनुमान के लिए संदर्भ (मेमोरी स्पेस और KV कैश) सुरक्षित करें।&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;/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="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">**&lt;/span> &lt;span class="n">argv&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">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">argc&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">2&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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Usage: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">argv&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">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; &amp;lt;model.gguf&amp;gt;&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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="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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">model_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">argv&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. बैकएंड का इनिशियलाइज़ेशन (CPU/GPU आदि का पर्यावरण सेटअप)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_backend_init&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">// 2. मॉडल पैरामीटर्स के डिफ़ॉल्ट सेटिंग्स प्राप्त करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_model_params&lt;/span> &lt;span class="n">model_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_model_default_params&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_gpu_layers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// GPU में ऑफ़लोड करने के लिए लेयर्स की संख्या
&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">// 3. मॉडल को लोड करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_model&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_load_model_from_file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model_path&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">model_params&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">model&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to load model&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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="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="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">// 4. संदर्भ पैरामीटर सेट करना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_context_params&lt;/span> &lt;span class="n">ctx_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_context_default_params&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ctx_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2048&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">ctx_params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_threads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// अनुमान (inference) के लिए उपयोग किए जाने वाले CPU थ्रेड्स की संख्या
&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">// 5. संदर्भ (Context) बनाना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_context&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_new_context_with_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctx_params&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">ctx&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="k">nullptr&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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to create context&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&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="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="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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Model and context loaded successfully!&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-परमपट-क-टकनइजशन-tokenization">5.3 प्रॉम्प्ट का टोकनाइज़ेशन (Tokenization)
&lt;/h3>&lt;p>LLM टेक्स्ट को सीधे नहीं समझता, बल्कि इसे इंटीजर ID (टोकन) के अनुक्रम के रूप में संसाधित करता है। इनपुट स्ट्रिंग को टोकन में बदलना आवश्यक है।&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;/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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Q: जापान की राजधानी कहाँ है?&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">A:&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">llama_token&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">4&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">// क्या शुरुआत में विशेष टोकन (BOS: Begin of Sequence आदि) जोड़ना है
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">add_special&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// स्ट्रिंग को टोकन ID की ऐरे में बदलना
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">n_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_tokenize&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">c_str&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">prompt&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&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="n">tokens_list&lt;/span>&lt;span class="p">.&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">add_special&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">false&lt;/span> &lt;span class="c1">// parse_special
&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">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">&amp;lt;&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">// यदि बफ़र पर्याप्त नहीं है तो पुनः आवंटन (reallocation) करके पुनः प्रयास करना आवश्यक है (सरलता के लिए यहाँ छोड़ा गया है)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to tokenize prompt&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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="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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_tokens&lt;/span>&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="54-अनमन-लप-और-सपलग">5.4 अनुमान लूप और सैंपलिंग
&lt;/h3>&lt;p>टोकन को मॉडल में इनपुट करें, अगले टोकन का संभाव्यता वितरण (Probability Distribution या Logits) प्राप्त करें, और वहां से सैंपलिंग करके अगला टोकन निर्धारित करने वाला लूप बनाएँ।&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;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&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">// उत्पन्न किए जाने वाले अधिकतम टोकनों की संख्या
&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">int&lt;/span> &lt;span class="n">max_gen_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">100&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="n">llama_batch&lt;/span> &lt;span class="n">batch&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_batch_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">512&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&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>&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">size_t&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">tokens_list&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">i&lt;/span>&lt;span class="o">++&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">llama_batch_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tokens_list&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">},&lt;/span> &lt;span class="nb">false&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="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">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">logits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&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">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;llama_decode() failed&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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="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="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">n_cur&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&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">int&lt;/span> &lt;span class="n">n_decode&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">Output: &amp;#34;&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">// सैम्पलर संदर्भ का इनिशियलाइज़ेशन (Temperature, Top-K, Top-P आदि की सेटिंग्स)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_sampler&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">smpl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_sampler_chain_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">llama_sampler_chain_default_params&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_top_k&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_top_p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.9f&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="n">llama_sampler_chain_add_temp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.7f&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_sampler_chain_add_dist&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1234&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="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n_decode&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">max_gen_tokens&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">// 1. सैंपलिंग: वर्तमान संदर्भ के आधार पर अगले टोकन की भविष्यवाणी
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_token&lt;/span> &lt;span class="n">new_token_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_sampler_sample&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. यदि टोकन EOS (End of Sequence) है तो लूप समाप्त करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_token_is_eog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&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">break&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">// 3. टोकन को स्ट्रिंग (टेक्स्ट) में डिकोड करें और प्रदर्शित करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">buf&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">128&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_chars&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_token_to_piece&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">buf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">false&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">n_chars&lt;/span> &lt;span class="o">&amp;gt;&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buf&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_chars&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">flush&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">// 4. नए उत्पन्न टोकन को अगले बैच के रूप में तैयार करें
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">llama_batch_clear&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_batch_add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">new_token_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_cur&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">},&lt;/span> &lt;span class="nb">true&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">// 5. मॉडल का मूल्यांकन (KV कैश अपडेट करें, और अगले की भविष्यवाणी करें)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">llama_decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cerr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Failed to evaluate&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&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">n_cur&lt;/span> &lt;span class="o">+=&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="n">n_decode&lt;/span> &lt;span class="o">+=&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="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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&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="n">llama_sampler_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">smpl&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_batch_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">batch&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_free_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">llama_backend_free&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">return&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="6-उननत-कसटमइजशन-उदहरण-c-क-मधयम-स-लजटस-हरफर-और-पनलट-नयतरण">6. उन्नत कस्टमाइज़ेशन उदाहरण: C++ के माध्यम से लॉजिट्स हेरफेर और पेनाल्टी नियंत्रण
&lt;/h3>&lt;p>सिर्फ सरल टेक्स्ट जनरेशन तक सीमित न रहकर, जब किसी विशेष प्रारूप (जैसे केवल JSON) में आउटपुट को बाध्य करना हो, या विशिष्ट प्रतिबंधित शब्दों के आउटपुट को रोकना हो, तो सैंपलिंग से पहले के &lt;strong>लॉजिट्स (Logits)&lt;/strong> को सीधे C++ की ओर से नियंत्रित किया जाता है।&lt;/p>
&lt;p>आप प्रत्येक टोकन के आउटपुट होने से ठीक पहले रॉ स्कोर की ऐरे (संभाव्यता में परिवर्तित होने से पहले का मान) प्राप्त कर सकते हैं।&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;/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">// अनुमान के तुरंत बाद, और सैंपलिंग से पहले कच्चे (raw) लॉजिट ऐरे को प्राप्त करना
&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="o">*&lt;/span> &lt;span class="n">logits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_get_logits_ith&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">batch&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">n_tokens&lt;/span> &lt;span class="o">-&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_vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llama_n_vocab&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&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">// प्रतिबंधित टोकन ID सूची (उदाहरण के लिए 1234, 5678)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">llama_token&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">forbidden_tokens&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">1234&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5678&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">// निषिद्ध टोकन की उपस्थिति की संभावना को 0 (Logit को माइनस इन्फिनिटी) पर सेट करना
&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">llama_token&lt;/span> &lt;span class="nl">bad_tok&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">forbidden_tokens&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">logits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">bad_tok&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">INFINITY&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>इस तरह, C++ API को सीधे हैंडल करके, &lt;strong>&amp;ldquo;अनुमान चक्र के प्रत्येक माइक्रोसेकंड-स्तर पर हस्तक्षेप&amp;rdquo;&lt;/strong> संभव हो जाता है, जो LangChain या Python के माध्यम से प्राप्त करना मुश्किल है या जिसमें अधिक ओवरहेड होता है।&lt;/p>
&lt;hr>
&lt;h2 id="7-परफरमस-टयनग-क-रहसय">7. परफॉर्मेंस ट्यूनिंग के रहस्य
&lt;/h2>&lt;p>C++ में कार्यान्वयन समाप्त करने के बाद, वास्तविक संचालन (production) के लिए गति को अधिकतम सीमा तक बढ़ाने के लिए यहां कुछ जांच बिंदु (checkpoints) दिए गए हैं।&lt;/p>
&lt;ol>
&lt;li>&lt;strong>बैच प्रोसेसिंग ऑप्टिमाइज़ेशन:&lt;/strong> कई उपयोगकर्ताओं के अनुरोधों को एक साथ संसाधित करते समय, &lt;code>llama_batch&lt;/code> में कई अनुक्रमों को शामिल करें और एक बार में &lt;code>llama_decode&lt;/code> को कॉल करें (Continuous Batching)। इससे मेमोरी एक्सेस साझा চরম हो सकता है और थ्रूपुट में काफी सुधार हो सकता है।&lt;/li>
&lt;li>&lt;strong>फ्लैश अटेंशन (Flash Attention) सक्षम करना:&lt;/strong>
संदर्भ पैरामीटर में &lt;code>ctx_params.flash_attn = true;&lt;/code> सेट करके, मेमोरी उपयोग को कम करते हुए अटेंशन गणना को तेज़ किया जा सकता है। लंबे संदर्भ (हजारों टोकन) से निपटने के दौरान यह एक आवश्यक सेटिंग है।&lt;/li>
&lt;li>&lt;strong>NUMA सपोर्ट:&lt;/strong>
मल्टी-सॉकेट सर्वर वातावरण में &lt;code>llama_backend_init()&lt;/code> से पहले NUMA सेटिंग्स को उचित रूप से कॉन्फ़िगर करके मेमोरी एक्सेस लेटेंसी को कम किया जा सकता है।&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-नषकरष">8. निष्कर्ष
&lt;/h2>&lt;p>इस लेख में, हमने &lt;code>llama.cpp&lt;/code> की गणितीय पृष्ठभूमि से शुरुआत की, इसके आर्किटेक्चर की व्याख्या की, और C++ API का पूरा उपयोग करके कस्टम अनुमान इंजन (custom inference engine) बनाने के तरीके के बारे में विस्तार से बताया।&lt;/p>
&lt;p>हालांकि Python इकोसिस्टम प्रोटोटाइपिंग के लिए बहुत सुविधाजनक है, लेकिन एज डिवाइस डिप्लॉयमेंट, गेम्स में एकीकरण (integration), और उत्पादन (production) वातावरण जहां रियल-टाइम प्रोसेसिंग की आवश्यकता होती है, वहां C/C++ आधारित &lt;code>llama.cpp&lt;/code> का प्रत्यक्ष नियंत्रण अपना अत्यधिक प्रभाव दिखाता है।&lt;/p>
&lt;p>आप भी कृपया स्वयं C++ कोड लिखने का प्रयास करें, और स्थानीय वातावरण (local environment) में LLM को स्वतंत्र रूप से हेरफेर करने के आनंद का अनुभव करें।&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>संदर्भ लिंक (Reference Links)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener"
>llama.cpp Official Repository&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/ggml" target="_blank" rel="noopener"
>ggml - Tensor Library&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
>Attention Is All You Need (Vaswani et al., 2017)&lt;/a>&lt;/li>
&lt;/ul>
&lt;/blockquote></description></item></channel></rss>