العودة إلى المدونة

استكشاف الأخطاءدليل

معالجة الموجّه في llama.cpp أبطأ 35 مرة؟ أصلح ذاكرة KV من نوع q5_1

يمكن أن يدفع flash attention مع ذاكرة KV من نوع q5_1 الانتباه إلى المعالج. كيف تتأكد، وتصلحه بـ q8_0، ومتى تكون واجهة API أبسط.

بواسطة CheapTokens Teamنُشر في 6 دقيقة قراءة

طرفية تُظهر وحدة معالجة الرسوميات عند 0 بالمئة والمعالج عند 930 بالمئة أثناء معالجة الموجّه في llama.cpp
في هذه الصفحة
  1. كيف يبدو الأمر على الشاشة
  2. لماذا تجعل الذاكرة الأصغر الأمر أبطأ بهذا القدر
  3. تحقّق منه في دقيقتين
  4. الإصلاح 1: استخدم q8_0 (أو أعد البناء)
  5. متى يتوقف الضبط عن كونه مجديًا
  6. الترتيب الذي تعمل به

نموذجك المحلي يجيب بشكل جيد، لكن كل موجّه طويل الآن ينتظر دقيقة ونصف بينما وحدة معالجة الرسوميات لا تفعل شيئًا. إذا كنت تشغّل llama.cpp مع -fa on وذاكرة KV من نوع q5_1، فهذا على الأرجح هو السبب: بناء CUDA الافتراضي لا يحتوي على نواة flash-attention لهذا النوع من الذاكرة، لذا تُنفَّذ خطوة الانتباه بهدوء على المعالج. أدى تغيير الذاكرة إلى q8_0 إلى رفع سرعة معالجة الموجّه لدى أحد المستخدمين من 38 إلى 1348 رمزًا/ثانية.

الأرقام أدناه مأخوذة من مشكلة llama.cpp رقم #28455 (فُتحت في 5 سبتمبر 2026، البناء 10791، تم التحقق في 28 أكتوبر 2026). مستخدم واحد، وبطاقة RTX 4080 واحدة، ونموذج واحد بحجم 27B، لذا اقرأها كمثال عملي لا كقاعدة. تحليل السبب الجذري هو تحليلهم أيضًا: وصفه أحد المشرفين بأنه "مشكلة معروفة" وأغلق المشكلة في اليوم التالي.

كيف يبدو الأمر على الشاشة#

كان الإعداد عاديًا. أراد أحدهم سياقًا بطول 131072 رمزًا على بطاقة واحدة بسعة 16 GB، فقلّص ذاكرة KV إلى q5_1:

bash
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
  --cache-type-k q5_1 --cache-type-v q5_1

ثم أرسل موجّهًا بطول 3.6K رمزًا. جرت معالجة الموجّه بسرعة 38.4 رمزًا/ثانية وفك الترميز بسرعة 6.5 رمزًا/ثانية. احسب القسمة: 3,600 ÷ 38.4 = 93.75، أي نحو 94 ثانية قبل الكلمة الأولى. مع q8_0 جرى الموجّه نفسه بسرعة 1348 رمزًا/ثانية: 3,600 ÷ 1,348 = 2.67، أي أقل من ثلاث ثوانٍ.

الدليل موجود في مدير المهام. أثناء التشغيلات البطيئة كانت وحدة معالجة الرسوميات قرب 0% بينما أظهر المعالج نحو 930% (تسع أو عشر أنوية مشغولة). وحدة معالجة رسوميات خاملة بينما أنت "تشغّل على وحدة معالجة الرسوميات" هي العَرَض الذي يجب البحث عنه.

سرعة معالجة الموجّه مع ذاكرة KV من نوع q5_1 وq8_0
تقييم الموجّه على موجّه بطول 3.6K رمزًا، RTX 4080، مشكلة llama.cpp رقم #28455 (5 سبتمبر 2026)

لماذا تجعل الذاكرة الأصغر الأمر أبطأ بهذا القدر#

