SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-10-26

كيف تقيس الرموز في الثانية لنموذج LLM محلي؟

استخدم اختبار تزامن تدريجياً لقياس الرموز في الثانية فعلياً، ثم احسب الحد الذي يصبح عنده استئجار GPU أوفر من الدفع لكل رمز عبر API.

لماذا يحدد عدد الرموز في الثانية ما إذا كان استخدام وحدة معالجة الرسوميات (GPU) مجدياً

عدد الرموز في الثانية (Tokens per second) هو المعدل الذي ينتج به خادمك النصوص، وهو الرقم الذي يحدد ما إذا كان استئجار وحدة معالجة رسوميات (GPU) أرخص من الدفع مقابل كل رمز عبر واجهة برمجة تطبيقات (API). تُحاسَب على خادم الـGPU بالساعة سواء كان مشغولاً أو خاملاً، بينما تُحاسَب على الـAPI المستضاف بناءً على عدد الرموز. لذا، لا يكون خيار الـGPU مربحاً إلا إذا حافظت على معدل إنتاج مرتفع بما يكفي خلال معظم الساعات التي تدفع ثمنها.

هذا يعني أنك بحاجة إلى قياس فعلي، وليس مجرد رقم قرأته في مكان ما. تحدد هذه الصفحة الأرقام الأربعة التي تستحق التسجيل، ثم توفر الأوامر التي تنتجها والعمليات الحسابية التي تحولها إلى قرار.

لماذا لا يكون رقم الرموز في الثانية المنشور هو رقمك

نشرت DigitalOcean في يوليو 2026 أرقاماً لمعدل المعالجة باستخدام NVIDIA H200 واحد يشغّل llama3.3-70b-instruct بتنسيق FP8 (الفاصلة العائمة ذات 8 بت) عبر vLLM. هذه الأرقام مفيدة، لكنها ليست أرقامك.

رسم بيانيPublished DigitalOcean H200 figures, llama3.3-70b-instruct FP8, July 2026
البيانات وراء هذا الرسم البياني
[
  {
    "config": "H200, one stream",
    "tok_s": "47"
  },
  {
    "config": "H100, saturated",
    "tok_s": "236"
  },
  {
    "config": "H200, saturated",
    "tok_s": "2,036"
  },
  {
    "config": "H200, saturated, in+out",
    "tok_s": "4,071.6"
  }
]

كل صف أعلاه منقول من تلك الصفحة، واثنان منهما يمثلان الحد الأدنى لنطاق تذكره الصفحة، لذلك تعامل مع هذين الرقمين على أنهما حد أدنى. لم نقس أي رقم في هذا المخطط بأنفسنا.

ابدأ بالصفين الأخيرين. الرقم الرئيسي هو 4,071.6 رمزاً/ثانية، بينما يبلغ معدل المخرجات فقط 2,036 رمزاً/ثانية. يحسب الرقم الرئيسي رموز الإدخال والإخراج معاً. استخدم الاختبار 1,024 رمز إدخال مقابل 1,024 رمز إخراج، لذلك فإن نصف الرقم الرئيسي تقريباً يمثل المخرجات. هذا التقسيم مهم لأن الإخراج هو الجزء الأبطأ. تعالج مرحلة Prefill، أي قراءة المطالبة، جميع رموز الإدخال في تمريرة واحدة. أما مرحلة Decode، أي كتابة الإجابة، فتنتج رمزاً واحداً في كل مرة. لذلك يَحسب رقم معدل المعالجة الإجمالي متوسطاً بين عملية قليلة التكلفة وأخرى مرتفعة التكلفة.

ننتقل الآن إلى الصف الأول. ينتج H200 نفسه عند خدمة طلب واحد في كل مرة 47 رمزاً/ثانية، لذلك يكون الرقم عند التشبع أعلى بأكثر من أربعين مرة على العتاد نفسه. يحدث هذا الفرق لأن خطوة Decode واحدة تترك GPU في انتظار الذاكرة معظم الوقت، بينما تملأ الطلبات المتزامنة ذلك الوقت الخامل. أما الصف الثاني، 236 رمزاً/ثانية، فيمثل NVIDIA H100 واحدة على النموذج نفسه، ويحده KV cache، أي ذاكرة التخزين المؤقت للمفاتيح والقيم التي تحتفظ بها المحادثة المقدمة لكل طلب على البطاقة. تستوعب بطاقة بسعة 80 GB عدداً أقل من الطلبات المتزامنة لنموذج 70B، لذلك تصل إلى التشبع عند معدل أقل.

