يتطلب مستوى: محترف. الشرح ده مبني على فرضية إنك بتخدم نموذج LLM مفتوح المصدر (زي Llama أو Qwen) على GPU واحد أو أكتر، وبتشوف الـ latency والـ throughput في بيئة إنتاج. لو انت مستخدم API خارجي بس، الجزء التطبيقي مش هيلزمك، بس المفهوم هيفيدك في فهم فاتورتك.
ليه سيرفر الـ LLM بيخنق عند 10 مستخدمين، وإزاي PagedAttention يحل المشكلة
تقدر تخدم من 2 لـ 24 ضعف عدد المستخدمين على نفس كرت الشاشة، من غير ما تغيّر النموذج ولا تشتري GPU أقوى. المفتاح هو طريقة إدارة الذاكرة اللي اسمها PagedAttention.
المشكلة باختصار
عندك سيرفر Llama-3 8B على كرت A100 بذاكرة 80 جيجا. النموذج نفسه بياخد حوالي 16 جيجا. المفروض يفضل 64 جيجا للمستخدمين. ومع ذلك السيرفر بيرمي "out of memory" عند المستخدم رقم 12، وكرت الشاشة مؤشره بيقول إنه نصه فاضي. ده مش عطل في الدرايفر. ده هدر في الـ KV Cache.
ما هو الـ KV Cache؟ المفهوم بمثال بسيط الأول
تخيّل إنك بتقرا كتاب بصوت عالي لصاحبك، وكل كلمة جديدة بتنطقها لازم تفتكر كل الكلمات اللي فاتت عشان الجملة تطلع مترابطة. لو في كل كلمة رجعت قريت الصفحة من أولها، هتاخد ساعة في فقرة. الحل الطبيعي: تكتب ملخص جنبك بالكلمات اللي عدّت، فتبص عليه بدل ما تعيد القراءة. الملخص ده هو الـ KV Cache.
علميًا: النموذج بيولّد التوكن التالي بناءً على كل التوكنز السابقة عبر آلية الـ attention. من غير كاش، توليد كل توكن جديد بيتطلب إعادة حساب مفاتيح (Keys) وقيم (Values) كل التوكنز السابقة. الـ KV Cache بيخزّن الـ K والـ V المحسوبين لكل توكن مرة واحدة، فبيحوّل التعقيد من تربيعي لخطي في كل خطوة. المقابل: استهلاك ذاكرة بيكبر مع طول السياق وعدد الطلبات المتوازية.
ليه بيتهدر 60–80% من الذاكرة
الأنظمة التقليدية (قبل vLLM) كانت بتحجز للـ KV Cache بتاع كل طلب كتلة ذاكرة متصلة بحجم أقصى طول ممكن للسياق، من أول لحظة. يعني لو الحد الأقصى 2048 توكن، والطلب استخدم 100 توكن بس، الـ 1948 الباقيين محجوزين وفاضيين ومش متاحين لأي طلب تاني. ده اسمه التجزئة الداخلية (internal fragmentation).
ابحاث فريق vLLM من جامعة بيركلي (Kwon et al., SOSP 2023) قاست إن الأنظمة دي كانت بتستغل فعليًا بين 20% و38% بس من الذاكرة المحجوزة للكاش. الباقي، 60–80%، بيضيع على الحجز المبكر والتجزئة. ده السبب المباشر إن سيرفرك بيخنق بدري رغم إن الذاكرة "مش مليانة".
الحل: PagedAttention — استعارة من نظام التشغيل
PagedAttention بياخد فكرة قديمة من أنظمة التشغيل: الذاكرة الافتراضية والـ paging. بدل ما يحجز كتلة متصلة كبيرة، بيقسّم الـ KV Cache لكتل صغيرة ثابتة الحجم (blocks/pages)، وبيخصّص الكتلة وقت ما الطلب يحتاجها فعليًا مش قبلها. الكتل مش لازم تكون متجاورة في الذاكرة، فبيختفي الهدر الناتج عن التجزئة، وينزل لأقل من 4%.
عمليًا انت مش هتكتب ده بإيدك. بتستخدم vLLM اللي مطبّق PagedAttention جوّه. الإعداد قابل للنسخ:
# تثبيت وتشغيل سيرفر متوافق مع OpenAI API
pip install vllm
vllm serve meta-llama/Meta-Llama-3-8B-Instruct \
--gpu-memory-utilization 0.90 \
--max-model-len 8192 \
--enable-prefix-caching \
--max-num-seqs 256
الأسطر المهمة: --gpu-memory-utilization 0.90 بيقول لـ vLLM ياخد 90% من الذاكرة كـ KV Cache pool مشترك بين كل الطلبات. --enable-prefix-caching بيعيد استخدام الكتل لو كذا طلب بيشتركوا في نفس البداية (زي نفس الـ system prompt). --max-num-seqs بيحدد أقصى عدد طلبات متوازية في الدفعة.
الأرقام: قد إيه بيفرق فعلًا
على نفس كرت الشاشة، وبنفس مستوى الـ latency، النتايج المقاسة بتتراكم على تلات مستويات:
- الدفعات المستمرة (continuous batching) لوحدها بتوصّل لحوالي 5 أضعاف مقارنة بحلقة PyTorch ساذجة، لأنها بتضيف طلبات جديدة للدفعة فور ما يخلّص أي طلب بدل ما تستنى الدفعة كلها.
- إضافة PagedAttention بتضاعف الاستفادة من الذاكرة، فبيقفز عدد الطلبات المتوازية والإنتاجية توصل حوالي 14 ضعف.
- مع prefix caching فوقهم، الرقم الرسمي من إطلاق vLLM بيوصل حتى 23–24 ضعف على مسارات تمثيلية.
ورقة vLLM الأصلية بتذكر تحسّن إنتاجية 2 لـ 4 أضعاف مقارنة بأنظمة متقدمة زي FasterTransformer وOrca عند نفس الـ latency. الرقم 24× بيكون مقارنة بالتنفيذ الساذج مش بالأنظمة المحسّنة. خلّي بالك إن الأرقام دي تعتمد على شكل الحِمل: طلبات قصيرة كتير بتستفيد أكتر من طلبات طويلة قليلة.
الـ trade-offs اللي لازم تعرفها
مفيش حل ببلاش. لمّا تعلّي --gpu-memory-utilization لـ 0.95 عشان تكسب سعة كاش أكبر، بتقلل الهامش المتاح لعمليات الـ CUDA المؤقتة، فممكن تقابل OOM تحت الضغط أو مع سياقات طويلة مفاجئة. المكسب: طلبات متوازية أكتر. الخسارة: هامش أمان أقل. القاعدة العملية: ابدأ بـ 0.90 وراقب الـ OOM قبل ما تعلّيه.
الـ prefix caching بيكسّبك سرعة كبيرة لو طلباتك بتشترك في بادئة طويلة، لكنه بياكل من الـ pool. لو طلباتك متنوعة وبلا بادئة مشتركة، بتدفع تكلفة إدارة من غير مكسب يُذكر.
متى لا تستخدم هذه الطريقة
لو عندك مستخدم واحد أو اتنين بس (batch size = 1)، مكسب PagedAttention بيبقى هامشي؛ الفايدة الأساسية بتظهر مع التوازي العالي. لو بتخدم عبر API خارجي (OpenAI أو Anthropic)، الموضوع ده متكفّل بيه من عندهم ومش شغلك. ولو الـ workload بتاعك offline batch (مش زمن حقيقي)، ممكن تكتفي بإعدادات throughput بسيطة من غير ما تدخل في ضبط الذاكرة الدقيق.
الخطوة التالية
شغّل سيرفرك الحالي وابعت 100 طلب متوازي بـ ab أو vllm bench، وسجّل الـ throughput والـ P95 latency. بعدين علّي --gpu-memory-utilization من القيمة الحالية لـ 0.90 وفعّل --enable-prefix-caching، وأعد نفس القياس. لو الإنتاجية اتحسّنت والـ latency ثابت، انت كسبت سعة مجانية. لو قابلت OOM، نزّل القيمة 0.05 وكرّر.
المصادر
- Kwon et al., "Efficient Memory Management for Large Language Model Serving with PagedAttention" (vLLM), SOSP 2023 — الورقة الأصلية اللي قاست الهدر 60–80% ونزّلته لأقل من 4%.
- vLLM Documentation — أوامر
vllm serve، ضبطgpu-memory-utilization، وprefix caching. - معايير إنتاج على كروت H100 (2025–2026) لتقدير مكاسب الدفعات المستمرة وchunked prefill التراكمية.