flash attention نواة مدمجة على وحدة معالجة الرسوميات. يوفّرها بناء CUDA الافتراضي فقط لبعض أزواج أنواع ذاكرة KV. بالنسبة إلى q4_0 وq4_1 وq5_0 وq5_1 لا توجد نواة، لذا لا يتوقف llama.cpp بخطأ. بل ينقل تلك العملية إلى المعالج ويستمر. كل شيء لا يزال يعمل، لكن أبطأ بنحو 35 مرة في معالجة الموجّه (1348 ÷ 38.4 = 35.1).

كلمة "بهدوء" هذه هي المشكلة كلها. لا شيء في الإجابة يخبرك. تنخفض معالجة الموجّه أكثر من غيرها (نحو 35×)، ويتباطأ التوليد أيضًا: 6.5 رمزًا/ثانية مقابل 30.1 مع q8_0 في المشكلة نفسها.

تحقّق منه في دقيقتين#

شغّل llama-bench بأنواع الذاكرة نفسها التي تستخدمها في الخادم، مرة لكل نوع، وراقب وحدة معالجة الرسوميات في طرفية أخرى:

bash
llama-bench -m model.gguf -ngl 99 -fa 1 -ctk q8_0 -ctv q8_0 -p 512 -n 0
llama-bench -m model.gguf -ngl 99 -fa 1 -ctk q5_1 -ctv q5_1 -p 512 -n 0
nvidia-smi -l 1

نتائج pp512 لدى المستخدم على Qwen 27B Q5_K_XL: 1511.92 رمزًا/ثانية لـ q8_0/q8_0، ونحو 197 لـ q5_1/q5_1 على البناء الافتراضي. إذا أظهر سطراك فجوة كهذه وأظهر nvidia-smi أن وحدة معالجة الرسوميات خاملة أثناء السطر الثاني، فقد وجدته.

قبل أن تصلح أي شيء، طابق ما تراه مع السبب المحتمل:

طابق الأزواج

طابق كل عَرَض مع سببه

  • وحدة معالجة الرسوميات عند ~0%، والمعالج عند ~930% أثناء موجّه طويلالانتباه يعمل على المعالج
  • ينخفض فك الترميز إلى ~6.5 رمزًا/ثانية مقابل 30.1 مع q8_0يتباطأ التوليد أيضًا، وليس معالجة الموجّه فقط
  • الأعلام نفسها سريعة مع q8_0هذا الزوج من أنواع الذاكرة لا يحتوي على نواة flash-attention على وحدة معالجة الرسوميات في البناء الافتراضي

الإصلاح 1: استخدم q8_0 (أو أعد البناء)#

أسرع إصلاح هو تغيير علمين والإبقاء على كل شيء آخر:

bash
llama-server -m model.gguf -ngl 99 -fa on -c 131072 -np 4 \
  --cache-type-k q8_0 --cache-type-v q8_0

في المشكلة أعطى هذا 1348 رمزًا/ثانية في معالجة الموجّه و30.1 رمزًا/ثانية في فك الترميز (بعد أن كان 6.5). الثمن هو الذاكرة: ذاكرة q8_0 أكبر من q5_1، لذا تحقق من أن طول سياقك لا يزال يتسع في VRAM.

إذا كان عليك الإبقاء على q5_1 لأسباب تتعلق بالذاكرة، فأعد البناء مع تضمين جميع تركيبات ذاكرة flash-attention:

bash
cmake -B build -DGGML_CUDA=ON -DGGML_CUDA_FA_ALL_QUANTS=ON
cmake --build build --config Release -j

شغّل ذلك البناء q5_1 بسرعة 1509.70 رمزًا/ثانية على pp512 و1162 رمزًا/ثانية على الموجّه بطول 3.6K رمزًا، مع فك ترميز بسرعة 38.5 رمزًا/ثانية. أشار أحد المعلّقين على المشكلة إلى أن نقل العمل بين الواجهات الخلفية قد يغيّر النتائج العددية قليلًا واقترح مقارنة الحيرة (perplexity) بين البنائين. إذا كانت المخرجات الدقيقة تهمك، فأجرِ واحدة.

قارن

أي إصلاح يناسب بطاقتك؟

ذاكرة q8_0

غيّر --cache-type-k و--cache-type-v إلى q8_0. دون إعادة بناء. يستهلك VRAM أكثر من q5_1، لذا أعد التحقق من حجم السياق الذي يمكنك استيعابه.