إذا غيّرت النموذج أو غيّرت نسبة الإدخال إلى الإخراج، فسيتغير كل رقم أعلاه. تحدد الأرقام المنشورة توقعاتك، لا ميزانيتك. وتنطبق القاعدة نفسها على اختبار VPS بصدق من حيث القرص والشبكة.

الأرقام الأربعة الجوهرية

  • الوقت حتى الرمز الأول (TTFT). هو التأخير بين إرسال الطلب ووصول أول رمز مخرجات. يتكون من وقت التعبئة المسبقة (prefill) مضافاً إليه وقت الانتظار في الطابور. يشعر المستخدم بهذا الرقم بشكل مباشر.
  • رموز المخرجات في الثانية، لكل تدفق. سرعة كتابة الإجابة الواحدة بمجرد بدئها. تجاوز سرعة 20 رمزاً في الثانية يجعلها أسرع من سرعة القراءة لدى معظم البشر، لذا فإن أي سرعة إضافية هنا لا تقدم فائدة تذكر.
  • إجمالي إنتاجية المخرجات المشبعة. هو مجموع كل التدفقات المتزامنة عندما يكون الخادم محملاً بالكامل. هذا هو رقم السعة، وهو الرقم الذي يبرر تكلفة وحدة معالجة الرسوميات (GPU).
  • قيم p50 و p99 لـ TTFT تحت ظروف التزامن. تمثل p50 الطلب المتوسط. بينما تمثل p99 القيمة التي تقع تحتها 99 طلباً من أصل 100. يظهر تأثير الانتظار في الطابور في قيمة p99 أولاً.

يتحسن الرقمان الأول والثاني عندما يكون الخادم في حالة خمول. بينما يتحسن الرقم الثالث عندما يكون الخادم مشغولاً. هذه الأرقام تتعارض مع بعضها البعض، ولهذا السبب لا يوجد رقم واحد يصف أداء خادم تقديم الخدمات.

ثبّت طولي الإدخال والإخراج قبل القياس

يعتمد معدل النقل على شكل حركة الشبكة. يُعدّ طلب يحتوي على 4,000 رمز وإجابة تحتوي على 50 رمزاً عبء عمل يتركّز في مرحلة prefill. ويُعدّ طلب يحتوي على 200 رمز وإجابة تحتوي على 2,000 رمز عبء عمل يتركّز في مرحلة decode. يعرض الخادم نفسه عدداً مختلفاً جداً من الرموز في الثانية لهذين النوعين، لذلك اختر نسبة واحدة، واكتبها بجانب كل رقم تسجّله، ولا تقارن أبداً بين نسب مختلفة. يُعدّ استخدام 1,024 رمزاً للإدخال و1,024 رمزاً للإخراج قيمة افتراضية مناسبة، لأن عدة مورّدين ينشرون نتائج بهذه النسبة. إذا كنت تعرف شكل حركة الشبكة الفعلي لديك، فاستخدمه.

ثبّت طول الإخراج أيضاً. عندما يصل النموذج إلى رمز التوقف بعد 60 رمزاً، تكون الجولة أقصر ولا يمكن مقارنتها بجولة كاملة؛ إذ تصبح قيمة TTFT جزءاً أكبر منها، ما يخفض معدل نقل الإخراج كما يحسبه الاختبار، رغم أن كل طلب يكتمل في وقت أقصر. يتيح الخيار --ignore-eos في عميل اختبار vLLM أن يُنشئ كل طلب العدد المطلوب من الرموز بالضبط، وبذلك تظل جولتان قابلتين للمقارنة. يؤثر اختيار النموذج في هذه الأرقام أكثر من أي خيار آخر: يشرح تشغيل نموذج Qwen 3 على GPU واحد في VPS جانب الذاكرة من هذا الاختيار.

قياس تدفق واحد أولاً

ابدأ بالحالة الأبسط. هذا فحص سلامة، وهو يمثل الحد الأقصى للأداء. يطبع Ollama توقيتاته الخاصة.

ollama run llama3.1:8b --verbose "Write 200 words about disk scheduling."

