Systems for ML2023متوسط11 دقيقة قراءة

إدارة الذاكرة بكفاءة لخدمة النماذج اللغوية الكبيرة باستخدام PagedAttention

Efficient Memory Management for Large Language Model Serving with PagedAttention

Kwon, W. · Li, Z. · Zhuang, S. · Sheng, Y. · Zheng, L. · Yu, C. H. · Gonzalez, J. E. · Zhang, H. · Stoica, I. — SOSP

المشكلة

عند تشغيل النماذج اللغوية الكبيرة لخدمة المستخدمين، يحتاج كل طلب إلى ذاكرة مؤقتة للمفاتيح والقيم (ذاكرة KV المؤقتة) تُخزَّن في ذاكرة GPU. هذه الذاكرة تكبر رمزًا بعد رمز أثناء التوليد، ولا يمكن معرفة حجمها النهائي مسبقًا. الأنظمة الحالية تحجز كتلة ذاكرة متصلة بحجم أقصى طول تسلسل ممكن، فيضيع 60–80% من ذاكرة GPU بسبب والخارجية والنسخ المكرر. هذا الهدر يحدّ مباشرةً من حجم الدُّفعة — وبالتالي من إنتاجية النظام.

الإسهام

تُقسِّم PagedAttention ذاكرة KV المؤقتة إلى كتل صغيرة ثابتة الحجم يمكن توزيعها في أي مكان من ذاكرة GPU، وتُربط هذه الكتل عبر جدول كتل — بنفس مبدأ في أنظمة التشغيل. هذا الأسلوب يقضي على التجزئة ويُتيح تخصيص الذاكرة عند الحاجة فقط. بنى المؤلفون فوق هذه الآلية نظام vLLM الذي يُحقّق هدرًا شبه معدوم ويدعم مشاركة كتل ذاكرة KV المؤقتة بأسلوب بين التسلسلات عند أخذ عيّنات متوازية أو إجراء بحث شعاعي. حقّق vLLM إنتاجية أعلى بمقدار 2–4 أضعاف مقارنةً بـ FasterTransformer وOrca عند مستوى الكُمون نفسه.

الأثر

صارت PagedAttention المعيار الصناعي لإدارة ذاكرة KV المؤقتة عند تشغيل النماذج اللغوية الكبيرة. هي اليوم مدير الذاكرة الافتراضي في vLLM، وتبنّتها TensorRT-LLM وHugging Face TGI ومعظم أُطر الكبرى. الورقة غيّرت نظرة المجال لخدمة النماذج اللغوية الكبيرة من مسألة تعلّم آلي بحتة إلى مسألة إدارة ذاكرة في المقام الأول، فاستفادت من عقود من خبرة أنظمة التشغيل ونقلتها إلى بنية التعلّم الآلي التحتية، مما فتح الباب لنشر هذه النماذج على نطاق واسع بجدوى اقتصادية.

تخيّل فندقًا يمنح كل نزيل جناحًا رئاسيًّا كاملًا — سواء أقام ليلة أو شهرًا — ولا يسمح لأحد باستخدام الغرف الفارغة. معظم الفندق يبقى مُظلمًا والمسافرون ينتظرون في الردهة.

الآن تخيّل أن الفندق انتقل إلى نظام مختلف: الغرف تُؤجَّر واحدة تلو الأخرى، ولا يُشترط أن تكون متجاورة، ودفتر في الاستقبال يربط كل نزيل بغرفه المتفرّقة. فجأة الفندق نفسه يستوعب أربعة أضعاف النزلاء.

هذه الورقة نقلت الفكرة ذاتها — الذاكرة الافتراضية ونظام الصفحات من أنظمة التشغيل — إلى ذاكرة التي تُخزِّن أثناء تشغيل النماذج اللغوية الكبيرة.

عنق الزجاجة: هدر ذاكرة KV المؤقتة

النماذج اللغوية الكبيرة تُولِّد النص رمزًا واحدًا في كل خطوة. وفي كل خطوة يحسب النموذج متجهات مفاتيح وقيم جديدة لآلية . وحتى لا يُعيد حساب هذه المتجهات من الصفر في كل مرة، يُخزّنها النظام فيما يُعرف بـذاكرة KV المؤقتة. لإعطائك فكرة عن الحجم: في نموذج بـ13 مليار معامل، قد تستهلك ذاكرة KV المؤقتة لطلب واحد فقط نحو 1.7 جيجابايت من ذاكرة وحدة معالجة الرسوميات.

