
في الجزء السابق من سلسلتنا حول أداء LLM، نظرنا في الاختلافات بين مرحلتي التعبئة المسبقة وفك التشفير أثناء إنشاء الرمز المميز. باختصار: لرمز الإخراج الأول (خطوة التعبئة المسبقة)، يجب معالجة الموجه بالكامل، والذي يمكن موازنته بكفاءة ويمكن أن يشبع استخدام وحدة معالجة الرسومات. لجميع الرموز المميزة للإخراج لاحقًا (خطوات فك التشفير)، يلزم معالجة رمز مميز إضافي واحد فقط، وهو أمر أقل استهلاكًا للحوسبة ولكن يجب إجراؤه بشكل تسلسلي. عندما تتم معالجة العديد من الطلبات بشكل متزامن، فإن أي إستراتيجية تهدف إلى زمن استجابة منخفض تحتاج إلى تشغيل خطوات التعبئة المسبقة للطلبات الواردة حديثًا بينما لا تزال خطوات فك التشفير للطلبات المجدولة مسبقًا مستمرة. وبالتالي، تتطلب المعالجة المتزامنة للطلبات الجديدة وكذلك الطلبات الجارية تحقيق توازن دقيق بين مرحلتي التعبئة المسبقة وفك التشفير، مما يمثل تحديين رئيسيين سنناقشهما فيما يلي. إحداهما قضية قابلة للحل بسهولة، في حين أن الأخرى تشكل عيبًا أكثر جوهرية.
التحدي الأبسط: المطالبات الطويلة تحجب قائمة الانتظار
نظرًا لأن خطوات فك التشفير الفردية لا تتطلب حوسبة مكثفة، فيمكن زيادة الإنتاجية عن طريق تجميع عمليات فك التشفير لطلبات متعددة. ومع ذلك، بالنسبة للتعبئة المسبقة، لا يعمل هذا الأسلوب. نظرًا للمعالجة المتوازية لجميع الرموز المميزة للمطالبة، يمكن لخطوة تعبئة مسبقة واحدة أن تشبع استخدام وحدة معالجة الرسومات بالفعل. وبالتالي، في استراتيجية التعبئة المسبقة المقسمة الافتراضية لـ vLLM، تحتوي كل قطعة تعبئة مسبقة فقط على الرموز المميزة لطلب واحد. يجب أن ينتظر الطلب التالي في السطر حتى تنتهي مرحلة التعبئة المسبقة السابقة قبل أن تبدأ مرحلة التعبئة المسبقة الخاصة به.
تشكل هذه الجدولة التسلسلية لأجزاء الملء المسبق للطلبات المختلفة تحديًا: عندما تتم جدولة طلب ذو مطالبة طويلة جدًا للملء المسبق، يجب على أي طلب لاحق الانتظار لمدة الملء المسبق الطويل قبل بدء معالجته؛ مطالبة طويلة تحظر قائمة انتظار التعبئة المسبقة. (لاحظ أن المعالجة التسلسلية لعمليات التعبئة المسبقة هي السمة الافتراضية لـ مقسمة التعبئة المسبقة ويظهر فقط عندما يكون هناك بالفعل طلب متزامن في مرحلة فك التشفير الخاصة به؛ ومن هنا جاء اسم “الملء المسبق الجزئي”.)