أعد البناء مع FA_ALL_QUANTS

أبقِ q5_1 وابنِ مع -DGGML_CUDA_FA_ALL_QUANTS=ON. VRAM نفسها كما كانت، لكنك تدير بناءك الخاص ويستغرق الترجمة وقتًا أطول.

رد المشرف "مشكلة معروفة" لا يوضح ما إذا كانت إصدارات llama.cpp الحالية قد غيّرت هذا. التحقق الصادق هو زوج llama-bench أعلاه: إذا كان السطران متقاربين، فأنت بخير.

متى يتوقف الضبط عن كونه مجديًا#

لنفترض أنك نجحت في الإصلاح، وأنت الآن تزن الجولة التالية: أعلام أكثر، أو وحدة معالجة رسوميات ثانية، أو تكميم أصغر. إذا كانت المهمة تلخيصًا أو مراجعة شيفرة أو استخراجًا على موجّهات من بضعة آلاف من الرموز، فاسأل عن تكلفة الطلب بالوقت والجهد، لا بالواط فقط.

إليك حمل عمل معلنًا للمقارنة. لنفترض أن مهمة تلخيص ترسل 3,600 رمز إدخال وتحصل على 500 رمز إخراج، 1,000 مرة. على CheapTokens يكلف ذلك نحو $0.104 على DeepSeek-V4-Flash (سياق 380K، حتى 32,768 رمز إخراج لكل إجابة، سعر واحد في أي ساعة) ونحو $0.092 على GLM-5.3-Flash (سياق 390K). يحسب الجدول الإدخال والإخراج معًا، مع عمود OpenRouter للمقارنة:

النموذج لكل طلب 1,000 طلبات OpenRouter، 1,000 طلبات
GLM-5.3-Flash $0.000092 $0.092 $0.187
DeepSeek-V4-Flash $0.0001 $0.104 $0.249
MiniMax-M2.7 $0.00026 $0.255 $1.68

3,600 رمز إدخال و500 رمز إخراج لكل طلب. الأسعار لكل مليون رمز حالية وتتغير مع تعريفاتنا؛ يعرض عمود OpenRouter أسعارًا مرجعية لنفس حجم العمل.

لا يهم واجهة API نوع ذاكرتك أو VRAM أو أعلام بنائك؛ لا شيء يعود إلى المعالج. أرسل حفنة من موجّهاتك الحقيقية أولًا واحكم على الإجابات بنفسك. الخطوة صغيرة: نقطة النهاية تتحدث صيغة OpenAI Chat Completions، لذا تحتاج معظم العملاء المحليين فقط إلى عنوان URL أساسي جديد.

bash
curl https://api.cheaptokens.dev/v1/chat/completions \
  -H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek-ai/DeepSeek-V4-Flash-0731", "messages": [{"role": "user", "content": "Summarize the text below in 5 bullets: ..."}], "max_tokens": 500}'

الإعداد الكامل في وثائق CheapTokens، والأسعار الحالية لكل نموذج على صفحة الأسعار. لنظرة أطول على العتاد مقابل API، راجع تشغيل DeepSeek محليًا أو استخدام API. إذا أردت معرفة كيف تُحاسب الإدخالات والمخرجات بشكل منفصل، فـ رموز الإدخال مقابل الإخراج تغطي ذلك.

الترتيب الذي تعمل به#

رتّب بالترتيب

رتّب خطوات استكشاف الأخطاء وإصلاحها

  1. شغّل llama-bench لـ q8_0 وq5_1 وراقب nvidia-smi
  2. غيّر نوعي الذاكرة إلى q8_0
  3. تحقق من أن طول السياق لا يزال يتسع في VRAM
  4. أعد البناء مع GGML_CUDA_FA_ALL_QUANTS=ON فقط إذا كنت بحاجة إلى q5_1
  5. قارن الموجّه نفسه على API إذا كان الإعداد المحلي لا يزال لا يستحق الجهد

تحذير آخر بشأن المصادر: التشخيص كله يستند إلى مشكلة عامة واحدة وبطاقة واحدة. اعتبر 1348 و38.4 كما حدثا هناك، وقِس بطاقتك قبل أن تثق بأي منهما.