الزمن والتكلفة
درس 2 من 6
2الزمن والتكلفة
الصورة الكبيرةالمتوسط يكذب في زمن الاستجابة. خدمة متوسطها 220 ملّي ثانية قد يعاني فيها مستخدم من كل مئة انتظار ثانية ونصف أو أكثر، ومستخدم يرسل عشرين طلبًا في جلسته سيقابل هذه الحالة غالبًا. هذا الدرس عن المئينات، وزمن أول رمز، والتجميع، وتكلفة ألف طلب.
ماذا تشاهد في الرسم: المتوسط 222 والوسيط 181، وكلاهما يبدو جيدًا. لكن p99 يقارب 1.3 ثانية، فواحد من كل مئة طلب أبطأ بأضعاف. لهذا تُكتب الأهداف بالمئينات لا بالمتوسط.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
لو كان أغلب الزبائن ينتظرون دقيقة وزبون واحد من كل عشرين ينتظر عشر دقائق، فالمتوسط يبدو جيدًا لكن ذلك الزبون لن يعود. لهذا نقيس زمن الأبطأ لا المتوسط فقط. وفي النماذج اللغوية يهم أيضًا متى تظهر أول كلمة.
p50 الوسيط وp95 وp99 ذيل التوزيع الذي يعيشه أسوأ المستخدمين. وفي التوليد يقاس زمن الرمز الأول TTFT ومعدل الرموز في الثانية. والتكلفة تُحسب بالرموز أو بزمن العتاد لكل طلب، والتجميع batching يرفع الإنتاجية على حساب الزمن.
قبل أن تبدأ
🌐من دفتر إلى خدمة
عندك خدمة تستقبل طلبات، والآن تقيس كم تستغرق.
🎲الاحتمال
تعرف التوزيع والوسيط، وأن التوزيع قد يكون له ذيل طويل.
الفكرة الجوهرية
المتوسط يكذب في الزمن. تتعلّم هنا قراءة المئينات، ثم مرحلتي النموذج اللغوي وزمن أول رمز، ثم التجميع، ثم تكلفة ألف طلب.
1المئينات لا المتوسط
p50 هو الزمن الذي ينتهي فيه نصف الطلبات، و p95 الزمن الذي ينتهي فيه 95% منها. الثاني يقيس تجربة أسوأ المستخدمين حظًا.
نحاكي 10000 طلب: معظمها حول 180 ملّي ثانية، وقليل منها يصيب مسارًا بطيئًا.
import numpy as np
rng = np.random.default_rng(0)
latency_ms = rng.lognormal(mean=np.log(180), sigma=0.45, size=10_000)
latency_ms[rng.choice(10_000, 150, replace=False)] *= 8 # 1.5% hit a slow path: a cold cache, a long input
print(f"mean: {latency_ms.mean():7.0f} ms")
for p in [50, 95, 99]:
print(f"p{p}: {np.percentile(latency_ms, p):7.0f} ms")
print(f"max: {latency_ms.max():7.0f} ms")
المتوسط 222 والوسيط (p50) 181، يبدوان جيدين. لكن p95 ضعف الوسيط، وp99 أكثر من ثانية وربع، والأسوأ قرب خمس ثوانٍ. لو راقبت المتوسط وحده، لما عرفت أن واحدًا من كل مئة طلب يستغرق سبعة أضعاف المعتاد. راقب p50 وp95 وp99 دائمًا، واكتب أهدافك بها: «p95 تحت 500 ملّي ثانية».
2مرحلتان: القراءة والكتابة
النموذج اللغوي يقرأ السؤال كله دفعة واحدة بالتوازي، وهذا سريع. ثم يكتب الجواب رمزًا رمزًا، وكل رمز يحتاج تمريرة كاملة، وهذا بطيء.
انظر إلى الرسم: قراءة 1200 رمز شريحة رفيعة، وكتابة 300 رمز تأخذ الشريط كله تقريبًا.
prompt_tokens, answer_tokens = 1200, 300
prefill_tok_per_s = 6000 # reading the prompt is fast and parallel
decode_tok_per_s = 40 # writing is one token at a time
ttft = prompt_tokens / prefill_tok_per_s
total = ttft + answer_tokens / decode_tok_per_s
print(f"time to first token: {ttft:.2f} s")
print(f"time to full answer: {total:.2f} s")
print(f"with streaming, the user starts reading after {ttft:.2f} s instead of {total:.2f} s")
قراءة 1200 رمز تستغرق 0.2 ثانية، وكتابة 300 رمز تستغرق 7.5 ثوانٍ. بلا بثّ، ينظر المستخدم إلى شاشة فارغة سبع ثوانٍ ونصف. مع البثّ، يبدأ القراءة بعد خُمس ثانية، والإجابة تكتمل أثناء قراءته. نفس الحساب، وتجربة مختلفة تمامًا.
لهذا رمز الإخراج أغلى من رمز الإدخال، وتقصير الجواب أسرع طريقة لخفض الزمن والتكلفة معًا.
3التجميع: إنتاجية مقابل زمن
التجميع يعالج عدة طلبات في تمريرة واحدة. لكل تمريرة تكلفة ثابتة، فتوزيعها على طلبات أكثر يرفع الإنتاجية، ويزيد زمن كل طلب قليلًا.
انظر إلى الرسم: الإنتاجية ترتفع بسرعة ثم تتباطأ، والزمن يبدأ بطيئًا ثم يقفز. العلامة عند دفعة 16.
كل تمريرة لها تكلفة ثابتة (40 ملّي ثانية) وتكلفة لكل طلب في الدفعة (6 ملّي ثانية). البطاقة بـ1.20 دولار في الساعة.
overhead_ms, per_item_ms = 40, 6 # each forward pass has a fixed cost plus a cost per request in the batch
gpu_cost_per_hour = 1.20
print("batch latency requests/s $ per 1000 requests")
for batch in [1, 4, 16, 64]:
latency = overhead_ms + per_item_ms * batch
throughput = batch / (latency / 1000)
cost = gpu_cost_per_hour / (throughput * 3600) * 1000
print(f"{batch:5} {latency:5.0f} ms {throughput:9.0f} {cost:10.4f}")
من دفعة 1 إلى 16، الإنتاجية من 22 إلى 118 طلبًا في الثانية، والتكلفة لكل ألف طلب تنخفض لأقل من الخُمس، بينما الزمن من 46 إلى 136 ملّي ثانية. بعد ذلك تتناقص الفائدة: دفعة 64 تضاعف الزمن ثلاث مرات مقابل إنتاجية أعلى بـ28% فقط. اختر الدفعة التي تحقّق هدف p95 بأقل تكلفة، لا الأكبر الممكنة.
4تكلفة ألف طلب
التكلفة لكل ألف طلب هي سعر الساعة مقسومًا على الطلبات في الساعة، مضروبًا في 1000. بهذا الرقم تقارن الإعدادات والمزوّدين.
انظر إلى الرسم: نفس البطاقة بسعر 1.20 دولار في الساعة، والتكلفة تهبط مع حجم الدفعة.
اختر الدفعة التي تحقّق هدف p95 بأقل تكلفة، لا أكبر دفعة ممكنة.
كيف يعمل، خطوة بخطوة: كيف يتكوّن زمن إجابة نموذج لغوي
ينتظر الطلب في الطابور إن كانت البطاقة مشغولة، وقد يُجمَّع مع طلبات أخرى في دفعة.
يُقرأ السؤال كاملًا دفعة واحدة بالتوازي، وهذه مرحلة سريعة: 1,200 رمز في 0.2 ثانية في المثال.
تُولَّد الإجابة رمزًا رمزًا، وكل رمز تمريرة كاملة: 300 رمز في 7.5 ثانية.
مع البثّ يرى المستخدم أول رمز بعد مرحلة القراءة، فيبدأ القراءة قبل اكتمال الإجابة.
مثال محلول
عشرة آلاف طلب حقيقي التوزيع: أغلبها حول 180 ملّي ثانية، وقلّة تمرّ بمسار بطيء (ذاكرة مؤقتة باردة، أو مدخل طويل). لنقارن المتوسط بالمئينات.
جرّب بلا كود
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| المتوسط يكفي لوصف سرعة الخدمة. | يخفي الذيل. في المثال كان المتوسط 222 والأسوأ قرب خمس ثوانٍ. |
| p99 حالة نادرة لا تهمّ. | مستخدم يرسل خمسين طلبًا يقابلها بنحو 40%، فهي تجربة أغلب المستخدمين النشطين كل بضع جلسات. |
| أكبر دفعة ممكنة هي الأفضل. | بعد الدفعة 16 تصغر المكاسب: الدفعة 64 ضاعفت الزمن ثلاث مرات مقابل 28% إنتاجية أكثر. اختر ما يحقّق هدف p95 بأقل تكلفة. |
جرّب بنفسك
أي رقم يعبّر عن تجربة المستخدمين الأسوأ حظًّا؟
المتوسط والوسيط يخفيان الذيل. p95 يقول: 5% من الطلبات أبطأ من هذا.
نظام دردشة يستغرق 8 ثوانٍ للإجابة الكاملة. ما أسرع تحسين يشعر به المستخدم؟
الحساب لا يتغيّر، لكن الانتظار المحسوس ينخفض من 8 ثوانٍ إلى أقل من ثانية. والخطوة التالية: إجابات أقصر.
بطاقات مراجعة سريعة
تحقق من فهمك
المتوسط 200 ملّي ثانية وp99 ثلاث ثوانٍ. مستخدم يرسل 50 طلبًا في جلسته. ما احتمال أن يقابل طلبًا واحدًا على الأقل بطيئًا جدًّا؟
نحو 40%: احتمال أن تكون الطلبات الخمسون كلها ضمن الـ99% هو 0.99 أُس 50، أي 0.6 تقريبًا. لهذا p99 ليس «حالة نادرة» لمستخدميك النشطين، بل شيء يقابله أغلبهم كل بضع جلسات.
بطاقة بسعر 1.20 دولار في الساعة تخدم 118 طلبًا في الثانية. كيف تحسب تكلفة ألف طلب؟
تقسم سعر الساعة على الطلبات في الساعة (118 × 3600) وتضرب في 1000، فتكون نحو 0.0028 دولار، كما في جدول التجميع.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.