← voidwest    research notes
سياق الملاحظة

الإعدادات والتقديرات والخطوات التالية هنا تخص وقت كتابة الملاحظة. نحتفظ بنتائج التشغيل كما هي؛ تحديث الصياغة ما يعني إننا أعدنا التجربة أو إن حالة التنفيذ القديمة لسه هي الحالية.

الملف قال Q4. والـruntime قال f32.

خط أساس مجمّد لمسار K-quant loader الحالي ومسار التنفيذ الأصلي المفقود في Ember
محمد الثبيتي · 2026-08-01
Ember GGUF quantization CPU inference runtime systems Qwen LLaMA

الـ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-InstructQ8_01807 MB0.97 s40.61941 MBcompressed-resident
Qwen2.5-1.5B-InstructQ6_K1396 MB14.4 s2.58713 MBpersistent f32 expansion
Qwen2.5-1.5B-InstructQ4_K_M1066 MB13.0 s2.68712 MBpersistent f32 expansion
Llama-3.2-1BQ8_01260 MB2.03 s149.62685 MBcompressed-resident
Llama-3.2-1BQ6_K974 MB16.4 s2.96965 MBpersistent f32 expansion
Llama-3.2-1BQ4_K_M770 MB15.9 s3.26965 MBpersistent 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 قبل ما نعامله كتفسير كامل للإقامة في الذاكرة.

checkpoint quantization مو هي deployment quantization

لاحقة GGUF أو اسم الملف ما تحدد وحدها ذاكرة العملية، تكلفة البداية، سرعة decode، الـworkspace المؤقت، سلوك الـkernels، أو مدة بقاء الـsource mapping. هذي قرارات يحددها الـloader وتخطيط الـtensors وسياسة الـdispatch والـbackend.

الـquantized checkpoint مجرد storage format إلى أن يحدد الـruntime كيف يجهزه ويشغله.

هذي هي النقطة المفاهيمية في المراجعة. قول إن الملف Q4 صحيح. بس ما يكفي لوصف الـdeployment كله.

إيش اللي تثبته هذي المراجعة؟

إيش اللي ما تثبته؟

سياق reference implementation

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.