لسوء الحظ، لا يمكن حل هذا التحدي من خلال جدولة الأولوية من جانب vLLM (راجع المقالة الأولى من هذه السلسلة) ولا من خلال جدولة المنبع الأكثر تطورًا. والسبب هو أنه يمكن جدولة الموجه الطويل قبل وجود أي طلبات لاحقة، لذلك لا يوجد شيء يمكن للمجدول انتظاره.
طلب-التعبئة المسبقة الموازية
سيكون الحل المباشر هو معالجة أجزاء التعبئة المسبقة للطلبات المختلفة بالتوازي. قد لا يكون هذا محسّنًا للموارد، حيث يمكن لقطع التعبئة المسبقة ذات الطلب الواحد أن تشبع بالفعل قوة الحوسبة. من المحتمل أن تؤدي أي تعبئة مسبقة إضافية يتم تنفيذها بالتوازي إلى إطالة مدة التعبئة المسبقة قليلاً وإبطاء أي طلبات فك تشفير متزامنة بشكل أكبر. سيكون هذا مقبولاً إذا أدى إلى تقليل زمن الوصول للطلبات القصيرة وجعل النظام يبدو أكثر استجابة. ومع ذلك، يفشل هذا الأسلوب عندما يكون للطلب التالي في السطر مطالبة طويلة أيضًا. في مثل هذه الحالة، سيتم تجميع عمليتي تعبئة مسبقة مكثفة للحوسبة معًا مما يؤدي إلى تباطؤ شديد.
في أحد تحديثات vLLM الأخيرة، تم تنفيذ إستراتيجية محسنة: فهي تسمح بالملء المسبق المتوازي للطلبات المختلفة ولكن مع حد لعدد الطلبات الطويلة التي تتم معالجتها بشكل متزامن. قد يؤدي تكوين المثال إلى تمكين تجميع عمليات التعبئة المسبقة لأربعة طلبات، ولكن واحدًا منها فقط قد يكون أطول من 10000 رمز مميز للمطالبة. مع هذا التكوين، يظل سلوك الطلبات الأطول هو نفسه كما كان من قبل: تتم معالجة المطالبات الطويلة بالتسلسل. ومع ذلك، لم تعد الطلبات القصيرة بحاجة إلى الانتظار حتى تنتهي عملية التعبئة المسبقة الطويلة للطلب السابق؛ يمكن للمطالبات القصيرة أن تأخذ مسارًا سريعًا. لم تعد هذه الطلبات تعاني من فترات الانتظار الطويلة وتظهر أقل من ذلك بكثير الوقت لأول رمز مميز المقاييس.
وبطبيعة الحال، يمكن لعمليات التعبئة المسبقة الموازية فقط تقليل أوقات الانتظار؛ ولكن الوقت لكل رمز الإخراج يبقى مرتفعا أثناء عملية التعبئة المسبقة الطويلة المتزامنة. في هذا الصدد، تُظهر عمليات التعبئة المسبقة المتوازية للطلب نفس السلوك والأداء مثل التعبئة المسبقة المقسمة القياسية، فقط مع وقت أقصر لأول رمز مميز.

الخلل الأساسي: تباطؤ إنشاء الرمز المميز بسبب عمليات التعبئة المسبقة المتوازية
عند تنفيذ التعبئة المسبقة وفك التشفير لطلبات مختلفة في نفس عملية GPU، يستغرق الأمر وقتًا أطول من خطوة فك التشفير المعزولة. يواجه المستخدم انقطاعًا أو تباطؤًا في إنشاء الرمز المميز من خلال طلب لاحق. بخاصة، يكفي طلب واحد بمطالبة طويلة لإبطاء جميع الطلبات المجدولة مسبقًا الموجودة بالفعل في مراحل فك التشفير الخاصة بها.
يعد هذا عيبًا أساسيًا في المعالجة المتزامنة للملء المسبق وفك التشفير على نفس وحدات معالجة الرسومات، لأنه لا يوجد الكثير مما يمكنك فعله:
- (أ) يمكنك ذلك معاقبة المطالبات الطويلة والسماح لهم بالانتظار (على سبيل المثال، حتى يتم الانتهاء من جميع الطلبات القصيرة ذات الأولوية العالية). ويأتي هذا على حساب زيادة زمن الاستجابة لتلك الطلبات، ولا يصلح السبب الجذري: على وجه الخصوص، عند تمكين عمليات التعبئة المسبقة المتوازية للطلب، يؤثر التباطؤ أيضًا على الطلبات القصيرة المطالبة التي تمت جدولتها بعد الطلب السريع الطويل. بالإضافة إلى ذلك، في أوقات التحميل العالي، يمكن أن تكون هناك فرصة ضئيلة جدًا لجدولة الطلبات طويلة الأمد خلال فترة زمنية معقولة. في TNG، قمنا بتنفيذ إستراتيجية مماثلة في واجهة برمجة التطبيقات (API) للطلبات المجمعة التي تمت جدولتها بأولوية منخفضة جدًا.
- (ب) كان من الممكن أن يكون لديك خادم استدلال منفصل للطلبات السريعة وجهاز توجيه يقوم بإعادة توجيه الطلبات اعتمادًا على أطوال التحميل والمطالبة. يتطلب هذا الأسلوب المزيد من موارد GPU ولكن خادم الاستدلال لطلبات السياق القصير لديه متطلبات أقل على ذاكرة GPU (على سبيل المثال، يحتاج Llama-3.3-70B إلى أربعة H100 لطول سياق يبلغ 130 ألف رمز مميز ولكن النشر الثاني مع اثنين H100 يمكن أن يخدم بالفعل الطلبات بطول سياق أقل من 10 آلاف رمز مميز). ومع ذلك، يلزم تصميم جهاز توجيه متطور لتحسين استخدام الموارد. على سبيل المثال، في حالة عدم وجود طلبات سريعة، يجب الاستمرار في استخدام خادم الاستدلال الأكبر.
- (ج) هل يمكن أن يكون منفصلا محركات الاستدلال للملء المسبق وفك التشفير. هذه العمارة التعبئة المسبقة المفصلة يجمع بين عمليات نشر vLLM المتعددة، كل واحدة منها تعمل فقط على التعبئة المسبقة أو فك التشفير فقط. بعد الانتهاء من مرحلة التعبئة المسبقة، يتم نقل ذاكرة التخزين المؤقت KV إلى عامل فك التشفير مما يتسبب في حدوث حمل بسيط للاتصالات. ولكن بما أن عملية التعبئة المسبقة وفك التشفير يتم تشغيلها بشكل معزول على وحدات معالجة رسومات مختلفة، فلن يكون هناك انقطاع مباشر في عمليات فك التشفير بسبب عمليات التعبئة المسبقة المتزامنة بعد الآن.
يظهر الفرق بين المعالجة المتزامنة المثالية (والتي لن تختلف عن الطلبات المعزولة)، والمعالجة المتزامنة الفعلية، واستراتيجية التعبئة المسبقة المفصلة من خلال القياسات التالية:

