إعداد تشغيل نموذج 744B MoE دون توقف على أجهزة ماك بوك ومحطات العمل بذاكرة وصول عشوائي 32 جيجابايت
عند تشغيل نموذج MoE بحجم 744B مثل GLM-5.2 محلياً على محطة عمل عادية أو ماك بوك، فإن عنق الزجاجة يظهر في النطاق الترددي للتخزين وسياسة الذاكرة الافتراضية لنظام التشغيل قبل أن يظهر في سعة ذاكرة الفيديو (VRAM). يقوم محرك الاستدلال الخفيف المكتوب بلغة C والمعروف باسم JustVugg (عبر colibrì) بتثبيت الطبقة المقيمة بحجم 17B فقط (حوالي 9.9 GiB بناءً على int4) في الذاكرة العشوائية (RAM)، بينما يبث أوزان الخبراء الموجهة المقسمة إلى 21,504 جزءاً (~370 جيجابايت) في الوقت الفعلي من قرص SSD خارجي على مستوى الرمز (token).
تكمن المشكلة في أنه إذا تم تشغيل النظام بإعداداته الافتراضية، فس يحدث تبادل في الذاكرة (swap thrashing) أو سيقوم نظام الإنهاء OOM Killer الخاص بالنواة بإنهاء العملية قسراً. لكي لا تتوقف عملية توليد الرموز، يجب تعديل كل شيء يدويًا، بدءًا من علامات الترجمة (compile flags) وصولاً إلى طوابير إدخال وإخراج NVMe ومعلمات النواة.
علامات الترجمة حسب البنية وإعدادات مجموعة تعليمات المتجهات
محرك الحساب الأساسي لـ colibrì هو ملف C11 واحد يحتوي على حوالي 1,300 سطر دون تبعيات خارجية. تختلف إنتاجية عمليات ضرب المصفوفات اعتماداً على تعليمات متجهات SIMD التي يستخدمها المترجم. بدلاً من بناء النظام بالاعتماد على -O2 الافتراضي، يجب تحديد تعليمات الامتداد الخاصة بعمليات الأعداد الصحيحة لوحدة المعالجة المركزية المستهدفة مباشرة.
بناء بيئة التطوير والترجمة
في بيئة x86_64 Linux، يتم تفعيل AVX-512 VNNI باستخدام GCC 12 أو أحدث، بينما يتم ربط NEON DotProduct في أجهزة Apple Silicon عبر Clang.
بالنسبة لتوزيعات Ubuntu و Debian، قم بتثبيت أدوات البناء أولاً:
`bash
sudo apt-get install gcc-12 libomp-dev
`
في بيئة macOS، يتم الحصول على وقت تشغيل OpenMP عبر Homebrew:
`bash
brew install libomp
`
على أجهزة x86_64 Linux، يتم بناء المشروع مع استهداف تعليمات AVX-512 VNNI:
`bash
gcc -O3 -march=native -mtune=native
-mavx512f -mavx512bw -mavx512vnni -mavx512dq
-fopenmp -funroll-loops -ffast-math
-o colibri_engine colibri_glm52.c -lm
`
في بيئة Apple Silicon (سلسلة M)، يتم الترجمة عن طريق توجيه مسار المكتبة مباشرة:
`bash
clang -O3 -mcpu=native
-march=armv8.4-a+dotprod+fp16
-Xpreprocessor -fopenmp
-I/opt/homebrew/opt/libomp/include
-L/opt/homebrew/opt/libomp/lib -lomp
-o colibri_engine colibri_glm52.c -lm
`
إذا ظهرت تحذيرات بناء تتعلق بالهياكل (structs)، أضف علامة -std=c11 لحل المشكلة.
| المنصة |
المترجم |
علامات تعليمات المتجهات |
التوازي باستخدام الخيوط (Threads) |
| x86_64 (Linux) |
GCC 12+ |
-mavx512vnni -mavx512bw |
-fopenmp |
| ARM64 (macOS) |
Apple Clang |
-march=armv8.4-a+dotprod |
-Xpreprocessor -fopenmp |
| x86 القديمة |
GCC / Clang |
-mavx2 -mfma |
-fopenmp |
مقاييس أداء SSD الخارجي وتوسيع طابير الإدخال والإخراج غير المتزامن
تحدد زمن انتقال فك التشفير في colibrì من خلال سرعة القراءة العشوائية للقرص بحجم 1 ميجابايت. يتم تقسيم ملف معلمة خبير التوجيه لنموذج GLM-5.2 إلى أحجام تقارب 19 ميجابايت لكل منها، وفي كل مرة يتم فيها إنشاء رمز، تقرأ خيوط الإدخال والإخراج غير المتزامنة القطع المطلوبة من قرص SSD.
قياس النطاق الترددي لقراءة التخزين عبر fio
قم بتثبيت أداة fio عبر مدير الحزم:
`bash
Linux
sudo apt-get install fio
macOS
brew install fio
`
قم بقياس النطاق الترددي للقراءة العشوائية باستخدام حجم كتلة 1 ميجابايت والإدخال والإخراج المباشر (Direct I/O):
`bash
fio --name=colibri_stream_bench
--filename=/Volumes/ExternalSSD/glm52_test.tmp
--size=10G
--rw=randread
--bs=1m
--iodepth=32
--numjobs=4
--ioengine=posixaio
--direct=1
--group_reporting
--runtime=60
`
تحافظ واجهات Thunderbolt 4 أو USB4 (40 جيجابت في الثانية) على نطاق ترددي فعلي يتراوح بين 2,800 إلى 3,200 ميجابايت/ثانية وتوفر سرعة فك تشفير تتراوح بين 0.08 إلى 0.10 رمز/ثانية. في المقابل، إذا قمت بتوصيل محرك الأقراص الخارجي بمنفذ USB 3.2 Gen2 (10 جيجابت في الثانية) والذي يقتصر النطاق الترددي فيه على 900 إلى 1,050 ميجابايت/ثانية، فس يستغرق استخراج 100 رمز أكثر من 80 دقيقة.
`
+-------------------------------------------------------------------------+
| colibrì C Inference Engine |
| +--------------------------+ +-------------------------------------+ |
| | Dense Weights (9.9 GiB) | | Multi-Token Prediction (MTP) Head |
| | Resident in RAM (mlock) | | int8 Quantized |
| +------------+-------------+ +------------------+------------------+ |
+---------------+-----------------------------------+---------------------+
| |
v v
+-------------------------------------------------------------------------+
| Memory & Storage I/O Layer |
| +--------------------------+ +-------------------------------------+ |
| | Async Expert Readahead | | 21,504 Routed Experts (370 GB) |
| | I/O Queue Depth 3264 | | Streamed from NVMe SSD via mmap |
| +--------------------------+ +-------------------------------------+ |
+-------------------------------------------------------------------------+
`
من خلال زيادة عمق طابور الإدخال والإخراج (iodepth) للتحميل المسبق غير المتزامن (Async Expert Readahead) إلى مستوى 32~64، يمكنك الاستفادة الكاملة من القنوات المتوازية لوحدة تحكم NVMe لتقليل زمن انتظار القرص.
إعدادات الذاكرة الافتراضية للنواة والوقاية من OOM
على نظام بذاكرة وصول عشوائي (RAM) سعة 32 جيجابايت، عندما يتم تحميل الأوزان المقيمة بحجم 9.9 GiB، وذاكرة KV Cache، وذاكرة التخزين المؤقت لصفحات نظام الملفات في نفس الوقت، يحدث تنافس في ذاكرة النواة. في إعدادات لينكس الافتراضية، يتم حظر تخصيص مساحة العنوان الظاهري عند استدعاء mmap بحجم 370 جيجابايت، أو يقوم برنامج OOM Killer بإيقاف المحرك.
تطبيق معلمات نواة لينكس
أنشئ الملف /etc/sysctl.d/99-colibri-memory.conf وأدخل المحتوى أدناه:
`ini
منع طرد الذاكرة المقيمة إلى مساحة التبادل في القرص
vm.swappiness = 1
السماح بالإفراط في تخصيص الذاكرة الافتراضية
pm.overcommit_memory = 1
تأمين مساحة ذاكرة مخفية للطوارئ (2 جيجابايت)
vm.min_free_kbytes = 2097152
زيادة نسبة الاحتفاظ بذاكرة التخزين المؤقت لملفات القرص
vm.vfs_cache_pressure = 50
توسيع الحد الأقصى لعدد تعيينات mmap
vm.max_map_count = 524288
`
بعد الحفظ، قم تطبيق المعلمات فوراً:
`bash
sudo sysctl --system
`
قم بإزالة حدود قفل الذاكرة في جلسة الطرفية للسماح باستدعاءات mlock() للطبقات المقيمة:
`bash
ulimit -l unlimited
`
| المعلمة |
القيمة الافتراضية |
القيمة الموصى بها |
الغرض من الإعداد |
| vm.swappiness |
60 |
1 |
منع دفع الأوزان بحجم 9.9 GiB المثبتة في RAM إلى منطقة التبادل |
| vm.overcommit_memory |
0 |
1 |
منع رفض ذاكرة النواة عند تعيين mmap بحجم 370 جيجابايت |
| vm.vfs_cache_pressure |
100 |
50 |
إطالة عمر ذاكرة التخزين المؤقت للملفات لإعادة استخدام أوزان الخبراء المستدعية بشكل متكرر |
| vm.max_map_count |
65530 |
524288 |
إلغاء قفل حد تعيين 21,504 ملف معلمات |
| ulimit -l |
64 (كيلوبايت) |
unlimited |
منح صلاحية تثبيت الذاكرة الفيزيائية (mlock) لطبقات Dense |
في بيئة macOS، عندما تنفد الذاكرة المتاحة، يقوم dynamic_pager بضغط الذاكرة في الخلفية مما يستهلك موارد وحدة المعالجة المركزية. يجب إغلاق التطبيقات عالية الاستهلاك قبل التشغيل لمنع الدخول إلى محرك الضغط.
تثبيت خيوط وحدة المعالجة المركزية وتكوين نص التشغيل
تقوم عملية فك تشفير MoE بالوصول المستمر إلى ذاكرة التخزين المؤقت لوحدة المعالجة المركزية وناقل الذاكرة. إذا تم اختيار عقدة NUMA بشكل خاطئ في محطة عمل ذات مقابس متعددة، فس تنخفض سرعة توليد الرموز إلى النصف بسبب عنق زجاجة ناقل الربط البيني.
كتابة نص التشغيل الموحد
تحقق أولاً من رقم عقدة وحدة المعالجة المركزية الفيزيائية المرتبطة مباشرة بوحدة تحكم NVMe الخارجية باستخدام أمر numactl --hardware. بعد ذلك، اكتب نصاً برمجياً للصدفة (shell script) يتجنب التخصيص المزدوج للمعالجة المتعددة الفائقة (Hyper-Threading) ويقصر الخيوط على النوى الفيزيائية فقط.
`bash
#!/usr/bin/env bash
set -euo pipefail
1. إعدادات الذاكرة الافتراضية للنواة
sudo sysctl -w vm.swappiness=1 > /dev/null
sudo sysctl -w vm.overcommit_memory=1 > /dev/null
sudo sysctl -w vm.max_map_count=524288 > /dev/null
sudo sysctl -w vm.vfs_cache_pressure=50 > /dev/null
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null
2. إلغاء قفل حد قفل الذاكرة
ulimit -l unlimited
3. ربط خيوط OpenMP بالنوى الفيزيائية
export OMP_NUM_THREADS=16
export OMP_PROC_BIND=TRUE
export OMP_PLACES=cores
4. تشغيل الربط بعقدة NUMA 0
ENGINE_BIN="./colibri_engine"
MODEL_PATH="/mnt/nvme_ext/GLM-5.2-colibri-int4-g64-with-int8-mtp"
exec numactl --physcpubind=0-15 --membind=0
"${ENGINE_BIN}"
--model "${MODEL_PATH}"
--threads "${OMP_NUM_THREADS}"
`
على أجهزة ماك بوك المزودة بمعالجات Apple Silicon، يجب منع برنامج مراقبة جودة الخدمة (QoS) في macOS من نقل خيوط العامل إلى النوى الفعالة (E-Core). قم بتشغيل البرنامج عن طريق رفع الأولوية قسراً:
`bash
sudo nice -n -20 taskpolicy -c default ./colibri_engine --model /Volumes/SSD/glm52_i4
`
بمجرد الانتهاء من هذه الإعدادات الأربعة، يمكنك تشغيل نموذج 744B MoE بثبات عبر طريقة البث من القرص المحلي دون أعطال نفاد الذاكرة (OOM)، حتى على محطة عمل أو ماك بوك بذاكرة وصول عشوائي 32 جيجابايت.