لو شركتك بتدفع $4,800 شهرياً علشان تشغّل Llama 3.1 70B على H100 لخدمة chatbot داخلي، وبتشتكي إن كل مستخدم بياخد توكناته بمعدل 42 توكن/ثانية (TPS) بس، انت بتدفع تكلفة memory bandwidth bottleneck حقيقي. الـ GPU مش هو المشكلة. الـ autoregressive decoding هو المشكلة. Speculative Decoding بيخلّي نموذج صغير (3B) يقترح 7 توكنات في تمرير أمامي واحد، ونموذج Llama 70B يتحقق منهم كلهم في تمرير أمامي واحد بدل سبعة، فيقفز TPS من 42 لـ 113 — تحسّن 2.7× بنفس الـ logits، بدون أي خسارة دقة إحصائياً.
Speculative Decoding: ليه أسرع وأمين رياضياً في نفس الوقت؟
المشكلة باختصار: ليه الـ 70B بطيء أصلاً
توليد التوكنات في decoder-only transformer عملية autoregressive. كل توكن لازم يستنى اللي قبله يخلص علشان يبتدي. على H100 SXM بـ 80GB، كل forward pass على Llama 3.1 70B بفترة memory-bound: الـ GPU بياخد ~24ms علشان يقرا الـ 140GB من الـ weights (FP16) من HBM، ينفّذ matmul، يكتب logits. الحساب نفسه ياخد أقل من 4ms. يعني 83% من الوقت GPU بيستنى الذاكرة.
النتيجة: throughput لا يتجاوز ~42 TPS لكل request، حتى لو الـ GPU عنده 989 TFLOPS متاح. الـ compute roof عالي، بس الـ bandwidth roof منخفض. ده Roofline model بسيط: عند compute intensity من 1.3 FLOPs/byte، أنت تحت bandwidth-bound بـ 100×.
مثال للفهم: الصحفي والمُحرر
تخيّل صحفي بيكتب تقرير لـ Reuters. الطريقة التقليدية: يكتب جملة، يرسلها لرئيس التحرير، يستنى ردّ "موافق/عدّل"، يكمل الجملة اللي بعدها. لو رئيس التحرير بياخد 5 دقائق لكل جملة، التقرير ياخد ساعتين.
دلوقتي تخيّل عندك صحفي مبتدئ سريع بيكتب 7 جمل مرة واحدة "تخميناً" بناءً على السياق. رئيس التحرير بيقرا كل السبع جمل في مرة واحدة، يقبل أول 5 (لأنهم منطقياً صح) ويكتب الجملة السادسة بنفسه (لأنها كانت غلط). النتيجة: 6 جمل معتمدة في زمن قراءة واحد بدل 6 جولات منفصلة. الجودة النهائية بالظبط هي اللي رئيس التحرير كان هيكتبها لو كتب لوحده. ده Speculative Decoding بالضبط.
التعريف العلمي الدقيق
Speculative Decoding، اللي اقترحوه Leviathan et al. (Google Research, 2023) و Chen et al. (DeepMind, 2023) في نفس الشهر تقريباً، بيستغل ملاحظة معمارية أساسية: في transformer decoder، تكلفة تمرير أمامي على K توكن متتالي تقريباً مساوية لتكلفة تمرير أمامي على توكن واحد، طالما الـ KV cache فيه السياق. ده بسبب إن المرحلة memory-bound والـ weights بيتقرأوا مرة واحدة لأي حجم batch صغير.
الـ algorithm:
- Draft phase: نموذج صغير M_q (مثل Llama 3.2 3B) بيولّد K توكن باستخدام K تمرير أمامي. تكلفته صغيرة لأن النموذج صغير (6GB FP16 بدل 140GB).
- Verification phase: النموذج الكبير M_p (Llama 3.1 70B) بياخد كل الـ K توكن المقترحين في تمرير أمامي واحد (parallel verification)، وبيحسب logits لكل موضع.