الإعدادات والتقديرات والخطوات التالية هنا تخص وقت كتابة الملاحظة. نحتفظ بنتائج التشغيل كما هي؛ تحديث الصياغة ما يعني إننا أعدنا التجربة أو إن حالة التنفيذ القديمة لسه هي الحالية.
الـloader القديم كان يوسّع أوزان K-quant إلى f32، فصار الملف الأصغر أغلى في الذاكرة. ملف Qwen Q4_K_M حجمه 1066 MB، بس peak RSS وصل 8712 MB؛ مقابل 1941 MB لـQ8_0. القياسات تخص سياسة التحميل القديمة اللي تغيرت بعدها.
عشان كذا المسار المقاس وقتها ما كان مناسب لهدف الذاكرة الأقل أو التأخير الأقل. النتيجة تخص سياسة الـloader والـbackend في النسخة هذي، وما ينفع نعممها على GGUF أو K-quants أو low-bit quantization عموماً.
pre-optimization engineering baseline فقط. الجدول يغطي عائلتين صغيرتين على جهاز محلي واحد. هذي مو نتيجة جديدة في quantization، ولا ادعاء production deployment، ولا مقارنة تقول إن Ember أسرع من llama.cpp.
هل quantized checkpoint الأصغر ينتج بالضرورة deployment محلياً أصغر وأسرع؟
الـbenchmark المجمّد يقيس حجم الملف، ووقت التحميل مع prefill، وسرعة decode، وpeak RSS. العمود الأخير هو المفتاح: يسجل ما يحتفظ به Ember في الذاكرة ويشغله، مو فقط ما يقوله اسم الملف.
| النموذج | quantization | حجم الملف | load + prefill | decode tok/s | peak RSS | تمثيل runtime |
|---|---|---|---|---|---|---|
| Qwen2.5-1.5B-Instruct | Q8_0 | 1807 MB | 0.97 s | 40.6 | 1941 MB | compressed-resident |
| Qwen2.5-1.5B-Instruct | Q6_K | 1396 MB | 14.4 s | 2.5 | 8713 MB | persistent f32 expansion |
| Qwen2.5-1.5B-Instruct | Q4_K_M | 1066 MB | 13.0 s | 2.6 | 8712 MB | persistent f32 expansion |
| Llama-3.2-1B | Q8_0 | 1260 MB | 2.03 s | 149.6 | 2685 MB | compressed-resident |
| Llama-3.2-1B | Q6_K | 974 MB | 16.4 s | 2.9 | 6965 MB | persistent f32 expansion |
| Llama-3.2-1B | Q4_K_M | 770 MB | 15.9 s | 3.2 | 6965 MB | persistent f32 expansion |
في Qwen، ملف Q4_K_M أصغر من Q8_0 على القرص بنحو 41%، بس يستهلك تقريباً 4.49× من peak RSS ويكون decode أبطأ بنحو 15.6×. وفي Llama، يصغر الملف بنحو 39%، بينما ترتفع الذاكرة إلى 2.59× وتصبح السرعة أبطأ بنحو 46.8×.
عبر مقارنات Q4/Q6 الأربع، يصبح decode أبطأ بين 15.6× و51.6×، وترتفع peak RSS بين 2.59× و4.49×. أعلى قيمة، 51.6×، هي Llama Q6_K، وأقل قيمة، 15.6×، هي Qwen Q4_K_M.
نفس الصورة تتكرر في العائلتين: الشيء الوحيد اللي يصغر مع Q6/Q4 هو الملف على القرص. ووقت التحميل يرتفع أيضاً من نحو ثانية أو ثانيتين في Q8_0 إلى نحو 13–16 ثانية في Q6_K وQ4_K_M.
quantization في الـcheckpoint تصف طريقة ترميز الـtensors داخل الملف. ما تقول تلقائياً كيف يخزنها الـruntime أو أي kernels يشغلها. مسار Q8_0 في Ember يبقي الـblocks مكمّمة في الذاكرة ويستخدم مسار packed Q8.
مسار K-quant الحالي هو reference loader، مو native K-quant backend. الـloader يفك التكميم إلى f32 وقت التحميل، ويحتفظ بالـbuffers الموسعة، ثم يرسل العمل إلى تنفيذ f32 عام.
ما فيه K-specific matmul أو packed kernel حالياً في Ember. الملف ما زال Q4 أو Q6 على القرص، بس تمثيل الـdeployment داخل الذاكرة مو كذلك.
Q8_0:
GGUF Q8 blocks
→ compressed-resident weights
→ packed Q8 kernels
Q4_K_M / Q6_K today (reference path):
GGUF K-quant blocks
→ full f32 expansion
→ generic f32 execution
إذا بقي compressed file mapping موجوداً في الذاكرة، فقد يعكس RSS التمثيل الأصلي والـbuffers الموسعة معاً. عشان كذا رقم RSS الواحد يحتاج تفكيكاً إلى file-backed وanonymous قبل ما نعامله كتفسير كامل للإقامة في الذاكرة.
لاحقة GGUF أو اسم الملف ما تحدد وحدها ذاكرة العملية، تكلفة البداية، سرعة decode، الـworkspace المؤقت، سلوك الـkernels، أو مدة بقاء الـsource mapping. هذي قرارات يحددها الـloader وتخطيط الـtensors وسياسة الـdispatch والـbackend.
الـquantized checkpoint مجرد storage format إلى أن يحدد الـruntime كيف يجهزه ويشغله.
هذي هي النقطة المفاهيمية في المراجعة. قول إن الملف Q4 صحيح. بس ما يكفي لوصف الـdeployment كله.
llama.cpp هو الـexternal correctness and performance reference هنا. الـCPU backend المحسّن فيه يحافظ على أوزان K-quant مضغوطة في المسارات العادية، ويستخدم native quantized vector-dot kernels لـQ4_K وQ6_K وQ8_0، بدل الاحتفاظ بنسخة f32 كاملة من النموذج في التنفيذ العادي.
وهذا الفرق المهم في المقارنة: الـreference يحافظ على تمثيل low-bit أثناء التشغيل، بينما مسار K-quant البحثي الحالي في Ember يحافظ على التخزين المكمّم ثم يحوله إلى أوزان f32.
استخدم الـbenchmark نفس CPU affinity وإعداد الـthreads بين التهيئات. وهذا يحسّن المقارنة داخل الجدول، بس ما يحول التشغيل إلى دراسة واسعة للأجهزة.
المهمة التالية في Ember هي مقارنة التوسيع الكامل المبكر إلى f32، وبديل بذاكرة محدودة، وتنفيذ K-quant أصلي يحتفظ بالتمثيل المضغوط، مع llama.cpp كـexternal baseline.
المسارات المحسّنة لازم تحافظ أيضاً على دلالات activation tracing وcapture وpatching في Ember. الذاكرة الأقل أو السرعة الأعلى ما تكفي إذا تغيّر الشيء اللي تقيسه أداة البحث أو تتدخل فيه.
مخرجات الـdeployment benchmark المجمدة والـrunner
موجودة محلياً في
research/pilots/arabic_quantization_001/deployment_benchmark.{json,csv}
على فرع pilot-001 المحلي. هذا الفرع مو مساراً عاماً،
عشان كذا ما أضيف رابطاً يوحي بعكس ذلك.
سياق التنفيذ العام موجود في
src/quant_k.rs،
src/loader.rs،
src/residency.rs،
ومذكرتي packed-Q8
packed-q8-research-memo.md
وpacked-q8-lifecycle.md.
الملف قال Q4. الـruntime اختار f32. وتكلفة الـdeployment تبعت تمثيل الـruntime.