السطر الذي يجب قراءته هو eval rate، وهو يمثل عدد الرموز (tokens) الناتجة في الثانية. prompt eval rate هو معدل التعبئة المسبقة (prefill rate)، وload duration هو الوقت المستغرق لتحميل النموذج في ذاكرة VRAM. في أول استدعاء بعد تشغيل بارد، يكون load duration كبيراً، لذا يكون total duration مضللاً. نفّذ الأمر مرتين واقرأ النتيجة الثانية. يقوم Ollama بإلغاء تحميل النموذج الخامل بعد خمس دقائق افتراضياً، لذا فإن التوقف الطويل بين التشغيلين يعيدك إلى حالة التشغيل البارد.

تأتي نفس الحقول من واجهة برمجة التطبيقات (API)، وهو أمر أسهل في البرمجة النصية.

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "Write 200 words about disk scheduling.",
  "stream": false
}' | jq '{eval_count, eval_duration,
         tok_s: (.eval_count / (.eval_duration / 1000000000))}'

eval_duration هو بالنانو ثانية، لذا فإن القسمة على 1,000,000,000 تعطي الثواني. هذه القسمة هي بالضبط ما توصي به وثائق API الخاصة بـ Ollama لحساب الرموز في الثانية. إذا لم يكن الخادم جاهزاً بعد، فإن استضافة LLM ذاتياً باستخدام Ollama على خادم VPS تغطي التثبيت ووحدة systemd.

يحتاج مقياس TTFT إلى طلب تدفق (streaming request)، ويمكن لـ curl قياس ذلك نيابة عنك.

curl -s -o /dev/null -N \
  -w 'ttfb=%{time_starttransfer}s  total=%{time_total}s\n' \
  http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"Qwen/Qwen3-8B",
       "messages":[{"role":"user","content":"Write 200 words about disk scheduling."}],
       "stream":true,"max_tokens":256}'

time_starttransfer هو اللحظة التي يصل فيها أول بايت من نص الاستجابة. في إكمال محادثة متدفق، ينتمي هذا البايت إلى أول حدث مرسل من الخادم، وهو إما أول رمز محتوى أو دلتا خاصة بالدور تُرسل قبله مباشرة. لذا تعامل مع القيمة كـ TTFT مع هامش خطأ حدث واحد. إنها دقيقة بما يكفي لمقارنة تشغيلين على نفس الخادم.

أرقام التدفق الواحد تجمّل أداء الجهاز مرتين. قيمة TTFT هي الأفضل على الإطلاق، لأنه لا يوجد شيء في قائمة الانتظار أمامك. ومعدل التدفق لكل طلب هو الأفضل على الإطلاق، لأن البطاقة بأكملها تخدم طلباً واحداً. لا يخبرك أي منهما بما يمكن للجهاز تحمله فعلياً.

كيف تُجري اختبار تزايد التزامن؟

يشغّل الاختبار عبء عمل ثابتاً مع زيادة التزامن، ويسجّل ما يحدث عند كل خطوة. يوفّر vLLM العميل اللازم لذلك، وهو يستخدم OpenAI API، لذا يعمل أيضاً مع Ollama وأي خدمة أخرى متوافقة مع OpenAI.

vllm bench serve \
  --backend openai-chat \
  --base-url http://127.0.0.1:8000 \
  --endpoint /v1/chat/completions \
  --model Qwen/Qwen3-8B \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 1024 \
  --ignore-eos \
  --num-prompts 160 \
  --max-concurrency 16 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,99

يحدّد --max-concurrency عدد الطلبات قيد التنفيذ، وهو المتغير الذي تزيده في الاختبار. يمثّل --num-prompts العدد الإجمالي للطلبات المرسلة، لذا اجعله قريباً من عشرة أضعاف التزامن للحصول على متوسط مستقر. يعرض الملخص Output token throughput (tok/s): وTotal token throughput (tok/s):، ثم Mean TTFT (ms): وMedian TTFT (ms): وP99 TTFT (ms): تحت العنوان Time to First Token.

لا يعرض ذلك الناتج معدل كل تدفق، لكن يمكنك حسابه بقسمة واحدة. يمثّل Mean TPOT (ms): متوسط الزمن اللازم لكل رمز ناتج بعد الرمز الأول، لذا يعني 25 ms لكل رمز 40 رمزاً في الثانية لكل تدفق. وتعطي قسمة معدل إخراج الرموز على التزامن النتيجة نفسها.