المشكلة أن هذه الذاكرة تكبر تدريجيًّا — كتلة متجهات مع كل رمز جديد — ولا يُمكن معرفة حجمها النهائي إلا بعد انتهاء التوليد. الأنظمة الحالية تتعامل مع هذا بتخصيص منطقة ذاكرة متصلة مسبقًا بحجم أقصى طول تسلسل ممكن، وهو ما يُسبّب ثلاثة أنواع من الهدر.

أولًا التجزئة الداخلية: المنطقة المحجوزة غالبًا أكبر بكثير من الطول الفعلي للتسلسل، فيبقى ذيل كل تخصيص فارغًا دون فائدة. ثانيًا : مع وصول الطلبات ومغادرتها تتفتّت الذاكرة الحرة إلى قطع صغيرة متناثرة لا تكفي لتخصيصات جديدة. ثالثًا النسخ المُكرّر: تقنيات مثل أخذ العيّنات المتوازية و تُولِّد عدة مخرجات من المُدخَل نفسه، لكن كل نسخة تحتفظ بذاكرة KV مؤقتة كاملة خاصة بها — حتى الجزء المشترك من المُدخَل.

القياسات على أنظمة إنتاجية تُبيّن أن هذه الأنواع الثلاثة مجتمعة تستهلك 60–80% من ذاكرة KV المؤقتة. النتيجة المباشرة أن يتقلّص لأن عددًا أقل من الطلبات يتسع في الذاكرة، وهذا بدوره يُخفّض الإجمالية للنظام.

افتح في المختبر
اسحب شريط التحكم لترى مقدار هدر ذاكرة وحدة معالجة الرسوميات في ظل التخصيص المتصل. التجزئة الداخلية والتجزئة الخارجية والنسخ المكرر تلتهم معظم المساحة المتاحة لذاكرة KV المؤقتة.
تستيقظ التجربة عند وصولك…

الفكرة المحورية: ذاكرة افتراضية لذاكرة KV المؤقتة

هذه المشكلة ليست جديدة — أنظمة التشغيل واجهتها وحلّتها منذ عقود. في ستينيات القرن الماضي كانت البرامج تحتاج ذاكرة فعلية متصلة، وكانت النتيجة كوابيس التجزئة نفسها. الحل كان الذاكرة الافتراضية مع نظام الصفحات: كل برنامج يرى فضاء عناوين منطقيًّا متصلًا، لكنه في الواقع مُوزَّع على صفحات فعلية متفرّقة يربطها جدول صفحات. البرنامج لا يعرف شيئًا عن هذا التوزيع — نظام التشغيل يتكفّل بكل التفاصيل.

PagedAttention تنقل هذه الفكرة كما هي إلى عالم GPU. ذاكرة KV المؤقتة لكل طلب تُقسَّم إلى كتل منطقية ثابتة الحجم تُقابل الصفحات الافتراضية. هذه الكتل تُربط بـكتل فعلية في ذاكرة GPU عبر يُقابل جدول الصفحات. الكتل الفعلية لا يلزم أن تكون متجاورة، ومدير الكتل يُخصّصها عند الحاجة — واحدة تلو الأخرى — كلما وُلِّد رمز جديد.

الصورة البسيطة: كأنك تُعطي كل طلب دفترًا مرقَّم الصفحات. الطلب يكتب في الصفحة 1 ثم 2 ثم 3. لكن الصفحة 1 مُخزّنة على الرف أ، والصفحة 2 على الرف ز، والصفحة 3 على الرف ج. جدول الكتل هو بطاقة الفهرس: «صفحة 1 ← رف أ، صفحة 2 ← رف ز، صفحة 3 ← رف ج». الطلب لا يشعر بشيء من هذا التوزيع.

افتح في المختبر
انقر "ولِّد رمزًا" لتشاهد كيف تُربط الكتل المنطقية بكتل فعلية متناثرة عبر جدول الكتل. لاحظ أنه لا حاجة لتخصيص متصل.
تستيقظ التجربة عند وصولك…

خوارزمية PagedAttention

