PagedAttention: ليه خدمة الـ LLM بتهدر معظم ذاكرة الـ GPU
يتطلب مستوى: محترف. المقال ده مفيد لو انت بتنشر نماذج لغوية في الإنتاج، وبتتعامل مع inference servers و GPU memory و batching.
لو بتخدم Llama أو أي LLM على GPU واحد وبتقدر تخدم 10 طلبات متزامنة بس، المشكلة غالبًا مش حجم الـ GPU. المشكلة إنك بتهدر 60 إلى 80% من ذاكرته على الفاضي. PagedAttention بتنزّل التهدير ده لأقل من 4% وترفع الإنتاجية حتى 24 ضعف على نفس الكارت. ركّز في السبب، لأنه مش زيادة في العتاد، ده تغيير في طريقة إدارة الذاكرة اتسرقت بالظبط من نظام التشغيل.
المشكلة باختصار: الـ KV Cache بياكل الذاكرة
لما الـ LLM بيولّد توكن جديد، بيحتاج يرجع لكل التوكنز اللي قبله. عشان ميعيدش حساب نفس الحاجة كل خطوة، بيخزّن نواتج وسيطة اسمها KV cache (مفاتيح وقيم طبقات الـ attention). الكاش ده بيكبر مع كل توكن جديد، وبيتحجز لكل طلب على حدة.
الرقم اللي بيوجع: في نموذج بحجم 13B، الـ KV cache بتاع توكن واحد بياخد حوالي 800 كيلوبايت. يعني تسلسل بطول 2048 توكن ممكن يوصل لـ 1.6 جيجابايت لطلب واحد. على A100 بسعة 40GB، ده بياكل جزء كبير من الذاكرة بعد ما النموذج نفسه ياخد نصيبه (المصدر: ورقة PagedAttention).
مثال يقرّب الفكرة قبل التشريح العلمي
تخيّل فندق بيحجز لكل نزيل جناح كامل من 20 أوضة، لأنه ممكن يجيب معاه 20 ضيف. أغلب النزلاء بييجوا لوحدهم، فـ 19 أوضة تفضل مقفولة وفاضية طول الإقامة. الفندق هيقولك مفيش أوضة فاضية وهو نص أوضه مقفول على الفاضي.
ده بالظبط اللي بيحصل في السيرفرات التقليدية. بتحجز لكل طلب مساحة متّصلة بحجم أطول إجابة ممكنة (مثلًا 2048 توكن)، حتى لو الإجابة طلعت 30 توكن. الباقي محجوز ومضيّع. النوع ده من الهدر اسمه internal fragmentation، وبيتجمع معاه external fragmentation وover-reservation (حجز مقدّم لتوكنز لسه ماتولّدتش).
الحل: هات فكرة الـ Virtual Memory من نظام التشغيل
نظام التشغيل حلّ نفس المشكلة من عشرات السنين. بدل ما يدّي كل برنامج كتلة ذاكرة متّصلة، بيقسّم الذاكرة لـ صفحات صغيرة ثابتة الحجم، وبيوزّعها على البرامج عند الحاجة، ويربطها بجدول صفحات. النتيجة: مفيش هدر يُذكر، وكل برنامج بيشوف ذاكرته كأنها متّصلة وهي في الحقيقة مبعثرة.
PagedAttention بتعمل نفس الحركة على الـ KV cache. بتقسّم كاش كل تسلسل لـ بلوكات، كل بلوك بيحمل عدد ثابت من التوكنز (الافتراضي 16). البلوكات دي مش لازم تكون متجاورة في الذاكرة الفعلية. جدول بلوكات بيربط التسلسل المنطقي بالبلوكات الفيزيائية المبعثرة. التهدير بينزل لجزء واحد بس: آخر بلوك ممكن يكون نص مليان، يعني أقل من 4% في المتوسط (المصدر: ورقة PagedAttention ومدوّنة vLLM).
وفوق ده، البلوكات اللي محتواها واحد (زي الـ prompt المشترك في عدة طلبات) ممكن تتشارك بنفس آلية الـ copy-on-write في نظام التشغيل. ده بيوفّر ذاكرة إضافية في سيناريوهات الـ parallel sampling.
الكود: شغّل vLLM وقيس الفرق بنفسك
vLLM هو المحرّك اللي طبّق PagedAttention. تشغيله سيرفر متوافق مع OpenAI API بيتعمل في أمر واحد: