مقالة
التعبئة المسبقة والتفكيك المجزأ

من أجل توليد رموز المخرجات من مطالبة إدخال، يتم تقسيم استنتاج LLM إلى مرحلتين: التعبئة المسبقة والفك. تعمل التعبئة المسبقة على رموز الإدخال، تملأ محادثات KV، قبل الدخول في مرحلة الفك التي تولد الرموز واحدًا تلو الآخر.
بينما تعمل خطوة فك واحدة عادة لعدة ميلي ثانية، تستغرق التعبئة المسبقة وقتًا أطول بكثير. إذا تم تشغيلها على نفس الأجهزة، فإن خلط التعبئة المسبقة مع فك يؤدي إلى تدهور أداء الفك. في هذه المقالة نستكشف حلًا معتمدًا بشكل معروف في شكل التعبئة المسبقة المنفصلة والفك، حيث يتم تشغيلهما على أجهزة منفصلة لزيادة الإنتاجية والكمون لكليهما.
أداء التعبئة المسبقة مقابل الفك
في محرك خدمة LLM النموذجي، يختار مجدول الدُفعات الطلبات لمعالجتها في كل خطوة تنفيذ نموذج. عند التشغيل على جهاز واحد أو عقدة، يتم تجميع كل من طلبات التعبئة المسبقة والفك معًا. تزداد تكلفة الانتباه، التي تتراكم مع طول التسلسل، لكل من التعبئة المسبقة والفك، بنسب طول الإدخالات في ذاكرة KV (kv_len). عادة ما تقوم طلبات الفك بإرسال رمز واحد فقط (qo_len=1
)، بتكلفة دنيا عبر طبقات أخرى تعمل بشكل مستقل على رموز تسلسل. يتم تمرير آلاف أو عشرات الآلاف من رموز طلبات التعبئة المسبقة بتكلفة كبيرة عبر طبقات كثيفة (qo_len كبير).
تتأثر مدة مرور الوراء بشكل أقوى بعدد الرموز المستقلة التي تمر عبر الطبقات الكثيفة (qo_len) أكثر من عدد الرموز المسترجعة من ذاكرة KV أثناء الانتباه (kv_len). يمكن مواصلة الانتباه بالتوازي عبر عدد الطلبات وkv_len بما يتناسب مع أطوال التسلسل، لتحقيق استخدام جيد. التعبئة المسبقة تعتمد على الحوسبة: مع qo_len المرتفع، يمكن لنوى GEMM تخصيص كتل كافية على طول البُعد M للاستفادة الكاملة من قدرات حوسبة وحدات معالجة الرسوميات الحديثة. فك يعتمد على الذاكرة: بسبب أحجام الدُفعات الصغيرة عادة، يكون عدد المدخلات على طول M صغيرًا في الغالب، بما يكفي لكتلة واحدة فقط. في حين أن نوى GEMM Split-K يمكن أن تحسن استخدام SM لأحجام دسمة منخفضة من الرموز، تظل المخزنات ووحدات ضرب المصفوفة تحت الاستخدام عادة.

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


يمكن معالجة هذه القضايا باستخدام مجموعة منفصلة من العقد لإجراء التعبئة المسبقة والفك. عند توصيل عقدة التعبئة المسبقة بعدة عقد فك، يمكن جدولة عدد كافٍ من الطلبات للتعبئة المسبقة لزيادة وحدة الطرفية إلى أقصى حد والحفاظ على عدد كافٍ من الطلبات المتزامنة على عقد الفك لزيادة وحدة الطرفية إلى أقصى حد. تملأ العقد التعبوية KV المحادثات، التي تنتقل بعد ذلك إلى عقد الفك. نظرًا لأن وحدات الفك لم تعد تحتاج إلى كسر التعبئة المسبقة، فإن زمن الاستجابة يصبح أكثر تحديدًا، لأن التأثير العام لنمو kv_len للطلبات النشطة يصبح أقل وضوحًا. يتم تغطية التكلفة في زيادة زمن الوصول إلى أول رمز (TTFT)، نظرًا لأن نقل محادثات KV عبر الشبكة يمكن أن يستغرق عشرات إلى مئات الميلي ثانية.
المرسل KV
في Perplexity، يتم بناء تنفيذنا للتعبئة المسبقة المنفصلة والفك حول مرسل KV الذي يتفاعل مع محرك LLM لتنسيق نقل محادثات KV من العقد التعبوية إلى العقد الفكية عبر الشبكة. على الجانب التعبوي، يقبل المرسل الطلبات من العقد الفكية، ويقوم بتسليمها إلى مجدول الدُفعات ويتتبع تنفيذ مرور الوراء لإرسال محادثات KV مع أقل قدر ممكن من الزمن الفاصل. على الجانب الفكي، بعد تخصيص الصفحات غير القابلة للطرد، يقوم المرسل بمنع الطلب من الجدولة للفك حتى يتم إخطاره بإكمال نقل محادثات KV وسياق فك.

يتطلب تفكيك التعبئة المسبقة اتصالات عالية السرعة ومنخفضة الزمن الفاصل، لذلك يتم تصميم تنفيذنا خصيصًا لـ RDMA، ويدعم واجهات تحكم الشبكات EFA وConnectX (NICs). يتم بناء المرسل KV على libfabric، باستخدام أغلفة fabric-lib الخاصة بنا لتوفير تجريدات ذات زمن فاصل منخفض المستوى أعلى من بدائي الوصول المباشر للذاكرة عن بعد (RDMA)، ينفذ نقل الصفحات والبيانات الفوقية بكفاءة، مع تطبيق إشارات ذات زمن فاصل منخفض. في الخلفية، يقوم fabric-lib بتنسيق وحدة معالجة الرسوميات GPU ووحدات اتصال الشبكة المتصلة مباشرة لنسخ البيانات من عقد التعبئة إلى عقد الفك.
عند الاستلام، تقوم عقدة التفضيل بتخصيص مجموعة مطابقة لصفحات KV المصدر وتجدول الطلب للتعبئة باستخدام محركها المحلي. لتقليل الزمن الفاصل، لا تنتظر عمليات النقل مرور الوراء: بدلاً من ذلك، يتم بدء نسخ صفحات KV بمجرد الانتهاء من إضافة إدخالات ذاكرة KV للطبقات الفردية. نظرًا لأنه يمكن تجميع طلبات التعبئة، يقوم مجدول الدُفعات بإخطار المرسل KV عن القطع الحالية المجدولة قبل التنفيذ. لدعم الرسوم البيانية CUDA أثناء القدرة على تتبع الطبقات، احتفظ المرسل بخيط مخصص يقوم باستطلاع عداد يتم زيادته بعد إسقاط ناتج الانتباه. يتم الحفاظ على العداد فقط في العقدة القائدة في بيئة متفرقة: حتى وإن كانت إدخالات KV صالحة بعد الإضافة وقبل الانتباه، فإن الإسقاط الناتج يتم تقليله عبر الرتب، مما يُزامنها ضمنيًا. بمجرد ملاحظة تغيير في العداد، يتم إخطار المرسل ويستدعي fabric-lib لبدء نقل الطبقة.