في الانتباه المعياري، تُحسب تركيبة موزونة من جميع متجهات القيم: الأوزان تأتي من الجداء النقطي بين وكل مفتاح. وفي التطبيق التقليدي تُخزَّن المفاتيح والقيم لكل تسلسل في مصفوفات موتّرة متصلة في الذاكرة.

ما تفعله PagedAttention هو تعديل نواة الانتباه بحيث تُجلب المفاتيح والقيم كتلةً بكتلة من مواقع فعلية غير متجاورة. لكل متجه استعلام، تمرّ النواة على جدول الكتل، وتجمع كتل المفاتيح والقيم المطلوبة، وتحسب الانتباه الجزئي داخل كل كتلة، ثم تُراكم النتائج. المُخرج الرياضي مطابق تمامًا للانتباه المعياري — الفرق الوحيد هو كيف تُرتَّب البيانات في الذاكرة.

لنُحدّد ذلك رياضيًّا: إذا كان حجم الكتلة BB رمزًا، فإن ذاكرة KV المؤقتة لتسلسل بطول TT تُقسَّم إلى T/B\lceil T/B \rceil كتلة. في كل رأس انتباه، المفاتيح في الكتلة jj تُشكِّل مصفوفة KjRB×dK_j \in \mathbb{R}^{B \times d} والقيم تُشكِّل VjRB×dV_j \in \mathbb{R}^{B \times d}، حيث dd هو بُعد الرأس. الانتباه لاستعلام واحد qq يُحسب كالتالي:

Attn(q)=j=1T/Besjmax(i=1BjesjisjmaxVji)j=1T/Besjmax(i=1Bjesjisjmax)wheresji=qKjid\text{Attn}(q) = \frac{\displaystyle\sum_{j=1}^{\lceil T/B \rceil} e^{s_j^{\max}} \cdot \left( \sum_{i=1}^{B_j} e^{s_{ji} - s_j^{\max}} \cdot V_{ji} \right)} {\displaystyle\sum_{j=1}^{\lceil T/B \rceil} e^{s_j^{\max}} \cdot \left( \sum_{i=1}^{B_j} e^{s_{ji} - s_j^{\max}} \right)} \quad\text{where}\quad s_{ji} = \frac{q^{\top} K_{ji}}{\sqrt{d}}
PagedAttention — انتباه على مستوى الكتل مع استقرار عددييُجرى الجداء النقطي بين الاستعلام qq والمفاتيح KjiK_{ji} في كل كتلة jj لإنتاج الدرجات sjis_{ji}. كل كتلة تحسب softmax محليًّا مستخدمةً أقصى درجة في الكتلة sjmaxs_j^{\max} لضمان الاستقرار العددي. ثم تُدمج النتائج عبر الكتل باستخدام خدعة log-sum-exp. النتيجة مطابقة رياضيًّا للانتباه المعياري لكن القراءة تتم من كتل فعلية غير متجاورة.
افتح في المختبر
تابع خطوات خوارزمية PagedAttention: شاهد الاستعلام يجمع المفاتيح من كتل فعلية متناثرة، ويحسب الانتباه الجزئي لكل كتلة، ثم يدمج النتائج.
تستيقظ التجربة عند وصولك…

vLLM: نظام الخدمة المبني على PagedAttention

vLLM نظام خدمة متكامل للنماذج اللغوية الكبيرة مبني على PagedAttention كأساس لإدارة الذاكرة. يتكوّن من ثلاث ركائز: مُجدوِل مركزي يُقرّر أيّ الطلبات تُعالَج في كل خطوة، ومدير لذاكرة KV المؤقتة (مدير الكتل) يتولى تخصيص الكتل الفعلية وتحريرها، ومجموعة من عمّال GPU تُنفّذ النموذج باستخدام نواة PagedAttention.

الميزة الأساسية في المُجدوِل أنه يُطبّق : بدلًا من انتظار انتهاء دُفعة كاملة قبل قبول طلبات جديدة، يُعيد تقييم المجموعة النشطة عند كل خطوة توليد. فالطلب الذي ينتهي مبكرًا يُحرّر كتله فورًا، ويمكن لطلب جديد أن يبدأ في الخطوة ذاتها. بهذه الطريقة يختفي وقت خمول GPU الذي كان يُعيق الدُّفعات الثابتة.