التعبئة المسبقة المفصلة – مُحسّنة لوقت الاستجابة
يؤدي فصل التعبئة المسبقة وفك التشفير إلى القضاء على تباطؤ إنشاء الرمز المميز في حالة وجود طلبات أخرى إلى حد كبير، مما يجعلها استراتيجية جذابة للغاية. يأتي ذلك بسعر نشر vLLM ثانٍ بالحجم الكامل (على سبيل المثال، بالنسبة لـ Llama-3.3-70B، ستحتاج إلى أربع وحدات معالجة رسوميات H100 لعامل التعبئة المسبقة وأربع وحدات معالجة رسوميات أخرى H100 لعامل فك التشفير إذا كنت تريد دعم الحد الأقصى لطول السياق وهو 130 ألف رمز مميز). عيب آخر هو الاستخدام غير المتكافئ لوحدة معالجة الرسومات: نظرًا لأن التعبئة المسبقة تتطلب حوسبة مكثفة ولكن فك التشفير ليس كذلك، فمن المحتمل أن يقوم عامل التعبئة المسبقة بتشبع استخدام وحدة معالجة الرسومات قبل أن يقوم عامل فك التشفير بذلك. من ناحية أخرى، يمكن أن تتكون المجموعات الكبيرة من أعداد مختلفة من عمال التعبئة المسبقة وفك التشفير (اعتمادًا على أنماط التحميل)، من أجل تحسين استخدام الموارد.
لا يهدف الملء المسبق المفصل إلى زيادة إجمالي الإنتاجية، بل إجمالي “الإنتاجية الجيدة” (أي معدل الطلبات التي تلبي أهداف زمن الاستجابة). وبالتالي، ليس من الأفضل استخدام موارد GPU إذا لم يكن تطبيقك حساسًا لزمن استجابة الطلبات الفردية.
تحذير آخر: لا تزال ميزة التعبئة المسبقة المفصلة في vLLM تجريبية، ولا يمكن الوصول إلى بعض التحسينات والميزات بعد. على سبيل المثال، توجد حاليًا حدود أقل لطول السياق، ولا يستخدم عامل فك التشفير الرسوم البيانية لـ CUDA بشكل متسق، مما يتسبب في فك تشفير أبطأ للطلب طويل الأمد في الشكل أعلاه. لحسن الحظ، هذه ليست عقبات أساسية ومن المرجح أن يتم حلها في الإصدارات المستقبلية من vLLM.