بعد إكمال نقل القطعة الأخيرة، يتم أيضًا نسخ أي بيانات فوقية إضافية: يتطلب فك التخمين أو MTP نقل العمليات الحسابية وحالات الإخفاء إلى وحدة فك. يتم تنفيذ هذه النسخ أيضًا عبر RDMA، إلى ومن المخازن المسبقة التخصيص.
عند إكمال جميع عمليات النقل المعلقة للقطعة الأخيرة، يتم إلغاء تخصيص صفحات KV من طرف التفضيل وإكمال الطلب. لا يتم إخطار العقدة الفكية صراحة: بدلاً من ذلك، تستخدم عدادات فورية لتتبع عدد العمليات المكتملة. يعتمد عدد عمليات RDMA على جانب التفضيل على عدد الصفحات المنقولة. عند اكتمال العدد المعروف من نسخ الصفحات والسياق، يستدعي fabric-lib المرسل KV للإشارة إلى أن الطلب جاهز للفك. يقوم المرسل بإلغاء تخصيص أي سياق ويسلم الطلب إلى محرك LLM.
نقل المخزنات KV المتفرقة
إذا كانت عقد التعبئة والفك تعتمد على التوازي النفاذ الموتر (TP) وتقوم بتسجيل أو استنساخ ذاكرات KV بشكل متطابق، فإن محرك نقل واحد يقوم بتنسيق أجهزة متعددة لإرسال واستقبال صفحات جميع النسخ. من أجل استخدام مرسل واحد ومحرك نقل واحد على الرغم من تكرار منفذ النموذج عبر أجهزة وعمليات متعددة، يتم استخدام cuMem وcuMemImportFromShareableHandle لتخصيص ذاكرة الجهاز التي تدعم ذاكرات KV ولمطابقتها في العملية الرئيسية. يقوم محرك النقل بفحص طوبولوجيا العقدة للعثور على وحدات الاتصال ووحدات المعالجة المركزية في أقرب عقدة NUMA لاستخدامها في نقل كل من أجزاء ذاكرة KV.
إذا كان المصدر والوجهة يشتركان في أجزاء متطابقة، فإن عمليات النقل تصبح سهلة لأنه يوجد تعيين واحد لواحد من الأجهزة والصفحات بين المصدر والوجهة. في هذه الحالة، يساعد التفكيك الضمني على تقليل فترات النقل: باستخدام المزيد من وحدات معالجة الرسوميات، يمكن استخدام المزيد من وحدات الاتصال المرتبطة، مما يقترب من تحقيق الاستخدام الكامل للنطاق الترددي. ومع ذلك، إذا كان هناك عدم توافق، يجب على محرك النقل تقسيم أو إعادة بناء الصفحات بناءً على النسبة بين أجزاء المصدر والوجهة.

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

تتطلب عمليات النقل المتفرقة تعديلاً طفيفًا في ذاكرات KV. افتراضيًا، يعتمد FlashInfer على تخطيط NHD، الذي يترتيب الرموز داخل الصفحة ضمن الرؤوس. نظرًا لأن المخزنات من المحتمل أن تقسيم على عدد رؤوس الانتباه، فإن هذا يخلق عدم الاستمرار داخل الرأس. نقلات RDMA لا تدعم ضمنيًا الكتابات المتقطعة، مما يتطلب عملية واحدة لكل رأس لإجراء النقل. بدلاً من ذلك، لتقليل عدد التفاعلات مع libfabric، ننظم ذاكرات KV باستخدام تخطيط HND الذي يضع البعد الرئيسي قبل عدد الرموز. يضمن ذلك الاستمرار، مما يسمح بنقل صفحة واحدة بكتابة واحدة.
الفك التخميني
يتطلب الفك التخميني تعديلات طفيفة على التعبئة المسبقة المفصلة. في تنفيذنا، لا يُسمح لعقد التعبئة بمعاينة الرموز. نظرًا لأن نماذج Sonar الخاصة بـ Perplexity تدعم المخرج المنظم، لا نريد التورط في تعقيد مزامنة تنفيذات معالجات التخطيطات عبر التعبئة والفك. في آليات MTP والفك التخميني، يتضمن التعبئة المسبقة لنموذج المسودة حتى الرمز الأخير معاينة الرموز من النموذج الهدف.