بعد ذلك، كرّر الاختبار واحفظ ناتج كل تشغيل.

for C in 1 4 16 32 64 128; do
  vllm bench serve \
    --backend openai-chat \
    --base-url http://127.0.0.1:8000 \
    --endpoint /v1/chat/completions \
    --model Qwen/Qwen3-8B \
    --dataset-name random \
    --random-input-len 1024 \
    --random-output-len 1024 \
    --ignore-eos \
    --num-prompts $(( C * 10 )) \
    --max-concurrency "$C" \
    --percentile-metrics ttft,tpot,itl,e2el \
    --metric-percentiles 50,99 \
    --save-result --result-filename "sweep-c$C.json"
done
قراءة ملفات JSON المحفوظة

ينشئ كل تشغيل ملفاً واحداً، لذا استخرج الحقول التي تهمك من جميع الملفات دفعة واحدة.

for f in sweep-c*.json; do
  jq -r --arg f "$f" \
    '[$f, .output_throughput, .total_token_throughput,
      .median_ttft_ms, .p99_ttft_ms] | @tsv' "$f"
done

يمثّل output_throughput عدد الرموز الناتجة في الثانية. يضيف total_token_throughput رموز الإدخال، لذا يكون قريباً من الضعف عند استخدام نسبة 1:1. كان p99_ttft_ms سيظهر حتى من دون --metric-percentiles، لأن القيمة الافتراضية لذلك الخيار هي 99. تضيف القيمة 50 في الأمر p50_ttft_ms بجانب median_ttft_ms إلى كل مقياس مذكور في --percentile-metrics. إذا طلبت مئيناً لم تطلبه، مثل .p90_ttft_ms، فسيطبع jq القيمة null.

ما الذي يُظهره مسح التزامن فعلياً؟

رسم بيانيIllustrative sweep shape: 8B model, one 24 GB GPU, 1024 in / 1024 out
البيانات وراء هذا الرسم البياني
[
  {
    "label": "1 stream",
    "per_stream_tok_s": 92,
    "total_tok_s": 92,
    "ttft_p50_ms": 48,
    "ttft_p99_ms": 61
  },
  {
    "label": "4 streams",
    "per_stream_tok_s": 88,
    "total_tok_s": 352,
    "ttft_p50_ms": 71,
    "ttft_p99_ms": 96
  },
  {
    "label": "16 streams",
    "per_stream_tok_s": 71,
    "total_tok_s": 1136,
    "ttft_p50_ms": 152,
    "ttft_p99_ms": 244
  },
  {
    "label": "32 streams",
    "per_stream_tok_s": 54,
    "total_tok_s": 1728,
    "ttft_p50_ms": 287,
    "ttft_p99_ms": 498
  },
  {
    "label": "64 streams",
    "per_stream_tok_s": 34,
    "total_tok_s": 2176,
    "ttft_p50_ms": 611,
    "ttft_p99_ms": 1240
  },
  {
    "label": "128 streams",
    "per_stream_tok_s": 18,
    "total_tok_s": 2304,
    "ttft_p50_ms": 1490,
    "ttft_p99_ms": 3820
  }
]

توضّح الصفوف 6 شكل النتائج التي ينتجها المسح على جهاز GPU صغير قابل للاستئجار، وبمراتب مقدار معقولة. وهي لا تقيس خادمك، وليست رقماً من مورّد. شغّل الحلقة أعلاه واستبدلها بنتائجك.

اقرأ الشكل، لأن الشكل هو ما يمكن تعميمه. عند تدفق واحد، ينتج الجهاز بأكمله 92 رمزاً في الثانية، مع p99 TTFT يبلغ 61 ms. عند 128 streams، يصل الإجمالي إلى 2304 رمزاً في الثانية، أي أعلى بخمسة وعشرين ضعفاً، بينما ينخفض معدل كل تدفق على حدة إلى 18 رمزاً في الثانية، ويصل p99 TTFT إلى 3820 ms. يرتفع معدل النقل الإجمالي لأن التجميع يحوّل فترات انتظار الذاكرة الخاملة إلى عمل مفيد. وينخفض معدل كل تدفق لأن موارد الحوسبة نفسها أصبحت مشتركة.