أما مدير الكتل فيحتفظ بقائمة الكتل الفعلية الحرة، ويتتبّع عدّادات مرجعية للكتل المشتركة، ويُنفّذ النسخ عند الكتابة حين تحتاج كتلة مشتركة إلى تعديل. كذلك يدعم : حين تشحّ ذاكرة GPU، يستطيع المُجدوِل إيقاف طلب أقل أولوية مؤقتًا إما بنقل كتله إلى ذاكرة المعالج المركزي أو بتحريرها لإعادة حسابها لاحقًا. هذا يضمن ألّا يتجمّد النظام أبدًا بسبب ضغط الذاكرة.

افتح في المختبر
شاهد مُجدوِل vLLM أثناء العمل: الطلبات تصل، وتُجمَّع في كل تكرار، وتنتهي في أوقات مختلفة، والطلبات الجديدة تملأ الفراغ فورًا.
تستيقظ التجربة عند وصولك…

مشاركة الذاكرة: النسخ عند الكتابة لفك الترميز المتوازي

كثير من أساليب التوليد تنتج عدة مخرجات من المُدخَل نفسه. في أخذ العيّنات المتوازية مثلًا، يُولِّد النموذج nn إكمالًا مستقلًّا من النص نفسه. وفي البحث الشُّعاعي، تتوسّع kk مسارات مُرشّحة بالتوازي في كل خطوة. في الحالتين توجد بادئة مشتركة: جميع التسلسلات تبدأ بالرموز ذاتها، وبالتالي تتطابق إدخالات ذاكرة KV المؤقتة لتلك المواضع.

بدون آلية مشاركة، سيُنسخ الجزء المشترك من ذاكرة KV المؤقتة مرة لكل تسلسل — هدر صريح. مع PagedAttention، جميع التسلسلات تُشير إلى الكتل الفعلية نفسها في البادئة المشتركة. حين يحتاج تسلسل ما إلى كتابة رمز جديد في كتلة كانت مشتركة، تُفعَّل آلية النسخ عند الكتابة: النظام ينسخ تلك الكتلة فقط إلى موقع جديد ويُحدِّث جدول كتل ذلك التسلسل — تمامًا كما يعمل نداء fork() في يونكس.

النتائج العملية: توفير 6–10% من الذاكرة في العيّنات المتوازية، و37–55% في البحث الشُّعاعي. ومع مجموعة بيانات ShareGPT التي تتميّز ببادئات مشتركة أطول، يصل التوفير إلى 66%.

افتح في المختبر
شاهد كيف يُشارك تفريع التسلسل الكتل الفعلية. حين يكتب تسلسل واحد رمزًا جديدًا، النسخ عند الكتابة يُخصّص نسخة خاصة فقط للكتلة المعدَّلة.
تستيقظ التجربة عند وصولك…

النتائج: تحسين الإنتاجية بمقدار 2–4 أضعاف

قارن المؤلفون vLLM بنظامين متقدّمين: FasterTransformer من إنفيديا وOrca (أول من طبّق الدُّفعات المستمرة). أُجريت التجارب على نماذج OPT بحجم 13 مليار و175 مليار معامل، مع مجموعات بيانات محادثات حقيقية (ShareGPT وAlpaca).

في وضع أخذ العيّنات الأساسي، حقّق vLLM إنتاجية أعلى بـ2–4 أضعاف من FasterTransformer وأعلى بـ1.7–2.7 ضعف من Orca، مع مماثل أو أقل. والملاحظ أن التحسين يزداد كلما طالت التسلسلات أو كبر النموذج، لأن ضغط الذاكرة يشتد في هذه الحالات. أما في البحث الشُّعاعي فكانت المكاسب أكبر بفضل آلية النسخ عند الكتابة.

قياسات الهدر أكّدت الصورة: الأنظمة القائمة أهدرت 60.4–80.3% من ذاكرة KV المؤقتة، بينما لم يتجاوز هدر vLLM نسبة 4%. الهدر الوحيد المتبقي هو التجزئة الداخلية في الكتلة الأخيرة من كل تسلسل، وحدّه الأقصى هو حجم الكتلة BB.

افتح في المختبر
قارن إنتاجية الخدمة عبر الأنظمة. بدِّل بين العيّنات الأساسية والبحث الشعاعي لترى كيف تُضخِّم مشاركة الذاكرة المكاسب.
تستيقظ التجربة عند وصولك…

من الداخل: البحث في جدول الكتل

نواة PagedAttention المبسَّطة — البحث في جدول الكتلpython

