<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GGUF on kenji.blog</title><link>http://kenji.blog/ar/tags/gguf/</link><description>Recent content in GGUF on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 00:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/tags/gguf/index.xml" rel="self" type="application/rss+xml"/><item><title>شرح آلية تقنية التكميم (GGUF) في llama.cpp</title><link>http://kenji.blog/ar/p/llama-cpp-quantization-gguf/</link><pubDate>Fri, 11 Sep 2026 00:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/llama-cpp-quantization-gguf/</guid><description>&lt;img src="http://kenji.blog/p/llama-cpp-quantization-gguf/img/eyecatch.jpg" alt="Featured image of post شرح آلية تقنية التكميم (GGUF) في llama.cpp" />&lt;h2 id="1-مقدمة-لماذا-تحتاج-النماذج-اللغوية-الكبيرة-llm-إلى-التكميم-quantization">1. مقدمة: لماذا تحتاج النماذج اللغوية الكبيرة (LLM) إلى التكميم (Quantization)؟
&lt;/h2>&lt;p>التطور الأخير في النماذج اللغوية الكبيرة (LLMs) ملحوظ بشكل كبير، ولكن خلف الكواليس ظهرت مشاكل خطيرة تتمثل في &amp;ldquo;استنفاد الموارد الحسابية&amp;rdquo; و&amp;quot;عنق الزجاجة في النطاق الترددي للذاكرة&amp;quot;. على سبيل المثال، إذا تم تحميل نموذج يحتوي على 70 مليار (70B) معلمة مثل Llama 3 في الذاكرة باستخدام النقطة العائمة القياسية 16 بت (FP16)، فإنه يستهلك حوالي 140 جيجابايت من VRAM/RAM للمعلمات فقط. وإذا أضفنا سياق الاستدلال (ذاكرة التخزين المؤقت KV)، فلن يعمل إلا إذا تم ربط وحدات معالجة رسومات (GPU) متطورة مخصصة لمراكز البيانات (مثل NVIDIA A100 80GB أو H100 80GB) في مجموعة (Cluster).&lt;/p>
&lt;p>كمنقذ لتمكين تشغيل النماذج اللغوية الكبيرة للمطورين الأفراد وعلى الأجهزة الطرفية (مثل أجهزة MacBook وأجهزة الكمبيوتر الشخصية المخصصة للألعاب)، ظهرت &lt;strong>llama.cpp&lt;/strong> وفي صميمها &lt;strong>تقنية التكميم (Quantization)&lt;/strong>. وبشكل خاص، تعد صيغة الملفات &lt;strong>GGUF (GPT-Generated Unified Format)&lt;/strong> وخوارزمية التكميم المتقدمة القائمة على الكتل والتي تسمى &lt;strong>k-quants&lt;/strong>، نهجًا ثوريًا يضغط حجم النموذج إلى أجزاء صغيرة من حجمه الأصلي، مع الحد من تدهور دقة النموذج (Perplexity) إلى أدنى مستوى ممكن.&lt;/p>
&lt;p>في هذه المقالة، سنشرح بالتفصيل تقنية التكميم في llama.cpp بدءًا من خلفيتها الرياضية، والاختلافات عن صيغة GGML، والهيكل التفصيلي لصيغة GGUF، وصولاً إلى الآلية الداخلية لـ k-quants.&lt;/p>
&lt;hr>
&lt;h2 id="2-الأساس-الرياضي-للتكميم-quantization">2. الأساس الرياضي للتكميم (Quantization)
&lt;/h2>&lt;p>في سياق النماذج اللغوية الكبيرة، يشير التكميم إلى عملية تعيين القيم المستمرة (أو أرقام النقطة العائمة عالية الدقة) إلى قيم منفصلة بعدد بتات أقل (مثل INT8 و INT4 و INT3 وما إلى ذلك).&lt;/p>
&lt;h3 id="21-المعادلة-الأساسية-للتكميم-الخطي">2.1. المعادلة الأساسية للتكميم الخطي
&lt;/h3>&lt;p>النهج الأبسط هو التكميم الخطي (تكميم Min-Max). لنفترض أن موتر الوزن (Weight Tensor) الأصلي عالي الدقة هو $W$، وموتر الأعداد الصحيحة المكمم هو $W_q$.&lt;/p>
$$ W_q = \text{round}\left( \frac{W}{S} \right) + Z $$
&lt;p>حيث:&lt;/p>
&lt;ul>
&lt;li>$S$ هو &lt;strong>عامل المقياس (Scale Factor)&lt;/strong>، والذي يحدد حجم الخطوة (الدقة) للتكميم.&lt;/li>
&lt;li>$Z$ هي &lt;strong>نقطة الصفر (Zero-point)&lt;/strong>، وهي قيمة انحياز تستخدم لإزاحة القيمة التي سيقابلها الرقم الحقيقي $0.0$ كقيمة صحيحة بعد التكميم.&lt;/li>
&lt;li>$\text{round}(\cdot)$ هي دالة التقريب إلى أقرب عدد صحيح.&lt;/li>
&lt;/ul>
&lt;p>من خلال إلغاء التكميم (Dequantization)، نقوم باستعادة الوزن الحقيقي التقريبي $\tilde{W}$ أثناء الاستدلال.&lt;/p>
$$ \tilde{W} = S \times (W_q - Z) $$
&lt;h3 id="22-التكميم-المتماثل-مقابل-التكميم-غير-المتماثل">2.2. التكميم المتماثل مقابل التكميم غير المتماثل
&lt;/h3>&lt;p>بناءً على كيفية التعامل مع نقطة الصفر $Z$، ينقسم الأمر بشكل أساسي إلى طريقتين:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>التكميم غير المتماثل (Asymmetric Quantization)&lt;/strong>
يتم التعيين باستخدام الحد الأدنى $W_{\min}$ والحد الأقصى $W_{\max}$ للبيانات.
&lt;/p>
$$ S = \frac{W_{\max} - W_{\min}}{2^b - 1}, \quad Z = \text{round}\left(-\frac{W_{\min}}{S}\right) $$
&lt;p>
حيث $b$ هو عدد بتات التكميم (مثال: إذا كان 4 بت، فإن $2^4-1 = 15$). نظرًا لوجود حاجة للاحتفاظ بـ $Z$، يزداد العبء الحسابي والذاكرة قليلاً.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>التكميم المتماثل (Symmetric Quantization)&lt;/strong>
يتم التعيين حول الصفر باستخدام الحد الأقصى للقيمة المطلقة للبيانات ($Z=0$).
&lt;/p>
$$ S = \frac{\max(|W_{\max}|, |W_{\min}|)}{2^{b-1} - 1}, \quad Z = 0 $$
&lt;p>
اعتمدت عمليات التكميم المبكرة في llama.cpp (مثل Q4_0 القديم) التكميم المتماثل، ونظرًا لعدم وجود حد $Z$، فإن لها ميزة تسريع حسابات الضرب النقطي بشكل كبير باستخدام تعليمات SIMD.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-التطور-من-ggml-إلى-gguf-وهيكل-الملف">3. التطور من GGML إلى GGUF وهيكل الملف
&lt;/h2>&lt;p>عند الحديث عن llama.cpp، لا يمكننا تجاهل مكتبة عمليات الموترات (Tensor) المكتوبة بلغة C++ &lt;strong>GGML&lt;/strong>، وصيغة الملفات المشتقة منها &lt;strong>GGUF&lt;/strong>.&lt;/p>
&lt;h3 id="31-تحديات-ggml">3.1. تحديات GGML
&lt;/h3>&lt;p>كانت الإصدارات الأولى من llama.cpp تستخدم صيغة &lt;code>ggml&lt;/code> (ومتغيراتها مثل &lt;code>ggjt&lt;/code>). ومع ذلك، كانت تعاني من المشاكل التالية:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>نقص قابلية التوسع:&lt;/strong> كانت الأرقام السحرية (Magic numbers) والمعلمات الفائقة مبرمجة بشكل ثابت (Hardcoded) بطول وترتيب ثابتين، مما أدى إلى تغييرات جذرية مع كل إضافة لهندسة نموذج جديدة (مثل: Llama و Falcon و Mixtral وما إلى ذلك) أو رمز مميز (Tokenizer) جديد.&lt;/li>
&lt;li>&lt;strong>فقدان التوافقية مع الإصدارات السابقة:&lt;/strong> تم تحديث الصيغة بشكل متكرر، مما أدى غالبًا إلى حالات لا يمكن فيها قراءة ملفات النماذج القديمة بواسطة أحدث إصدارات llama.cpp.&lt;/li>
&lt;/ul>
&lt;h3 id="32-ولادة-صيغة-gguf">3.2. ولادة صيغة GGUF
&lt;/h3>&lt;p>تم تقديم &lt;strong>GGUF&lt;/strong> في أغسطس 2023، وهي صيغة عالية التنوع مصممة لحل هذه المشكلات. أكبر ميزة لها هي اعتمادها على &lt;strong>هيكل بيانات وصفية (Metadata) يعتمد على المفتاح والقيمة (Key-Value)&lt;/strong>.&lt;/p>
&lt;p>يوضح مخطط Mermaid التالي الشكل المجرد لهيكل ملف GGUF.&lt;/p>
&lt;div class="mermaid">graph TD
A["ملف GGUF"] --> B["الرأس (السحر، الإصدار)"]
A --> C["البيانات الوصفية (أزواج المفتاح والقيمة)"]
A --> D["معلومات الموتر (الاسم، الشكل، الإزاحة)"]
A --> E["بيانات الموتر (حمولة ثنائية)"]
C --> C1["general.architecture: llama"]
C --> C2["llama.context_length: 4096"]
C --> C3["tokenizer.ggml.tokens: [...]"]
E --> E1["أوزان الطبقة 0"]
E --> E2["أوزان الطبقة 1"]
E --> E3["..."]&lt;/div>
&lt;p>&lt;strong>المزايا الرئيسية لـ GGUF:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>المرونة:&lt;/strong> يتم تخزين جميع المعلمات الفائقة للنموذج، وإعدادات RoPE (Rotary Positional Embedding)، وبيانات مفردات الرموز (Tokenizer) كأزواج مفتاح-قيمة مسماة. يتم تجاهل المفاتيح غير المعروفة، مما يجعل إضافة ميزات جديدة أمراً سهلاً.&lt;/li>
&lt;li>&lt;strong>الاستقلالية عن ترتيب البايتات (Endianness):&lt;/strong> تعتمد GGUF على ترتيب البايتات الصغير (Little-endian) بشكل افتراضي، ولكنها تحتوي صراحة على علامة (Flag) للترتيب، مما يجعلها قابلة للنقل بأمان عبر البنى المختلفة.&lt;/li>
&lt;li>&lt;strong>التحسين لـ mmap (تخطيط الذاكرة):&lt;/strong> تتم محاذاة (Padding) بيانات الموتر عند حدود معينة، ويمكن تعيينها مباشرة من القرص إلى مساحة الذاكرة باستخدام استدعاء النظام &lt;code>mmap()&lt;/code> في نظام التشغيل. ونتيجة لذلك، يصبح وقت التهيئة لتحميل النموذج فعليًا صفراً.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-أعماق-k-quants-التكميم-المتقدم-القائم-على-الكتل">4. أعماق k-quants: التكميم المتقدم القائم على الكتل
&lt;/h2>&lt;p>الجوهر الحقيقي لصيغة GGUF هو آلية &lt;strong>k-quants (K-quantization)&lt;/strong> المسؤولة عن ضغط أوزان النموذج.&lt;/p>
&lt;p>عادةً، تقترب أوزان الشبكات العصبية من التوزيع الطبيعي عند النظر إلى الطبقة ككل، ولكن توجد محلياً قيم متطرفة (Outliers). إذا قمنا بتكميم أوزان الطبقة بأكملها باستخدام عامل مقياس $S$ موحد، فإن القيم المتطرفة ستسحب المقياس، وسيتم فقدان معلومات الأوزان الصغيرة تمامًا.&lt;/p>
&lt;p>لمنع ذلك، تقوم llama.cpp بتنفيذ &lt;strong>التكميم القائم على الكتل (Block-wise Quantization)&lt;/strong>. يتم تقسيم موتر الأوزان إلى كتل صغيرة (مثلاً 32 عنصرًا أو 256 عنصرًا)، وتحصل كل كتلة على عامل مقياس (ونقطة صفر) خاص بها.&lt;/p>
&lt;h3 id="41-حدود-التكميم-القديم-q4_0-q4_1">4.1. حدود التكميم القديم (Q4_0, Q4_1)
&lt;/h3>&lt;p>كان &lt;code>Q4_0&lt;/code> الأولي يستخدم 32 وزنًا من نوع FP16 ككتلة واحدة، ويتشارك عامل مقياس FP16 واحد.&lt;/p>
&lt;ul>
&lt;li>حجم الكتلة: 32&lt;/li>
&lt;li>الذاكرة: 1 مقياس (16 بت) + 32 وزنًا بـ 4-بت (128 بت) = 144 بت&lt;/li>
&lt;li>عدد البتات الفعال لكل عنصر (bpw: bits per weight): $144 / 32 = 4.5$ bpw&lt;/li>
&lt;/ul>
&lt;p>على الرغم من أن هذا ممتاز، إلا أن حدود الدقة ونسبة الضغط أصبحت واضحة. هنا ظهرت &lt;strong>k-quants&lt;/strong> بهيكل هرمي أكثر تعقيدًا وتطوراً.&lt;/p>
&lt;h3 id="42-الهيكل-الهرمي-للكتل-الفائقة-والكتل-الفرعية-مثال-q4_k_m">4.2. الهيكل الهرمي للكتل الفائقة والكتل الفرعية (مثال Q4_K_M)
&lt;/h3>&lt;p>تمتلك k-quants هيكلاً هرمياً يتكون من &amp;ldquo;كتل فائقة (Super-block)&amp;rdquo; كبيرة، و&amp;quot;كتل فرعية (Sub-block)&amp;quot; أصغر مضمنة بداخلها. بفضل هذا، يتم تكميم البيانات الوصفية (مثل قيم المقياس) نفسها، مما يقلل bpw إلى أقصى حد مع الحفاظ على الدقة.&lt;/p>
&lt;p>لنلقِ نظرة على هيكل &lt;strong>Q4_K_M&lt;/strong>، وهو الإعداد الأكثر شيوعًا. يستخدم Q4_K_M كتلة فائقة مكونة من 256 عنصرًا.&lt;/p>
&lt;div class="mermaid">graph TD
A["كتلة فائقة (256 وزناً)"] --> B["البيانات الوصفية للمقياس (FP16/INT8)"]
A --> C["كتلة فرعية 0 (32 وزناً، 4-بت)"]
A --> D["كتلة فرعية 1 (32 وزناً، 4-بت)"]
A --> E["..."]
A --> F["كتلة فرعية 7 (32 وزناً، 4-بت)"]
B --> B1["مقياس فائق (FP16)"]
B --> B2["مقاييس فرعية (8 × 6-بت)"]
B --> B3["حدود دنيا فرعية (8 × 6-بت)"]&lt;/div>
&lt;p>يتم تعريف البنية الفعلية في C++ (GGML) بشكل مفاهيمي على النحو التالي:&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;/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">// الهيكل المفاهيمي لـ block_q4_K في llama.cpp
&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 QK_K 256
&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">block_q4_K&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="n">d&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// المقياس الفائق للكتلة الفائقة بأكملها (مثل FP16 x 2)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">scales&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// بيانات مجمعة تحتوي على مقياس 6-بت والحد الأدنى 6-بت (نقطة الصفر) لـ 8 كتل فرعية (32 عنصرًا لكل منها)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">qs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">QK_K&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// بيانات الأوزان المكممة بـ 4-بت (256 عنصرًا / 2 = 128 بايت)
&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>عملية إلغاء التكميم (Dequantization) الرياضية:&lt;/strong>&lt;/p>
&lt;p>يتم حساب القيمة الحقيقية التقريبية $\tilde{W}_{i, j}$ للعنصر $j$ ($0 \le j &lt; 32$) داخل الكتلة الفرعية $i$ ($0 \le i &lt; 8$) على النحو التالي:&lt;/p>
$$ \tilde{W}_{i, j} = S_{\text{super}} \times s_i \times (w_{i, j} - m_i) $$
&lt;ul>
&lt;li>$S_{\text{super}}$: مقياس النقطة العائمة للكتلة الفائقة بأكملها&lt;/li>
&lt;li>$s_i$: مقياس 6-بت المكمم للكتلة الفرعية $i$&lt;/li>
&lt;li>$m_i$: الحد الأدنى (نقطة الصفر) 6-بت المكمم للكتلة الفرعية $i$&lt;/li>
&lt;li>$w_{i, j}$: وزن التكميم 4-بت ($0 \dots 15$)&lt;/li>
&lt;/ul>
&lt;p>من خلال هذا الهيكل الهرمي، مع الحفاظ على القدرة على التكيف مع القيم المتطرفة، يتم تقليل مساحة الذاكرة التي تشغلها عوامل المقياس نفسها بشكل كبير. يحقق Q4_K_M إجماليًا يبلغ حوالي &lt;strong>4.8 bpw&lt;/strong>.&lt;/p>
&lt;h3 id="43-خيارات-k-quants-المتنوعة">4.3. خيارات k-quants المتنوعة
&lt;/h3>&lt;p>تقدم llama.cpp العديد من المتغيرات اعتمادًا على الغرض. تشير اللواحق (S, M, L) بعد &amp;ldquo;K&amp;rdquo; إلى الحجم.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">الصيغة&lt;/th>
&lt;th style="text-align:center">BPW (بت لكل وزن)&lt;/th>
&lt;th style="text-align:left">نظرة عامة والميزات&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q2_K&lt;/strong>&lt;/td>
&lt;td style="text-align:center">2.5～3.3&lt;/td>
&lt;td style="text-align:left">ضغط أقصى. انخفاض كبير في الدقة، لكنه مخصص للبيئات التي تحتوي على VRAM قليل جدًا.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q3_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">3.3&lt;/td>
&lt;td style="text-align:left">المعيار لتكميم 3 بت. يتدهور أكثر من Q4 ولكنه غالباً ما يبقى ضمن الحدود المقبولة.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q4_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">4.8&lt;/td>
&lt;td style="text-align:left">&lt;strong>النقطة المثالية الموصى بها&lt;/strong>. يوازن بين خفض حجم النموذج إلى النصف والحفاظ على الدقة.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q5_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">5.5&lt;/td>
&lt;td style="text-align:left">عندما تتطلب دقة أعلى. يمثل موقعاً وسطاً بين Q4 و FP16.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q6_K&lt;/strong>&lt;/td>
&lt;td style="text-align:center">6.6&lt;/td>
&lt;td style="text-align:left">يحافظ على Perplexity (حيرة) متطابقة تقريبًا مع FP16، لكن حجم الملف أكبر.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q8_0&lt;/strong>&lt;/td>
&lt;td style="text-align:center">8.5&lt;/td>
&lt;td style="text-align:left">يعادل INT8. يستخدم بشكل رئيسي للموترات الوسيطة أثناء الاستدلال، أو في الطبقة الأخيرة فقط.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>※ يتم متوسط BPW الفعلي عبر النموذج بأكمله نظرًا لأنه يتم تطبيق التكميم المختلط (Mixed Quantization) اعتمادًا على موترات النموذج (على سبيل المثال، إسقاط Q/K/V في Attention، أو أوزان FFN). داخلياً يتم إجراء تحسينات مثل تكميم الموترات المهمة بـ Q6 والباقي بـ Q4.&lt;/p>
&lt;hr>
&lt;h2 id="5-تحسين-أداء-الاستدلال-تعليمات-simd-ومعمارية-cuda">5. تحسين أداء الاستدلال: تعليمات SIMD ومعمارية CUDA
&lt;/h2>&lt;p>مجرد تحميل نموذج GGUF في الذاكرة لن يؤدي إلى تسريع الاستدلال. يمثل الجزء الأكبر من الاستدلال في النماذج اللغوية الكبيرة &amp;ldquo;ضرب المصفوفات (Matrix-Vector Multiplication، واختصاراً GEMV، أو Matrix-Matrix، GEMM)&amp;rdquo;. المفتاح هو كيفية تسريع عمليات الضرب والجمع بين الأوزان المكممة والتنشيطات (بيانات الإدخال) المحفوظة بتنسيق FP16 (أو FP32).&lt;/p>
&lt;h3 id="51-استخدام-تعليمات-simd-في-بيئة-وحدة-المعالجة-المركزية-cpu">5.1. استخدام تعليمات SIMD في بيئة وحدة المعالجة المركزية (CPU)
&lt;/h3>&lt;p>السرعة المذهلة التي تفتخر بها llama.cpp في استدلال وحدة المعالجة المركزية (CPU) ترجع إلى تحسين &lt;strong>SIMD (Single Instruction, Multiple Data)&lt;/strong> على مستوى التجميع (Assembly).
على سبيل المثال، تستفيد بشكل كامل من مجموعات تعليمات &lt;strong>AVX2&lt;/strong> أو &lt;strong>AVX-512&lt;/strong> على معالجات Intel/AMD، وتعليمات &lt;strong>ARM NEON&lt;/strong> على Apple Silicon.&lt;/p>
&lt;p>أثناء الاستدلال، لا يتم إرجاع $W_q$ إلى FP32 (إلغاء التكميم) أولاً ثم إجراء الضرب.
بل يتم تكميم جانب التنشيطات ديناميكياً (Dynamic Quantization، عادةً إلى INT8) على مستوى الكتلة، ويتم حساب العمليات الصحيحة لـ &lt;strong>INT8 $\times$ INT4&lt;/strong> دفعة واحدة باستخدام تعليمات الضرب النقطي الخاصة بـ SIMD (مثل: &lt;code>vdpaddd&lt;/code> أو &lt;code>_mm256_madd_epi16&lt;/code>). بفضل ذلك، في المتراكم النهائي (Accumulator)، يتم تحويل القيم مرة أخرى إلى FP32 وضربها في عامل المقياس، مما يحقق إنتاجية مذهلة (Throughput).&lt;/p>
&lt;h3 id="52-التفريغ-offload-في-بيئة-gpu-cublas--cuda">5.2. التفريغ (Offload) في بيئة GPU (cuBLAS / CUDA)
&lt;/h3>&lt;p>لم تعد llama.cpp تقتصر على دعم CPU فحسب، بل توفر أيضًا دعمًا قويًا لوحدات معالجة الرسومات من NVIDIA (CUBLAS / CUDA).
من الممكن تفريغ جزء من طبقات ملف GGUF أو جميعها إلى VRAM (خيار &lt;code>--n-gpu-layers&lt;/code>).&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant User
participant CPU_RAM as CPU &amp; RAM (mmap)
participant VRAM as GPU VRAM
participant Compute as أنوية Tensor
User->>CPU_RAM: تحميل GGUF (mmap)
CPU_RAM->>VRAM: تفريغ الطبقات (مثلاً 30/32 طبقة)
Note over CPU_RAM, VRAM: تبقى البيانات مكممة في VRAM
User->>Compute: التمرير الأمامي (الرموز المدخلة)
Compute->>VRAM: جلب الأوزان المكممة
Compute->>Compute: إلغاء التكميم إلى FP16 سريعاً في SRAM
Compute->>Compute: ضرب المصفوفات (cuBLAS / Custom Kernels)
Compute->>User: إخراج اللوغاريتمات (Logits)&lt;/div>
&lt;p>عند الحساب على GPU، يكون النطاق الترددي للذاكرة (Memory Bandwidth) لـ VRAM هو العائق الأكبر. وبما أن الأوزان مضغوطة بتقنية k-quants، يتم تقليل كمية نقل البيانات من VRAM إلى وحدات الحساب في GPU (SM: Streaming Multiprocessor أو أنوية Tensor) إلى 1/3 ~ 1/4. في اللحظة التي تصل فيها الأوزان إلى وحدة الحساب، يتم إلغاء تكميمها (فك ضغطها) سريعًا إلى FP16، ويتم تنفيذ ضرب المصفوفات بسرعة فائقة باستخدام Tensor Core.
بعبارة أخرى، يمكن القول إن التكميم يتم &lt;strong>&amp;ldquo;ليس لتقليل حجم العمليات الحسابية&amp;rdquo; بل &amp;ldquo;لتقليل كمية نقل البيانات من الذاكرة&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="6-أمثلة-عملية-لمقايضة-trade-off-بين-استهلاك-الذاكرة-والأداء">6. أمثلة عملية لمقايضة (Trade-off) بين استهلاك الذاكرة والأداء
&lt;/h2>&lt;p>هنا، لنأخذ نموذج Llama 3 8B كمثال لنتعرف على المواصفات المطلوبة بناءً على مستوى تكميم GGUF. (الأرقام هي قيم تقريبية)&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">النموذج/التكميم&lt;/th>
&lt;th style="text-align:left">حجم الملف&lt;/th>
&lt;th style="text-align:left">VRAM/RAM المطلوب&lt;/th>
&lt;th style="text-align:left">سرعة الاستدلال (تقريبية)&lt;/th>
&lt;th style="text-align:left">تدهور Perplexity&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (FP16)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 16 GB&lt;/td>
&lt;td style="text-align:left">18 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">الأساس&lt;/td>
&lt;td style="text-align:left">لا يوجد (الأساس)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q8_0)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 8.5 GB&lt;/td>
&lt;td style="text-align:left">10 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">سريعة&lt;/td>
&lt;td style="text-align:left">شبه معدوم&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q6_K)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 6.6 GB&lt;/td>
&lt;td style="text-align:left">8 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">سريعة جداً&lt;/td>
&lt;td style="text-align:left">ضئيل جداً&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q4_K_M)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 4.9 GB&lt;/td>
&lt;td style="text-align:left">6.5 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">الأسرع والأمثل&lt;/td>
&lt;td style="text-align:left">ضمن الحدود، ضئيل&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q3_K_M)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 3.9 GB&lt;/td>
&lt;td style="text-align:left">5.5 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">الأسرع&lt;/td>
&lt;td style="text-align:left">ملحوظ قليلاً&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q2_K)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">حوالي 3.0 GB&lt;/td>
&lt;td style="text-align:left">4.5 GB أو أكثر&lt;/td>
&lt;td style="text-align:left">سريعة&lt;/td>
&lt;td style="text-align:left">تدهور واضح&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>ملاحظة هامة (تأثير ذاكرة التخزين المؤقت KV):&lt;/strong>
في استدلال النماذج اللغوية الكبيرة، كلما زاد طول السياق (عدد الرموز في الموجه)، لا تزيد الأوزان فحسب بل يزداد استهلاك الذاكرة بشكل انفجاري بسبب &lt;strong>ذاكرة التخزين المؤقت KV (KV Cache)&lt;/strong> التي تحفظ حالة الانتباه (Attention) السابقة.
على سبيل المثال، إذا كان طول السياق 8192 رمزاً، ستستهلك ذاكرة KV وحدها عدة جيجابايتات. ولذلك، في الاستخدام الفعلي، من الضروري الاحتفاظ بهامش إضافي (Headroom) يعادل &lt;code>حجم ملف النموذج + حوالي 1.5GB إلى 3GB&lt;/code>. السبب في التوصية بـ Q4_K_M هو أنه حتى مع تخصيص مساحة لـ KV Cache، فإنه يوفر توازناً مثالياً يسمح بتشغيل آمن على بطاقات الرسومات الشائعة المزودة بـ 8GB VRAM (مثل RTX 3060 / 4060).&lt;/p>
&lt;p>في الإصدارات الأخيرة من llama.cpp، تمت إضافة &lt;strong>ميزة تكميم ذاكرة التخزين المؤقت KV بحد ذاتها إلى Q8_0 أو Q4_0&lt;/strong>، وهناك جهود مستمرة لزيادة طول السياق بشكل أكبر.&lt;/p>
&lt;hr>
&lt;h2 id="7-الخاتمة">7. الخاتمة
&lt;/h2>&lt;p>في هذه المقالة، قمنا بالتعمق في الهيكل الداخلي لصيغة GGUF وتقنية تكميم k-quants، والتي تعد قلب llama.cpp النابض.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>مرونة GGUF:&lt;/strong> بفضل هيكل البيانات الوصفية الذي يعتمد على المفتاح والقيمة، تم بناء نظام بيئي قوي يمكنه مواكبة التطور السريع للنماذج اللغوية الكبيرة (وظهور بنيات نماذج جديدة) دون تغييرات جذرية تدمر التوافق.&lt;/li>
&lt;li>&lt;strong>ضغط أقصى مع k-quants:&lt;/strong> من خلال إدارة عامل المقياس بشكل هرمي عبر الكتل الفائقة والكتل الفرعية، أمكن تحقيق ضغط مذهل بمتوسط 4.8 بت لكل وزن (Q4_K_M) مع الحفاظ على معلومات القيم المتطرفة.&lt;/li>
&lt;li>&lt;strong>تجاوز عنق الزجاجة في النطاق الترددي للذاكرة:&lt;/strong> من خلال تنفيذ تطبيقات Kernel متقدمة في SIMD و CUDA، أتاح إجراء الحسابات مع إلغاء التكميم سريعاً (On-the-fly) تقليل كمية نقل بيانات VRAM، مما أدى إلى تحسين سرعة الاستدلال بشكل كبير.&lt;/li>
&lt;/ol>
&lt;p>إن القوة التقنية لـ llama.cpp، والتي تدفع نحو ديمقراطية الذكاء الاصطناعي، تتجاوز كونها مجرد أداة ويمكن القول إنها من أرقى قمم هندسة البرمجيات الحديثة. من خلال فهم خوارزمية التكميم وآلية صيغة GGUF، ستتمكن من اختيار النموذج الأنسب لبيئتك وإجراء ضبط الأداء بدقة أكبر.&lt;/p>
&lt;h3 id="روابط-مرجعية">روابط مرجعية
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener"
>مستودع llama.cpp على GitHub&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/ggml/blob/master/docs/gguf.md" target="_blank" rel="noopener"
>مواصفات صيغة GGUF&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp/pull/1684" target="_blank" rel="noopener"
>طلب السحب (PR) الخاص بتنفيذ K-quants&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>(النهاية)&lt;/p></description></item></channel></rss>