لتفادي هذه المشاكل، لا تتضمن التعبئة المسبقة الرمز الأخير لتسلسل المدخلات. بدلاً من ذلك، يتم نقل حالات الإخفاء أو العمليات الحسابية من التعبئة المسبقة قبل الرمز الأخير ويُعتبر كرمز يتم فك تشفيره في الخطوة التالية على وحدة الفك. على الرغم من أن هذا يزيد قليلاً من الفترات الزمنية، نظرًا لأن خطوة فك كاملة يجب أن تنفذ بعد التعبئة لإصدار الرمز الأول، إلا أن تعقيد التنفيذ يتم تخفيضه بشكل كبير.
عمليات الانتشار المنفصلة
لقد نشرنا أو جربنا تكوينات منفصلة متعددة مع نماذج مختلفة، لدعم حركة المرور الإنتاجية أو تحميل عمليات التقييم الداخلية. بناءً على حجم النماذج وآلية الانتباه الخاصة بها، اخترنا مخططات تقسيمية مناسبة لعقد التعبئة والفك لأفضل استخدام لوحدات معالجة الرسوميات.
ديبسيك-R1
مع ديبسيك، نظرنا في كل من التوزيعات المتوازية الموترة (TP) والمتوازية البياناتية (DP). كما نوقش في مشاركات مدونة سابقة، توفر توزيعات TP فترة أقل في مقابل تكلفة أقل في وحدة الطرفية، وتحتاج إلى المزيد من وحدات معالجة الرسوميات لخدمة حركة المرور الكثيفة. توزيعات DP تتكيف بشكل أفضل مع الحمل، ولكن وحدة الطرفية القصوى لها أقل بسبب تكلفة الاتصال بين الأجهزة أو العقد.
يعتمد ديبسيك على الانتباه متعدد الرؤوس الضمني، مما يضغط ذاكرات KV. نظرًا لأن جميع رؤوس KV مضغوطة في متجه ضمني منفرد، لا يستطيع TP تفكيك ذاكرات KV، حيث يجب بدلاً من ذلك تكرار المتجهات الضمنية على جميع الرتب. يحدث الانفجار بعد فك الضغط، حيث يمكن لكل رتبة استخراج رؤوس مختلفة من نفس التمثيل الضمني. بالتالي، جميع شفرات ذاكرات KV متطابقة عبر كل من التعبئة والفك.
مع إعداد TP داخل العقدة، يتم تفكيك كل من التعبئات والفك بطريقة متطابقة. يتم إرسال انتقالات من جميع الرتب من أجل الاستفادة الكاملة من جميع وحدات الاتصال المتاحة. ومع ذلك، مع نشر DP، حيث يكون حجم رتبة TP أقل أو يتم تعيين كل رتبة DP إلى وحدة معالجة رسومات واحدة، يمكن لأي جهاز تعبئة يحتفظ بنسخة مكررة من ذاكرة KV إرسالها. لموازنة الطلبات عبر جميع وحدات الاتصال المتاحة، نقوم باختيار عشوائي لوحدة معالجة رسومات ووحدة اتصال لإرسال ذاكرات KV من عقدة التعبئة إلى وحدة الفك.
مع تحصيل مزيج من التعبئة والفك، كان انتشار R1 يكافح بشكل متزايد لتجاوز 50 TPS ببسبب الانقطاع المتكرر للتعبئة باتجاه مئات الميلي ثانية. بالعكس، من خلال فصل التعبئة، تكبدنا زيادة زمنية تبلغ حوالي 100 ميلي ثانية لزمن الوصول إلى أول رمز (TTFT) لكل طلب، ولكن يمكن لعقدة تعبئة واحدة الحفاظ على حجم دُفعة متسق على 3 عقد فك، وتسليم حمل يزيد عن 90 TPS مع تحميل يبلغ حوالي 1 QPS لكل عقدة فك. مع نشرات DP، كان TPS أقل قليلاً حوالي 50، ومع ذلك يمكن للعقدة التعامل مع حمل يبلغ 1 QPS لكل رتبة، بوجود 8 رتب في عقدة واحدة.
كيوان-كاتب 3
هذا النموذج 480B يستخدم انتباه الطلبات المجمعة (GQA)، لذا يمكن تفكيك الانتباه بسهولة ويمكن أن يستفيد من التوازي النفاذ الموحد دون التضحية بالذاكرة لمحادثات KV. بناءً على ذلك، يمكننا تفكيك النموذج عبر 8 وحدات معالجة رسوميات لكل من التعبئة والفك، مع تقسيم حوالي 3 وحدات فك بعقدة تعبئة واحدة. نظرًاطعالية الانتباه تم تفريقها، نعتمد على تخطيط ذاكرة KV HND لتقسيم محادثات تعبئة وفك KV، مع ترتيب رتب التعبئة مع رتب الفكرة والتوظيف الكامل لجميع وحدات الاتصال لنقل الأجزاء بالتوازي.