<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Development on kenji.blog</title><link>http://kenji.blog/ar/tags/development/</link><description>Recent content in Development on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 14:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/tags/development/index.xml" rel="self" type="application/rss+xml"/><item><title>دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++</title><link>http://kenji.blog/ar/p/cpp-small-ai-model-tinyllama-dev-guide/</link><pubDate>Fri, 11 Sep 2026 14:00:00 +0900</pubDate><guid>http://kenji.blog/ar/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 دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++" />&lt;h1 id="دليل-تطوير-نماذج-الذكاء-الاصطناعي-الصغيرة-مثل-tinyllama-باستخدام-c">دليل تطوير نماذج الذكاء الاصطناعي الصغيرة (مثل TinyLLaMA) باستخدام C++
&lt;/h1>&lt;p>في الآونة الأخيرة، ازداد الاهتمام بشكل سريع بتشغيل النماذج اللغوية الكبيرة (LLM) في البيئات المحلية. على وجه الخصوص، يمكن للنماذج الصغيرة مثل TinyLLaMA (بحجم 1.1 مليار معلمة) إجراء الاستدلال بسرعة عملية حتى على الأجهزة الطرفية ذات الموارد المحدودة أو أجهزة الكمبيوتر المحمولة العادية (بما في ذلك بيئات Windows). بينما يعتبر التطوير باستخدام Python و PyTorch هو السائد، إلا أنه عند السعي لتحقيق الأداء الأمثل وكفاءة الذاكرة، يصبح الجمع بين C++ ومكتبة التنسور &amp;ldquo;ggml&amp;rdquo; المعتمدة على لغة C هو المعيار الفعلي.&lt;/p>
&lt;p>في هذا المقال، سنشرح خطوات تطوير مفصلة للغاية لبناء محرك استدلال من الصفر (أو فهم البنية الداخلية لـ llama.cpp الحالية بعمق) لتحميل TinyLLaMA وتوليد النصوص باستخدام C++.&lt;/p>
&lt;hr>
&lt;h2 id="1-لماذا-c-و-ggml">1. لماذا C++ و ggml؟
&lt;/h2>&lt;p>في مرحلة تدريب الذكاء الاصطناعي، تتفوق Python بفضل مرونتها ونظامها البيئي الغني. ومع ذلك، في مرحلة النشر أو &amp;ldquo;الاستدلال (Inference)&amp;quot;، تصبح C++ خياراً قوياً للأسباب التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>تقليل النفقات العامة (Overhead)&lt;/strong>: يمكن القضاء تماماً على قفل المترجم العالمي (GIL) والنفقات العامة لوقت التشغيل في Python.&lt;/li>
&lt;li>&lt;strong>كفاءة الذاكرة وتخصيص الساحة (Arena Allocation)&lt;/strong>: نظراً لإمكانية التحكم اليدوي في تخصيص وتحرير الذاكرة، يمكن منع الزيادات غير المتوقعة الناتجة عن جمع القمامة (Garbage Collection).&lt;/li>
&lt;li>&lt;strong>الوصول المباشر إلى الأجهزة&lt;/strong>: استدعاء الوظائف المضمنة لـ SIMD (Intrinsics) مباشرة مثل AVX-512 و AVX2 و ARM NEON، مما يتيح استغلال قدرات الحوسبة لوحدة المعالجة المركزية إلى أقصى حد.&lt;/li>
&lt;li>&lt;strong>التخلص من التبعيات&lt;/strong>: ggml هي مكتبة C/C++ خالية من التبعيات (Zero dependencies)، ويمكن بناؤها بسهولة حتى في بيئة MSVC على Windows بمجرد توفر مترجم.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="2-النظرة-العامة-على-البنية">2. النظرة العامة على البنية
&lt;/h2>&lt;p>يوضح مخطط Mermaid التالي سير العمل في خط أنابيب الاستدلال بالكامل. إنها سلسلة من العمليات تبدأ من النص المدخل من قبل المستخدم وصولاً إلى توليد الرمز (Token) التالي.&lt;/p>
&lt;div class="mermaid">graph TD
A["نص إدخال المستخدم"] --> B["BPE Tokenizer"]
B --> C["مصفوفة معرفات الرموز (Token IDs)"]
C --> D["البحث في طبقة التضمين (Embedding Layer Lookup)"]
D --> E["كتل المحول (Transformer Blocks)"]
E --> F["RMSNorm"]
F --> G["طبقة رأس LM (LM Head Layer)"]
G --> H["مصفوفة اللوغاريتمات (Logits)"]
H --> I["وحدة أخذ العينات (Sampler)"]
I --> J["معرف الرمز التالي (Next Token ID)"]
J --> K["Detokenizer"]
K --> L["قطعة النص المخرجة"]
J -.-> |"إضافة إلى السياق"| C&lt;/div>
&lt;p>نظراً لأنه نموذج انحدار ذاتي (Autoregressive)، تتم إضافة الرموز المخرجة مرة أخرى إلى السياق، وتدور كمدخلات لتوقع الرمز التالي (الجزء المتقطع في المخطط).&lt;/p>
&lt;hr>
&lt;h2 id="3-تنسيق-النموذج-وتخطيط-الذاكرة-mmap">3. تنسيق النموذج وتخطيط الذاكرة (mmap)
&lt;/h2>&lt;p>تعد القراءة/الكتابة على القرص واستهلاك الذاكرة العائق الأكبر عند التعامل مع أوزان الشبكات العصبية الضخمة. في تطبيقات C++، يتم حل ذلك باستخدام &lt;strong>تخطيط الذاكرة (Memory Mapping - 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>: يتم تحميل البيانات مباشرة من القرص إلى ذاكرة التخزين المؤقت للصفحات في النواة (Kernel)، ولا يحدث نسخ إضافي إلى مساحة المستخدم.&lt;/li>
&lt;li>&lt;strong>التحميل عند الطلب (Page Fault)&lt;/strong>: في اللحظة التي تصل فيها وحدة المعالجة المركزية فعلياً إلى عنوان الذاكرة ذلك، يحدث خطأ في الصفحة (Page Fault)، ويتم تحميل الكتلة المطلوبة فقط (عادة 4 كيلوبايت) في الذاكرة الفعلية.&lt;/li>
&lt;/ul>
&lt;p>في بيئة Windows، بدلاً من &lt;code>mmap&lt;/code> الخاصة بـ POSIX، يتم استخدام واجهات برمجة تطبيقات Win32 &lt;code>CreateFileMapping&lt;/code> و &lt;code>MapViewOfFile&lt;/code>.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant OS["نظام التشغيل Windows"]
participant RAM["الذاكرة الفعلية (Physical Memory)"]
participant App["تطبيق C++"]
App->>OS: "CreateFileMapping / MapViewOfFile"
OS-->>App: "مؤشر عنوان الذاكرة الافتراضية"
App->>App: "قراءة بيانات التنسور عند المؤشر"
OS->>RAM: "Page Fault / تحميل الصفحة من القرص"
RAM-->>App: "البيانات جاهزة لحسابات SIMD"&lt;/div>
&lt;h3 id="32-البنية-الثنائية-لتنسيق-gguf">3.2 البنية الثنائية لتنسيق GGUF
&lt;/h3>&lt;p>يعد &lt;strong>GGUF (GPT-Generated Unified Format)&lt;/strong>، المحول من تنسيقات مثل &lt;code>.safetensors&lt;/code> الخاصة بـ Hugging Face، التنسيق النهائي للاستدلال. يحتوي على المخطط الثنائي الصارم التالي:&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>عدد التنسورات وعدد البيانات الوصفية (Tensor &amp;amp; Metadata Count)&lt;/strong>: عدد التنسورات وأزواج المفتاح-القيمة للبيانات الوصفية.&lt;/li>
&lt;li>&lt;strong>البيانات الوصفية (Metadata)&lt;/strong>: مفاتيح ببادئات طول السلسلة وقيم محددة النوع.&lt;/li>
&lt;li>&lt;strong>معلومات التنسور (Tensor Info)&lt;/strong>: اسم كل تنسور، عدد الأبعاد، نوع البيانات (FP16، Q4_K، إلخ)، وموقع الإزاحة داخل الملف.&lt;/li>
&lt;li>&lt;strong>الحشو (Padding)&lt;/strong>: حشوات مدرجة لمحاذاة بيانات التنسور مع حدود معينة (عادة 32 بايت أو 64 بايت). هذا ضروري للوصول السريع للذاكرة في تعليمات SIMD (وخاصة AVX).&lt;/li>
&lt;li>&lt;strong>بيانات التنسور (Tensor Data)&lt;/strong>: مصفوفة بيانات الأوزان الفعلية المحاذاة.&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">4.1 التقييس الجذري لمتوسط المربعات (RMSNorm)
&lt;/h3>&lt;p>يقلل التكلفة الحسابية عن طريق حذف مركزة المتوسط من LayerNorm وتنفيذ قياس التباين فقط.&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++، نقوم أولاً بحساب مجموع مربعات المصفوفة بسرعة باستخدام &lt;code>_mm256_fmadd_ps&lt;/code> في AVX2، وتحسينه عن طريق ضربه بالجذر التربيعي العكسي (مثل تعليمة &lt;code>_mm256_rsqrt_ps&lt;/code>).&lt;/p>
&lt;h3 id="42-التضمين-الموضعي-الدوار-rope">4.2 التضمين الموضعي الدوار (RoPE)
&lt;/h3>&lt;p>هي تقنية لتطبيق معلومات موقع الرمز كدوران (Rotate) في مساحة التنسور. يمكن اعتبارها دوراناً على مستوى الأعداد المركبة، ويتم تطبيق الدوران التالي على الأزواج البعدية المتجاورة $(x_1, x_2)$ للمتجه $x$:&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>في الانتباه متعدد الرؤوس (MHA) العادي، يوجد نفس عدد الرؤوس لكل من Query و Key و Value. ومع ذلك، لتقليل استهلاك عرض النطاق الترددي للذاكرة وذاكرة التخزين المؤقت KV بشكل كبير، يعتمد TinyLLaMA &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 واحد. في تطبيق C++، قبل إجراء ضرب المصفوفات &lt;code>ggml_mul_mat&lt;/code>، من الضروري إجراء عملية بث (Broadcast) لتنسورات KV لتتناسب مع عدد Query.&lt;/p>
&lt;h3 id="44-دالة-التنشيط-swiglu">4.4 دالة التنشيط SwiGLU
&lt;/h3>&lt;p>في طبقة الشبكة المغذية للأمام (FFN)، يتم استخدام SwiGLU بدلاً من GELU.&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;quot;، حيث تقوم ببناء رسم بياني حسابي ثابت للاستدلال ثم تقييمه (evaluate) لاحقاً.&lt;/p>
&lt;h3 id="51-ggml_context-ومخصص-الساحة-arena-allocator">5.1 ggml_context ومخصص الساحة (Arena Allocator)
&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> وغيره، يزداد مؤشر هذه المنطقة. عند اكتمال خطوة استدلال واحدة، يتم فقط إعادة تعيين مؤشر التخصيص إلى الموضع الأولي، وبذلك يكتمل تخصيص الذاكرة لخطوة الاستدلال التالية على الفور.&lt;/p>
&lt;h3 id="52-مثال-عملي-لبناء-الرسم-البياني">5.2 مثال عملي لبناء الرسم البياني
&lt;/h3>&lt;p>في كل خطوة استدلال، يتم تجميع الرسم البياني الحسابي التالي في الذاكرة.&lt;/p>
&lt;div class="mermaid">graph TD
A["معرف رمز الإدخال (Tokens Input ID)"] --> B["البحث عن التضمين (Embed Lookup)"]
B --> C["ggml_rms_norm"]
C --> D["إسقاطات Q / K / V"]
D --> E["ggml_rope Positional"]
E --> F["حفظ في KV Cache"]
E --> G["تحميل من KV Cache"]
G --> H["الانتباه الذاتي (Self Attention)"]
H --> I["المقياس و Softmax"]
I --> J["مخرجات الانتباه (Attention Output)"]
J --> K["الإسقاط الخارجي (Out Projection)"]
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.2 جيجابايت من الذاكرة، ولكن باستخدام تكميم 4-بت (مثل Q4_K) يمكن ضغطه بشكل كبير إلى حوالي 600 ميجابايت.&lt;/p>
&lt;h3 id="61-بنية-التكميم-الكتلي-block-quantization">6.1 بنية التكميم الكتلي (Block Quantization)
&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>عامل المقياس (Scale Factor)&lt;/strong>: قيمة واحدة 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>عند البناء لأحدث وحدات المعالجة المركزية x86 في بيئة Windows، مع الاستفادة من علامات المترجم مثل &lt;code>/arch:AVX2&lt;/code>، تتم معالجة SIMD عبر التدفق التالي:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>التحميل (Load)&lt;/strong>: تحميل بيانات التكميم 4-بت من الذاكرة إلى سجلات AVX بحجم 256 بت.&lt;/li>
&lt;li>&lt;strong>التوسيع وفك الحزم (Unpack)&lt;/strong>: استخدام أقنعة البت (Bitmasks) وعمليات الإزاحة لتوسيع قيم 4-بت إلى Int8 أو Int16.&lt;/li>
&lt;li>&lt;strong>إلغاء التكميم (Dequantize)&lt;/strong>: الضرب في عامل المقياس للتحويل إلى فاصلة عائمة.&lt;/li>
&lt;li>&lt;strong>عمليات FMA&lt;/strong>: تنفيذ عمليات الضرب والجمع بالتوازي على قيم التنشيط باستخدام &lt;code>_mm256_fmadd_ps&lt;/code> (Fused Multiply-Add).&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="7-تفاصيل-تنفيذ-ذاكرة-التخزين-المؤقت-kv-kv-cache">7. تفاصيل تنفيذ ذاكرة التخزين المؤقت KV (KV Cache)
&lt;/h2>&lt;p>في التوليد التلقائي الانحداري، تعد &amp;ldquo;ذاكرة التخزين المؤقت KV&amp;rdquo; لتجاوز حسابات Key و Value للرموز السابقة ميزة أساسية.&lt;/p>
&lt;p>فيما يلي النقاط الرئيسية عند تنفيذ ذلك بـ C++:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>التخصيص المسبق للتنسور&lt;/strong>: تهيئة تنسور ضخم لذاكرة التخزين المؤقت KV بحجم الحد الأقصى لطول السياق (مثال: 2048 رمزاً) (يُفضل FP16).&lt;/li>
&lt;li>&lt;strong>نسخ الإزاحة (Offset Copy)&lt;/strong>: عند الحساب للموضع الرمزي $N$، يتم تخزين متجهات K و V الناتجة في تلك الخطوة في الصف $N$ من تنسور التخزين المؤقت KV باستخدام دوال مثل &lt;code>ggml_cpy&lt;/code>.&lt;/li>
&lt;li>&lt;strong>إنشاء مشهد (View) أثناء الانتباه&lt;/strong>: عند حساب الانتباه، يتم تمرير &amp;ldquo;مشهد&amp;rdquo; يشير فقط إلى أجزاء الرموز من 0 إلى $N$ لضرب المصفوفات.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-bpe-tokenizer-وفك-التشفير-decoding">8. BPE Tokenizer وفك التشفير (Decoding)
&lt;/h2>&lt;p>تتم معالجة السلسلة المدخلة كتسلسل بايتات UTF-8 وتتم مطابقتها مع مفردات محددة مسبقاً. في C++، لتسريع البحث في المفردات، يتم تنفيذ خوارزميات مثل &lt;strong>شجرة البادئة (Trie Tree)&lt;/strong> أو قوائم الانتظار ذات الأولوية.&lt;/p>
&lt;p>من سجلات Logits الناتجة عن LM Head، يتم قياس الاحتمالات باستخدام معلمة درجة الحرارة (Temperature)، ويتم تضييق المرشحين باستخدام استخراج Top-K أو أساليب Top-P (Nucleus Sampling)، ويتم تحديد الرمز التالي النهائي باستخدام أرقام عشوائية.&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"># إعدادات التحسين وعلامات AVX2 لـ Windows (MSVC)
&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>يعد تنفيذ محرك استدلال لنموذج ذكاء اصطناعي صغير مثل TinyLLaMA من الصفر باستخدام C++ و ggml فرصة رائعة لكشف الصندوق الأسود للتعلم العميق وتعلم جمال التحكم في الأجهزة منخفضة المستوى. باستخدام التحميل بنسخ صفري المعتمد على تخطيط الذاكرة، وتحسينات SIMD، وبناء ذاكرة التخزين المؤقت KV، دعونا نفتح آفاقاً جديدة لمستقبل الذكاء الاصطناعي الطرفي (Edge AI) بينما نستمتع بجوهر برمجة الأنظمة.&lt;/p></description></item></channel></rss>