التضاعف الأخير هو المؤشر الحاسم. فالانتقال من 64 إلى 128 تدفقاً يضيف أقل من ستة بالمئة إلى الإجمالي، بينما يتضاعف p99 TTFT ثلاث مرات تقريباً. وهذا يعني أن الطلبات تنتظر في الطابور بدلاً من تنفيذها، إما لأن ذاكرة KV cache ممتلئة، أو لأن الخادم بلغ حداً لجدولة الطلبات مثل max_num_seqs في vLLM. نقطة التشغيل المفيدة تسبق ذلك: عند 32 تدفقاً، لا يزال الجهاز يعيد 1728 رمزاً في الثانية، أي 75 بالمئة من ذروة الأداء، بمعدل 54 رمزاً في الثانية لكل تدفق، وp99 TTFT يبلغ 498 ms. أبلغ عن هذه النقطة باعتبارها سعتك. أما ذروة المنحنى فهي رقم لا يمكنك تقديم الخدمة للمستخدمين عنده.

Ollama وvLLM لا يقيسان الشيء نفسه

نفّذ ذلك الاختبار على خادم Ollama بالإعدادات الافتراضية، ولن يتغير الإجمالي إلا قليلاً. القيمة الافتراضية لـ OLLAMA_NUM_PARALLEL هي 1، لذلك يُنفَّذ طلب واحد بينما تنتظر الطلبات الأخرى. وتؤدي قائمة الانتظار إلى ارتفاع p99 TTFT، بينما يبقى إجمالي الإخراج ثابتاً. ارفع هذه القيمة قبل أن تقيس أي شيء.

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_NUM_PARALLEL=8"

أعد التشغيل باستخدام sudo systemctl restart ollama، ثم تأكد من أن النموذج ما زال يتسع في الذاكرة. تحصل كل فتحة متوازية على حصتها من نافذة السياق، لذلك توضّح وثائق Ollama أن سياقاً بحجم 2K مع 4 طلبات متوازية يخصص 8K. ارفع عدد الفتحات بدرجة كبيرة، فيخرج النموذج من VRAM. افحص ollama ps: إذا كان العمود PROCESSOR يقرأ قيمة مثل 48%/52% CPU/GPU، فهذا يعني أن جزءاً من النموذج موجود على CPU، وعندها سينخفض معدل النقل كلما أضفت التزامناً بدلاً من أن يرتفع. بعد تجاوز عدد الفتحات المتوازية، تُوضَع الطلبات في قائمة انتظار تصل إلى OLLAMA_MAX_QUEUE، وقيمتها الافتراضية 512، وبعد ذلك يجيب الخادم بالرمز 503.

يستخدم vLLM التجميع المستمر، لذلك يضيف الطلبات الجديدة إلى التجميعة قيد التشغيل عند توفر الفتحات. ويستمر منحناه في الارتفاع إلى أن ينفد أحد الموارد: عادةً ذاكرة KV cache، مع أن حداً مضبوطاً مثل max_num_seqs أو الحمل الإضافي لجدولة CPU قد يجعله يستقر عند مستوى أقل. يركّز Ollama على نموذج واحد وجهاز واحد وتكلفة إعداد منخفضة. لذلك يعطي المحركان إجابات مختلفة للاختبار نفسه، وهذا هو الموضوع الفعلي في مقارنة Ollama وvLLM كمحركي تقديم. سجّل المحرك والإصدار اللذين أنتجا كل قيمة.

