المستوى المطلوب: متوسط — تحتاج فهمًا أساسيًا لـ Transformers و Self-Attention، مع خبرة عملية في تشغيل LLMs محليًا أو سحابيًا (vLLM، Ollama، أو HuggingFace Transformers).
لو حاولت تشغّل Llama 3 70B على A100 80GB بـ 32K context وجاتلك CUDA out of memory، المشكلة مش في وزن الموديل. وزن الموديل في FP16 بيبقى 140GB، ولو quantized لـ INT4 بينزل لـ 40GB. الباقي من ذاكرة الـ 80GB بيتأكل في حاجة اسمها KV Cache، وبتكبر خطيًا مع طول الـ context. كل توكن إضافي بياخد ذاكرة محسوبة بدقة، ولما توصل لـ 32K توكن الـ Cache لوحده ممكن يوصل 10GB على Llama 3 70B بـ GQA، أو 80GB لو الموديل بـ Multi-Head Attention الكاملة.
المشكلة باختصار
الـ Self-Attention في Transformer لازم لكل توكن جديد يحسب علاقاته بكل التوكنز اللي قبله. عشان متعيدش الحسابات في كل مرة، الموديل بيخزّن مصفوفتي Key و Value لكل التوكنز السابقة في الذاكرة. ده اللي اسمه KV Cache. النتيجة: كل توكن إضافي بيضيف للذاكرة بشكل ثابت، ومع contexts طويلة الـ Cache بيستهلك ذاكرة أكتر من الموديل نفسه.
مثال للمبتدئ: السكرتير اللي بيحفظ الاجتماع
تخيّل سكرتير في اجتماع طويل بيكتب محضر. كل ما حد يقول جملة، السكرتير محتاج يفهم علاقتها بكل جملة قيلت قبلها. لو في كل مرة هيرجع يقرأ المحضر كله من الأول، الاجتماع هيقعد ساعات بدون ما يخلص.
السكرتير الشاطر بيعمل حاجة تانية: لكل جملة، بيكتب جنبها "أهم نقطتين فيها" (ده الـ Key) و"ملخصها التنفيذي" (ده الـ Value). لما تيجي جملة جديدة، بيفتح ملخصاته السابقة بدل ما يعيد قراءة كل المحضر. ده الـ KV Cache بالظبط.
المشكلة: المحضر بيكبر، ودفتر الملخصات بيكبر معاه. لو الاجتماع طول 10 ساعات، دفتر الملخصات وحده بقى أتقل من المحضر الأصلي. ده اللي بيحصل لما توصل لـ 32K توكن: الـ KV Cache يتعدّى وزن الموديل نفسه.
التعريف العلمي الدقيق
في كل layer من الـ Transformer، الـ Self-Attention بيحسب ثلاث مصفوفات: Query (Q)، Key (K)، Value (V). للتوكن الجديد بيتم حساب Q جديد، لكن K و V لكل التوكنز السابقة لازم يكونوا موجودين في الذاكرة عشان عملية الـ attention dot product تشتغل بدون إعادة حساب.
الصيغة الرياضية لحجم الـ KV Cache:
KV_size = 2 × num_layers × seq_length × num_kv_heads × head_dim × precision_bytesالرقم 2 لأن عندك Key و Value. على Llama 3 70B (FP16):
- num_layers = 80
- num_kv_heads = 8 (بفضل Grouped Query Attention)
- head_dim = 128
- precision = 2 bytes (FP16)
الحساب لكل توكن: 2 × 80 × 8 × 128 × 2 = 327,680 بايت = 320 KB.
لـ 32,768 توكن: 320 KB × 32,768 = 10.24 GB.