مبسَّط لإظهار الفكرة — ليس التنفيذ الحقيقي.

def paged_attention(query, key_cache, value_cache, block_table, block_size):
    """حساب الانتباه عبر كتل KV غير متجاورة."""
    d = query.shape[-1]
    num_blocks = len(block_table)

    # تجميع القيم الموزونة عبر الكتل
    output = zeros_like(query)
    total_exp = 0.0
    global_max = -inf

    for j in range(num_blocks):
        # ابحث عن الكتلة الفعلية من جدول الكتل
        phys_block = block_table[j]
        K_j = key_cache[phys_block]    # الشكل: [B, d]
        V_j = value_cache[phys_block]  # الشكل: [B, d]

        # احسب درجات الانتباه لهذه الكتلة
        scores = query @ K_j.T / sqrt(d)  # الشكل: [B]
        block_max = max(scores)

        # تجميع مستقر عدديًّا
        correction = exp(global_max - max(global_max, block_max))
        exp_scores = exp(scores - max(global_max, block_max))

        output = output * correction + exp_scores @ V_j
        total_exp = total_exp * correction + sum(exp_scores)
        global_max = max(global_max, block_max)

    return output / total_exp

الجدول الزمني: من نظام صفحات التشغيل إلى معيار خدمة النماذج اللغوية

  1. 1962

    اختراع الذاكرة الافتراضية

    حاسوب Atlas في مانشستر قدّم الذاكرة الافتراضية مع نظام الصفحات، حالًّا مشكلة تجزئة الذاكرة الفعلية للبرامج العامة.

  2. 2017

    نشر بنية المحوّل

    ورقة «الانتباه هو كل ما تحتاجه» قدّمت المحوّل، الذي يتطلب انتباهه متعدد الرؤوس تخزين أزواج المفاتيح والقيم لجميع الرموز السابقة.

  3. 2022

    Orca يُقدِّم الدُّفعات المستمرة

    اقترح Orca الجدولة على مستوى التكرار، مما يسمح لطلبات جديدة بالانضمام إلى الدُّفعة في كل خطوة فك ترميز. لكنه ظلّ يستخدم تخصيصًا متصلًا لذاكرة KV المؤقتة.

  4. 2023

    PagedAttention وvLLM (هذه الورقة)

    طبّق كوون وزملاؤه نظام صفحات على طراز أنظمة التشغيل لإدارة ذاكرة KV المؤقتة، محققين هدرًا شبه معدوم وتحسينًا في الإنتاجية بمقدار 2–4 أضعاف. نُشرت في SOSP 2023.

  5. 2024

    PagedAttention يُصبح المعيار الصناعي

    تبنّت TensorRT-LLM وHugging Face TGI وSGLang وMLC-LLM جميعها إدارة ذاكرة KV المؤقتة بنظام الصفحات. وأُضيف FlashAttention-2 كنواة حسابية تحتها.

  6. 2025

    vAttention وما بعدها

    اقترح vAttention إبقاء ذاكرة KV المؤقتة متصلة في الذاكرة الافتراضية مع استخدام نظام الصفحات عند الطلب للتخصيص الفعلي — مبقيًا على أنوية الانتباه المعيارية دون تعديل. نموذج الصفحات يستمر في التطور.

الإسهام الأعمق لـ PagedAttention ليس التسريع بمقدار 2–4 أضعاف — بل طريقة التفكير في المشكلة. قبل هذه الورقة كان تشغيل النماذج اللغوية الكبيرة يُعامَل كمسألة تعلّم آلي بحتة. بعدها أدرك المجال أن إدارة الذاكرة هي العنق الحقيقي، وأن عقودًا من أبحاث أنظمة التشغيل تُقدّم حلولًا جاهزة. هذا التحوّل في المنظور فتح الباب أمام جيل كامل من التحسينات: التخزين المؤقت للبادئات، وانتباه الجذر، وفصل مرحلتي المعالجة الأولية وفك الترميز، و — وكلها تقوم على تجريد الذاكرة المُصفّحة الذي قدّمته هذه الورقة.

المرجعKwon, Li, Zhuang, Sheng, Zheng, Yu, Gonzalez, Zhang, Stoica. Efficient Memory Management for Large Language Model Serving with PagedAttention. SOSP, 2023.

مصطلحات هذه الورقة