خمس طرق لقياس الشيء الخطأ

  • العميل بعيد. تؤدي الاختبارات المعيارية من حاسوبك المحمول عبر الإنترنت إلى إضافة زمن رحلة الاتصال ذهاباً وإياباً إلى كل قيمة TTFT، ولذلك فأنت تقيس اتصالك المنزلي. شغّل العميل في المنطقة نفسها التي يوجد فيها الخادم.
  • كان النموذج في حالة باردة. يتحمل الطلب الأول تكلفة تحميل الأوزان، وقد يتحمل أيضاً تكلفة التقاط الرسم البياني في vLLM. أرسل دفعة تهيئة، ثم تجاهل نتيجتها.
  • أجاب التخزين المؤقت للبادئة نيابةً عنك. يفعّل vLLM التخزين المؤقت التلقائي للبادئة افتراضياً، ولذلك فإن إرسال الموجّه نفسه مراراً يقيس التخزين المؤقت بدلاً من مرحلة prefill، وينخفض TTFT إلى جزء من قيمته الفعلية. يتجنب --dataset-name random ذلك لأن كل موجّه يختلف عن الآخر. وللتأكد، شغّل الخادم باستخدام --no-enable-prefix-caching.
  • كانت المخرجات قصيرة. مع إجابات تتكون من 32 رمزاً، يهيمن TTFT على كل طلب، ويصف معدل الرموز في الثانية لديك مرحلة prefill فعلياً. استخدم --ignore-eos مع طول مخرجات واقعي.
  • أبلغت عن التزامن 1 فقط. فهو يوفّر أفضل TTFT في الجدول، ولا يكون مدخل التكلفة الصحيح إلا إذا كانت طلباتك الفعلية لا تتداخل أبداً. إذا تداخلت، تعتمد التكلفة على معدل النقل الذي تحافظ عليه عند مستوى التزامن الذي تنتجه حركة المرور لديك فعلياً، ولذلك قِس الأداء عند ذلك المستوى أيضاً.

حوّل الرقم المقاس إلى قرار

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

cost_per_million_output = price_out + price_in * (input_tokens / output_tokens)
break_even_tok_s = (price_per_hour / cost_per_million_output) * 1000000 / 3600

طبّق ذلك على أسعار DigitalOcean في يوليو 2026. كان سعر نقطة الاستدلال المخصصة H200 لديهم $4.47 في الساعة، وكان سعر Llama 3.3 70B بلا خادم $0.65 لكل مليون رمز إدخال و$0.65 لكل مليون رمز إخراج. عند نسبة 1:1 المستخدمة أعلاه، يجلب كل مليون رمز ناتج معه مليون رمز إدخال، لذا يصبح السعر الفعلي $1.30 لكل مليون رمز ناتج. وبذلك، فإن قسمة 4.47 على 1.30 تساوي نحو 3.44 مليون رمز ناتج في الساعة، وقسمتها على 3,600 ثانية تعطي نحو 955 رمزاً ناتجاً في الثانية، أو نحو 1,910 رمزاً في الثانية عند احتساب الإدخال والإخراج معاً. هذه الأسعار من DigitalOcean، أما القسمة فمن حسابنا. عندما تحقّقنا في 25 October 2026، ظل سعر نقطة H200 هو $4.47 في الساعة، لكن DigitalOcean أوقفت Llama 3.3 70B بلا خادم في 18 August 2026، وتوجّه المستخدمين إلى Llama 4 Maverick، المدرج بسعر $0.25 لكل مليون رمز إدخال و$0.87 لكل مليون رمز إخراج. هذا نموذج مختلف، لذلك يحتاج إلى اختبار تزايد خاص به قبل أن تصبح المقارنة ذات معنى.

الكلمة الحاسمة هنا هي المستمر. إن بلوغ 955 رمزاً ناتجاً في الثانية عند التشبع لمدة ساعتين يومياً لا يعني تحقيق 955 رمزاً ناتجاً في الثانية بشكل مستمر، لأنك تدفع تكلفة الساعات الاثنتين والعشرين الأخرى أيضاً. ولا يؤدي استئجار البطاقة كـGPU Droplet إلى خفض الحد المطلوب. ففي 25 October 2026، أدرج تسعير Droplet لدى DigitalOcean بطاقة H200 بسعر $4.47 في الساعة عند الطلب، وهو السعر نفسه لنقطة الاستدلال، كما أن أرخص NVIDIA Droplets لديهم، وهي RTX 4000 بسعر $0.76 في الساعة وL40S أو RTX 6000 بسعر $1.57 في الساعة، صغيرة جداً لتشغيل نموذج 70B بتنسيق FP8. لذلك، وفق الأرقام أعلاه، يجب أن يحقق H200 الذي يبلغ ذروة التشبع فيه 2,036 رمزاً ناتجاً في الثانية متوسطاً يقارب 47 بالمئة من هذه الذروة خلال كل ساعة تدفع ثمنها، وذلك لمعادلة سعر $0.65 لكل مليون رمز إدخال وإخراج. وأقل من ذلك، يفوز السعر لكل رمز. عادةً ما تؤدي ساعات GPU الخاملة، لا الرموز البطيئة، إلى فشل الاستضافة الذاتية.

