مستوى المقال: متوسط — مفترض إنك تعرف يعني إيه LLM، ركّبت موديل من Hugging Face قبل كده، وعندك فكرة أساسية عن FP16 و GPU memory.
لو حاولت تشغّل Llama 3.1 70B على RTX 4090 بـ 24GB ذاكرة وطلع معاك خطأ CUDA out of memory، المشكلة مش عتاد ضعيف. الموديل ده بـ FP16 بياخد 140GB. الحل اسمه Quantization، وبيخلّيه يشتغل في 35GB بدقة شبه مطابقة. المقال ده هيوريك إزاي بالظبط.
Quantization: السلاح اللي بيخلّي LLMs الكبيرة تشتغل على عتاد متاح
المشكلة باختصار
كل موديل LLM عبارة عن مليارات الأرقام (الأوزان أو weights) محفوظة في الذاكرة. الـ default إن كل رقم محفوظ في 16 bit (نوع float16 أو bfloat16). يعني كل باراميتر بياخد 2 بايت.
- Llama 3.1 70B بـ FP16: 70 مليار × 2 بايت = 140GB
- DeepSeek V3 671B بـ FP16: 671 مليار × 2 بايت = 1.34TB
- Mistral 7B بـ FP16: 7 مليار × 2 بايت = 14GB
السيرفر اللي معاه H100 80GB واحد مش هيقدر يحمّل 70B أصلاً. ولو عندك consumer GPU، 7B هي السقف. Quantization بيغيّر المعادلة دي.
مثال للمبتدئ: ضغط الصور
تخيّل عندك ألبوم 10,000 صورة بحجم 4K، كل واحدة 8MB. الألبوم بياخد 80GB. لو ضغطتهم بصيغة JPEG بجودة 85%، الحجم نزل لـ 12GB، بس عينك مش هتفرّق بين الصورة الأصلية والمضغوطة لو فتحتها على الموبايل.
Quantization بيعمل نفس الفكرة بالظبط. كل وزن في الموديل بدل ما يكون رقم عشري دقيق محفوظ في 16 bit، بيتحوّل لرقم صحيح صغير محفوظ في 4 bits. الفرق في الدقة موجود بس صغير لدرجة إن الموديل بيرد بنفس الجودة تقريبًا على معظم المهام.
الفرق المهم: ضغط الصور عشان تخزّنها، لكن Quantization عشان تشغّل الموديل أسرع وعلى عتاد أصغر — مش بس توفير ديسك.
التعريف العلمي الدقيق
Quantization عملية رياضية بتاخد وزن من نطاق متصل (continuous) مخزّن في FP16، وتطبّقه على نطاق منفصل (discrete) محدود بعدد bits أصغر. المعادلة الأساسية للـ uniform quantization:
# المعادلة في صورتها الأبسط
scale = (max_weight - min_weight) / (2**bits - 1)
zero_point = round(-min_weight / scale)
quantized = round(weight / scale) + zero_point
# للاسترجاع وقت الـ inference
dequantized = (quantized - zero_point) * scale
كل block من الأوزان (مثلاً 128 وزن متجاورين) بياخد قيم scale و zero_point خاصة بيه. ده اسمه Group-wise Quantization وبيقلّل الخسارة في الدقة.