Speculative Decoding للمحترف: 2.3× سرعة في Llama 70B بـ Draft Model أصغر 70 مرة
المستوى: محترف — يفترض هذا المقال أنك تعرف الـ autoregressive decoding، شغّلت vLLM أو TensorRT-LLM قبل كده، وفاهم الفرق بين memory-bound و compute-bound في الـ GPU inference.
لو بتشغّل Llama 3.1 70B على H100 بـ batch size = 1 وبتقيس 32 token/ثانية، أنت بتستخدم 4% بس من قدرة الـ tensor cores. الـ GPU مش بطيء، الـ GPU مستني الذاكرة. Speculative Decoding بيرفع الرقم لـ 74 token/ثانية بدون تغيير في جودة الخرج ولا fine-tuning. مقال للمحترف بأرقام مقاسة على workload فعلي.
المشكلة باختصار: ليه الـ GPU بيقف مكتوف الأيدي؟
توليد التوكنات في LLM autoregressive — لازم النموذج يخلّص توكن قبل ما يبدأ اللي بعده، لأن كل توكن جديد بياخد كل التوكنات السابقة كمدخل. على H100 (989 TFLOPS في FP16) ونموذج 70B، كل forward pass بيتطلّب قراءة 140GB من الأوزان من الـ HBM. الـ memory bandwidth (3.35TB/s) هي السقف الفعلي، مش الـ compute.
النتيجة: arithmetic intensity حوالي 4 FLOPs لكل byte يتم قراءته، والـ tensor cores بتقعد فاضية أكثر من 90% من الوقت. ده اللي بنسمّيه memory-bound regime، وهو ميزة هندسية ممكن نستغلها.
المثال الواقعي: مطبخ المطعم وطبّاخ المراجعة
تخيّل مطبخ فيه شيف ماهر بيعمل وصفة معقّدة، كل طبق بياخد منه 3 دقايق. لو معاك زبون عايز 8 أطباق وفضل الشيف شغّال لوحده، هتنتظر 24 دقيقة بالترتيب.
بدل ما تستنّى، حطّيت طبّاخ مبتدئ سريع جنبه. الطبّاخ المبتدئ بيخمّن الـ 5 أطباق الجايين بسرعة — مش بنفس دقّة الشيف بس بتقدير معقول. الشيف الماهر بيقعد يفحص الـ 5 أطباق في وقت واحد (الوقت اللي كان فاضي عنده أصلاً) ويقول لكل طبق: مقبول أو مرفوض.
لو 4 من 5 أطباق اتقبلت، أنت طلعت 4 أطباق في وقت طبق واحد. لو الشيف رفض الطبق الثاني، أنت بتتجاهل الـ 3 الباقيين وتطلب من المبتدئ يبدأ من جديد. الميزة: الشيف بيشتغل بنفس المعدّل، بس عدد الأطباق الناتجة بيتضاعف. هذه فكرة Speculative Decoding بالظبط.
الشرح العلمي: Draft and Verify
الخوارزمية الأصلية (Leviathan et al., "Fast Inference from Transformers via Speculative Decoding", ICML 2023) بتشتغل على 3 خطوات في كل iteration:
- Draft: نموذج صغير (مثلاً Llama 3.2 1B) بيولّد K توكنات متتالية autoregressive في زمن قصير. القيمة الشائعة K=5.
- Verify: النموذج الكبير (Llama 3.1 70B) بياخد الـ prompt + الـ K توكنات الجديدة كـ batch واحد، ويحسب توزيع الاحتمالات لكل توكن في forward pass واحدة. ده ممكن لأن الـ GPU كان فاضي compute-wise.
- Accept or Resample: لكل توكن i في الترتيب، نقارن p_target(x_i) مع p_draft(x_i). لو p_target ≥ p_draft، نقبل التوكن. غير كده، نقبله باحتمال p_target/p_draft. لو رفضنا، نوقف ونسحب توكن مصحّح من التوزيع max(0, p_target - p_draft) ثم نعيد التطبيع.
الإثبات الرياضي في الورقة بيضمن إن التوزيع الإجمالي للتوكنات المقبولة == التوزيع لو شغّلت الـ target model لوحده، توكن توكن. يعني الجودة محفوظة بنسبة 100% — مش approximation. هذه نقطة جوهرية: Speculative Decoding lossless، مش تنازل عن دقّة مقابل سرعة.