إذن، يعتمد قرارك على مدخلين. يمنحك الاختبار الحد الأقصى. ويحدد نمط حركة المرور لديك النسبة التي تحصل عليها فعلياً من هذا الحد. اضربهما، ثم انقل النتيجة إلى مقارنة نقطة تعادل GPU VPS مع API ذي التسعير لكل رمز واقرأ النتيجة الخاصة بحجمك.

FAQ

ما المعدل الجيد للتوكنات في الثانية لنموذج LLM مستضاف ذاتياً؟

هناك إجابتان، لأن هذا المقياس يؤدي وظيفتين. إذا كان شخص واحد يقرأ المخرجات، فإن أي معدل يتجاوز تقريباً 20 توكناً مخرجاً في الثانية لكل تدفق يكون أسرع من سرعة القراءة، ولذلك لا تعود الزيادة مفيدة. أما من ناحية التكلفة، فالرقم المهم هو إجمالي معدل المخرجات الذي يمكنك الحفاظ عليه تحت الحمل الفعلي، ويكون المعدل جيداً عندما يتجاوز نقطة التعادل لديك. عند سعر $0.65 لكل مليون توكن، للإدخال والإخراج معاً، وعلى خادم تكلفته $4.47 في الساعة، تبلغ نقطة التعادل نحو 955 توكناً مخرجاً في الثانية بشكل مستمر عند نسبة 1:1 وبأسعار July 2026. لا يصل إليها تدفق واحد على نموذج كبير، ولذلك تُستخدم المعالجة الدفعية.

لماذا يبقى معدل Ollama ثابتاً عند إضافة طلبات متزامنة؟

تكون قيمة OLLAMA_NUM_PARALLEL الافتراضية هي 1، لذلك يعالج الخادم طلباً واحداً في كل مرة لكل نموذج، ويضع بقية الطلبات في قائمة انتظار، حتى حد OLLAMA_MAX_QUEUE (ويكون 512 افتراضياً)، ثم يعيد الحالة 503. يبقى إجمالي المخرجات ثابتاً بينما يرتفع p99 TTFT، وهذا يدل على وجود قائمة انتظار لا على انشغال GPU. اضبط المتغير في ملف drop-in لـsystemd وأعد التشغيل، ثم تحقق من ollama ps، لأن كل خانة معالجة متوازية تضاعف السياق المخصص وقد تدفع جزءاً من النموذج إلى CPU.

هل ينبغي أن أقيس زمن الوصول إلى أول توكن أم عدد التوكنات في الثانية؟

قِس كليهما، لأنهما يتحركان في اتجاهين متعاكسين مع ارتفاع الحمل. إن TTFT هو ما يشعر به المستخدم، بينما يعكس معدل المخرجات عند التشبع ما يظهر في فاتورتك. سجّل p50 وp99 لـTTFT عند كل درجة من التزامن، ثم اختر أعلى درجة تزامن يظل عندها p99 لـTTFT مقبولاً لك. أبلغ عن معدل النقل عند تلك النقطة باعتباره سعتك، لا عن الحد الأقصى في أعلى المنحنى.

هل يعني ارتفاع معدل التوكنات في الثانية دائماً انخفاض التكلفة لكل توكن؟

لا. تُحسب التكلفة لكل توكن بقسمة السعر بالساعة على عدد التوكنات التي أنتجها الخادم فعلياً خلال تلك الساعة، ولذلك يظل الخادم السريع ذا تكلفة مرتفعة لكل توكن إذا كان خاملاً معظم اليوم. الاستخدام هو العامل الحاسم، لا السرعة القصوى. انتبه أيضاً إلى الوحدات: إجمالي معدل نقل التوكنات المعلن يشمل توكنات الإدخال، ولذلك يقترب من ضعف معدل الإخراج عند نسبة إدخال إلى إخراج تبلغ 1:1. إذا كانت واجهة API التي تقارن بها تحاسب على توكنات الإدخال والإخراج معاً، فسعّر الجزأين قبل المقارنة.

هل كان هذا المقال مفيدًا؟

#benchmarking#tokens-per-second#vllm#ollama#gpu-vps