SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-08-13

محاسبه دقیق توکن در ثانیه برای بهینه‌سازی هزینه GPU

اجاره GPU تنها زمانی از API به‌صرفه‌تر است که نرخ خروجی از حد مشخصی بگذرد. با اجرای تست concurrency sweep و اندازه‌گیری دقیق توکن در ثانیه، صرفه اقتصادی سرور خود را بسنجید.

چرا تعداد توکن در ثانیه تعیین‌کننده صرفه اقتصادی GPU است

تعداد توکن در ثانیه (Tokens per second)، نرخ تولید متن خروجی توسط سرور شماست و عددی است که تعیین می‌کند آیا اجاره یک GPU ارزان‌تر از پرداخت هزینه به ازای هر توکن در API است یا خیر. هزینه یک سرور GPU به صورت ساعتی محاسبه می‌شود، فارغ از اینکه مشغول باشد یا بیکار. در مقابل، هزینه APIهای میزبانی‌شده بر اساس تعداد توکن محاسبه می‌شود. بنابراین، استفاده از GPU تنها زمانی صرفه اقتصادی دارد که نرخ خروجی بالایی را در اکثر ساعات اجاره‌ای حفظ کنید.

این یعنی شما به یک اندازه‌گیری دقیق نیاز دارید، نه عددی که از منابع دیگر می‌خوانید. این صفحه چهار عددی را که ارزش ثبت دارند تعریف می‌کند، سپس دستوراتی را ارائه می‌دهد که این اعداد را تولید می‌کنند و در نهایت محاسباتی را شرح می‌دهد که آن‌ها را به یک تصمیم‌گیری نهایی تبدیل می‌کند.

چرا عدد توکن در ثانیه منتشرشده، عدد واقعی شما نیست

DigitalOcean در ژوئیه 2026 ارقام توان عملیاتی (throughput) را برای یک NVIDIA H200 که در حال اجرای llama3.3-70b-instruct با فرمت FP8 (ممیز شناور 8 بیتی) تحت vLLM است، منتشر کرد. این ارقام مفید هستند اما متعلق به شما نیستند.

ChartPublished DigitalOcean H200 figures, llama3.3-70b-instruct FP8, July 2026
The data behind this chart
[
  {
    "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 توکن در ثانیه تولید می‌کند، بنابراین عدد اشباع‌شده (saturated) در سخت‌افزار مشابه، بیش از چهل برابر بیشتر است. این شکاف به این دلیل وجود دارد که یک مرحله Decode، پردازنده گرافیکی (GPU) را در بیشتر زمان خود در انتظار حافظه نگه می‌دارد و درخواست‌های همزمان، این زمان‌های بیکاری را پر می‌کنند. ردیف دوم، یعنی 236 توکن در ثانیه، مربوط به یک H100 روی همان مدل است که توسط KV cache (حافظه کلید و مقدار؛ حافظه اختصاصی هر درخواست که مکالمه در حال اجرا روی کارت نگه می‌دارد) محدود شده است. یک کارت 80 گیگابایتی، درخواست‌های همزمان کمتری را برای یک مدل 70B نگه می‌دارد، بنابراین زودتر به نقطه اشباع می‌رسد.

مدل را تغییر دهید یا نسبت ورودی به خروجی را عوض کنید تا تمام اعداد بالا تغییر کنند. ارقام منتشرشده انتظارات شما را تعیین می‌کنند، نه بودجه شما را؛ این همان قاعده‌ای است که در بنچمارک صادقانه یک VPS برای دیسک و شبکه نیز صدق می‌کند.

چهار عدد کلیدی

  • زمان تا اولین توکن (TTFT): تأخیر بین ارسال درخواست و دریافت اولین توکن خروجی. این مقدار مجموع زمان پیش‌پر کردن (prefill) و زمان قرارگیری در صف است. کاربر این مورد را مستقیماً حس می‌کند.
  • تعداد توکن‌های خروجی در ثانیه، برای هر جریان: سرعت نوشتن یک پاسخ پس از شروع تولید آن. بالاتر از حدود 20 توکن بر ثانیه، سرعت از توان خواندن اکثر افراد فراتر می‌رود؛ بنابراین افزایش بیشتر سرعت در اینجا دستاورد ناچیزی دارد.
  • مجموع توان عملیاتی خروجی در حالت اشباع: مجموع تمام جریان‌های همزمان در زمانی که سرور کاملاً تحت بار است. این عدد نشان‌دهنده ظرفیت است و همان معیاری است که هزینه‌های GPU را توجیه می‌کند.
  • مقادیر p50 و p99 برای TTFT تحت شرایط همزمانی: مقدار p50 نشان‌دهنده درخواست میانی است. مقدار p99 عددی است که 99 درصد از درخواست‌ها زیر آن قرار می‌گیرند. تأثیر صف همیشه ابتدا در p99 نمایان می‌شود.

دو مورد اول زمانی بهبود می‌یابند که سرور خلوت باشد. مورد سوم زمانی بهبود می‌یابد که سرور پرکار باشد. این معیارها در تضاد با یکدیگر هستند و به همین دلیل است که هیچ عدد واحدی نمی‌تواند عملکرد یک سرور سرویس‌دهنده را به‌طور کامل توصیف کند.

پیش از اندازه‌گیری، طول ورودی و خروجی را اصلاح کنید

میزان throughput به شکل ترافیک بستگی دارد. یک prompt با 4,000 توکن و پاسخ 50 توکنی، کاری است که فشار اصلی آن بر مرحله prefill است. یک prompt با 200 توکن و پاسخ 2,000 توکنی، کاری است که فشار اصلی آن بر مرحله decode است. یک سرور واحد برای این دو حالت، مقادیر بسیار متفاوتی از توکن در ثانیه گزارش می‌دهد؛ بنابراین یک نسبت را انتخاب کنید، آن را کنار هر عددی که ثبت می‌کنید بنویسید و هرگز نتایج نسبت‌های مختلف را با هم مقایسه نکنید. نسبت 1,024 توکن ورودی به 1,024 توکن خروجی یک پیش‌فرض منطقی است، زیرا چندین فروشنده نتایج خود را با این نسبت منتشر می‌کنند. اگر ترافیک واقعی خود را می‌شناسید، از همان استفاده کنید.

طول خروجی را نیز اجباری کنید. مدلی که پس از 60 توکن به stop token خود می‌رسد، اجرای کوتاه‌تری ارائه می‌دهد که سریع‌تر به نظر می‌رسد، زیرا در این حالت TTFT سهم بزرگ‌تری از زمان کل را تشکیل می‌دهد. فلگ --ignore-eos در کلاینت بنچمارک vLLM باعث می‌شود هر درخواست دقیقاً به تعداد مشخص‌شده تولید کند، بنابراین دو اجرا با هم قابل مقایسه باقی می‌مانند. انتخاب مدل بیش از هر فلگی روی این اعداد تأثیر می‌گذارد: جای‌گذاری مدل Qwen 3 روی یک GPU در VPS جنبه‌های حافظه این انتخاب را پوشش می‌دهد.

اندازه‌گیری یک جریان (stream) در ابتدا

با ساده‌ترین حالت شروع کنید. این یک بررسی سلامت (sanity check) و تعیین سقف توانایی است. Ollama زمان‌بندی‌های خود را چاپ می‌کند.

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

خطی که باید خوانده شود eval rate است که نشان‌دهنده تعداد توکن‌های خروجی در ثانیه است. prompt eval rate نرخ پیش‌پردازش (prefill) و load duration زمان صرف‌شده برای بارگذاری مدل در VRAM است. در اولین فراخوانی پس از یک شروع سرد (cold start)، مقدار load duration بزرگ است، بنابراین total duration گمراه‌کننده خواهد بود. دستور را دو بار اجرا کنید و نتیجه دوم را بخوانید. Ollama به‌صورت پیش‌فرض مدل‌های غیرفعال را پس از 5 دقیقه از حافظه خارج می‌کند، بنابراین وقفه طولانی بین اجراها شما را به حالت شروع سرد بازمی‌گرداند.

همین فیلدها از طریق 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 مراحل نصب و unit مربوط به systemd را پوشش می‌دهد.

برای اندازه‌گیری TTFT به یک درخواست streaming نیاز دارید و 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 لحظه‌ای است که اولین بایت از بدنه پاسخ دریافت می‌شود. در یک تکمیل چت (chat completion) به صورت streaming، آن بایت متعلق به اولین رویداد ارسالی از سمت سرور (server-sent event) است که یا اولین توکن محتواست و یا یک delta فقط شامل نقش (role) که درست پیش از آن ارسال شده است. بنابراین این مقدار را با تقریب یک رویداد، همان TTFT در نظر بگیرید. این مقدار برای مقایسه دو اجرا روی یک سرور به اندازه کافی دقیق است.

اعداد مربوط به تک‌جریان (single-stream)، عملکرد سخت‌افزار را بیش از حد واقعی نشان می‌دهند. مقدار TTFT در بهترین حالت ممکن است، زیرا هیچ درخواستی پیش از شما در صف قرار ندارد. نرخ هر جریان نیز در بهترین حالت خود است، زیرا کل کارت گرافیک در حال سرویس‌دهی به یک درخواست است. هیچ‌کدام از این‌ها نشان نمی‌دهند که این سخت‌افزار در عمل چه ظرفیتی دارد.

چگونه یک concurrency sweep اجرا کنیم؟

یک sweep یک workload ثابت را با افزایش سطح هم‌زمانی (concurrency) اجرا کرده و نتایج هر مرحله را ثبت می‌کند. 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 تعداد درخواست‌های در حال اجرا (in-flight) را محدود می‌کند و همان متغیری است که در sweep تغییر می‌دهید. --num-prompts تعداد کل درخواست‌های ارسالی است؛ بنابراین برای دستیابی به یک میانگین پایدار، آن را حدود ده برابر مقدار concurrency نگه دارید. خروجی خلاصه، مقادیر Output token throughput (tok/s): و Total token throughput (tok/s): و سپس Mean TTFT (ms):، Median TTFT (ms): و P99 TTFT (ms): را در زیر عنوان Time to First Token چاپ می‌کند.

در این خروجی، نرخ به ازای هر stream وجود ندارد، اما با یک تقسیم ساده به دست می‌آید. Mean TPOT (ms): میانگین زمان برای هر توکن خروجی پس از توکن اول است؛ بنابراین 25 میلی‌ثانیه به ازای هر توکن، معادل 40 توکن در ثانیه برای هر stream است. تقسیم throughput خروجی بر concurrency نیز همین نتیجه را می‌دهد.

سپس این فرآیند را در یک حلقه قرار دهید و هر اجرا را ذخیره کنید.

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 بوده است؛ اگر درخواستی برای درصدی (percentile) که تعیین نکرده‌اید ارسال کنید، jq مقدار null را چاپ می‌کند.

بررسی هم‌زمانی (concurrency sweep) دقیقاً چه چیزی را نشان می‌دهد؟

ChartIllustrative sweep shape: 8B model, one 24 GB GPU, 1024 in / 1024 out
The data behind this chart
[
  {
    "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 ردیف، تصویری از شکلی است که یک sweep روی یک سرور GPU کوچک و اجاره‌ای در مقیاس‌های احتمالی ایجاد می‌کند. این‌ها اندازه‌گیری سرور شما نیستند و ارقام تبلیغاتی فروشنده نیز محسوب نمی‌شوند. حلقه بالا را اجرا کنید و مقادیر خود را جایگزین آن‌ها کنید.

شکل نمودار را بخوانید، زیرا این شکل است که تعمیم‌پذیر است. در یک جریان (stream)، کل سرور 92 توکن در ثانیه با p99 TTFT معادل 61 میلی‌ثانیه تولید می‌کند. در 128 streams، مجموع به 2304 توکن در ثانیه می‌رسد که بیست و پنج برابر بیشتر است، در حالی که هر جریان جداگانه به 18 توکن در ثانیه کاهش می‌یابد و p99 TTFT به 3820 میلی‌ثانیه می‌رسد. توان عملیاتی کل افزایش می‌یابد زیرا دسته‌بندی (batching)، زمان‌های انتظار بیهوده حافظه را به کار مفید تبدیل می‌کند. سرعت هر جریان کاهش می‌یابد زیرا توان پردازشی اکنون به اشتراک گذاشته شده است.

آخرین دوبرابر شدن، نکته کلیدی است. افزایش از 64 به 128 جریان، کمتر از شش درصد به مجموع اضافه می‌کند در حالی که p99 TTFT تقریباً سه برابر می‌شود؛ این یعنی حافظه KV پر شده و درخواست‌ها به جای اجرا شدن، در صف انتظار می‌مانند. نقطه عملیاتی مفید، پیش از این مرحله است: در 32 جریان، سرور همچنان 1728 توکن در ثانیه (75 درصد اوج توان خود) را با سرعت 54 توکن در ثانیه برای هر جریان و p99 TTFT معادل 498 میلی‌ثانیه ارائه می‌دهد. این نقطه را به عنوان ظرفیت خود گزارش کنید. اوج منحنی، عددی است که نمی‌توانید به کاربران سرویس‌دهی کنید.

Ollama و vLLM معیارهای یکسانی را اندازه‌گیری نمی‌کنند

این تست را روی یک سرور پیش‌فرض Ollama اجرا کنید؛ خواهید دید که مجموع خروجی تغییر چندانی نمی‌کند. مقدار OLLAMA_NUM_PARALLEL به‌صورت پیش‌فرض روی 1 تنظیم شده است، بنابراین در حالی که یک درخواست اجرا می‌شود، بقیه در انتظار می‌مانند. همین صف باعث می‌شود p99 TTFT افزایش یابد، در حالی که مجموع خروجی ثابت می‌ماند. پیش از هرگونه اندازه‌گیری، این مقدار را افزایش دهید.

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

سرویس را با sudo systemctl restart ollama مجدداً راه‌اندازی کنید و سپس مطمئن شوید که مدل همچنان در حافظه جا می‌شود. هر اسلات موازی، سهم خاص خود را از پنجره کانتکست (context window) اشغال می‌کند؛ بنابراین مستندات Ollama اشاره می‌کنند که کانتکست 2K با 4 درخواست موازی، در مجموع 8K فضا اشغال می‌کند. اگر تعداد اسلات‌ها را بیش از حد افزایش دهید، مدل از VRAM خارج می‌شود. وضعیت ollama ps را بررسی کنید: اگر ستونی مانند PROCESSOR مقداری شبیه به 48%/52% CPU/GPU را نشان دهد، به این معنی است که بخشی از مدل روی CPU قرار گرفته است. در این حالت، با افزایش هم‌زمانی (concurrency)، نرخ خروجی (throughput) به‌جای افزایش، کاهش می‌یابد. پس از پر شدن اسلات‌های موازی، درخواست‌ها در صف OLLAMA_MAX_QUEUE قرار می‌گیرند (که به‌صورت پیش‌فرض 512 است) و پس از آن، سرور خطای 503 برمی‌گرداند.

vLLM از continuous batching استفاده می‌کند؛ بنابراین به محض آزاد شدن اسلات‌ها، درخواست‌های جدید را به بچ (batch) در حال اجرا اضافه می‌کند و نمودار عملکرد آن تا زمانی که KV cache تمام نشود، به صعود ادامه می‌دهد. Ollama برای یک مدل، یک ماشین و هزینه راه‌اندازی پایین بهینه‌سازی شده است. به همین دلیل، این دو موتور پاسخ‌های متفاوتی به یک تست یکسان می‌دهند که موضوع اصلی مقایسه Ollama و vLLM به عنوان موتورهای سرویس‌دهی است. حتماً ثبت کنید که هر عدد توسط کدام موتور و کدام نسخه تولید شده است.

پنج روش برای اندازه‌گیری شاخص‌های اشتباه

  • کلاینت در فاصله دوری قرار دارد. بنچ‌مارک گرفتن از لپ‌تاپ شخصی از طریق اینترنت، زمان رفت‌وبرگشت (RTT) شما را به هر TTFT اضافه می‌کند؛ بنابراین شما در واقع کیفیت اتصال اینترنت خود را اندازه‌گیری می‌کنید. کلاینت را در همان منطقه‌ای (region) اجرا کنید که سرور در آن قرار دارد.
  • مدل در حالت سرد (cold) بوده است. اولین درخواست شامل بارگذاری وزن‌ها (weight loading) است و در vLLM ممکن است شامل capture کردن گراف نیز باشد. یک batch گرم‌کننده (warmup) ارسال کنید و نتیجه آن را نادیده بگیرید.
  • کش پیشوند (prefix caching) به جای شما پاسخ داده است. vLLM به‌طور پیش‌فرض قابلیت automatic prefix caching را فعال می‌کند؛ بنابراین ارسال مکرر یک prompt مشابه، به جای اندازه‌گیری prefill، باعث اندازه‌گیری کش می‌شود و TTFT به کسری از مقدار واقعی کاهش می‌یابد. --dataset-name random از این مسئله جلوگیری می‌کند زیرا هر prompt متفاوت است. برای اطمینان، سرور را با --no-enable-prefix-caching راه‌اندازی کنید.
  • خروجی‌ها کوتاه بوده‌اند. با پاسخ‌های 32 توکنی، TTFT بر هر درخواست غلبه می‌کند و شاخص tokens per second شما در واقع فقط prefill را توصیف می‌کند. از --ignore-eos با طول خروجی واقع‌بینانه استفاده کنید.
  • شما هم‌زمانی (concurrency) را روی 1 گزارش کرده‌اید. این عدد خوش‌بینانه‌ترین مقدار در گزارش است و هیچ ارتباطی با هزینه‌ها ندارد.

تبدیل عدد اندازه‌گیری‌شده به یک تصمیم

خروجی اشباع‌شده (saturated) را از تست خود بردارید، نه نرخ تک‌جریانی (single-stream)، و آن را با قیمت‌گذاری به ازای هر توکن مقایسه کنید. نقطه سربه‌سر (break-even) حاصل یک تقسیم ساده است:

break_even_tok_s = (price_per_hour / price_per_million_output_tokens) * 1000000 / 3600

این محاسبه را با قیمت‌های جولای 2026 در DigitalOcean انجام دهید. هزینه endpoint استنتاج اختصاصی H200 آن‌ها 4.47 دلار در ساعت و معادل serverless آن 0.65 دلار به ازای هر میلیون توکن بود. بنابراین، 4.47 تقسیم بر 0.65 برابر با 6.88 میلیون توکن در ساعت است و تقسیم آن بر 3,600 ثانیه، حدود 1,910 توکن خروجی در ثانیه را به دست می‌دهد. قیمت‌ها متعلق به آن‌هاست و تقسیم متعلق به ما.

کلمه‌ای که این تصمیم را تعیین می‌کند، پایداری (sustained) است. رسیدن به 1,910 توکن در ثانیه در حالت اشباع برای دو ساعت در روز، به معنای 1,910 توکن در ثانیه به‌صورت پایدار نیست، زیرا شما هزینه بیست‌ودو ساعت دیگر را نیز پرداخت می‌کنید. نقطه تقاطع خودِ DigitalOcean برای GPU Droplet ارزان‌تر با قیمت 3.44 دلار در ساعت، در 72.2 درصد بهره‌وری متوسط پایدار قرار می‌گیرد و زیر این مقدار، قیمت به ازای هر توکن به‌صرفه‌تر است. ساعات بیکاری GPU، نه کند بودن توکن‌ها، چیزی است که معمولاً باعث شکست پروژه self-hosting می‌شود.

بنابراین تصمیم شما دو ورودی دارد. تست sweep سقف توانایی شما را مشخص می‌کند. الگوی ترافیک شما مشخص می‌کند که چه کسری از آن سقف را واقعاً استفاده می‌کنید. آن‌ها را در هم ضرب کنید، سپس نتیجه را به مقایسه GPU VPS با نقطه سربه‌سر API به ازای هر توکن ببرید و پاسخ را برای حجم کاری خود بخوانید.

FAQ

نرخ مناسب توکن در ثانیه برای یک LLM که به‌صورت self-hosted اجرا می‌شود چقدر است؟

دو پاسخ برای این پرسش وجود دارد، زیرا این معیار دو وظیفه متفاوت را انجام می‌دهد. برای یک کاربر که خروجی را می‌خواند، هر سرعتی بالاتر از حدود 20 توکن در ثانیه برای هر جریان (stream)، سریع‌تر از سرعت خواندن انسان است و افزایش آن تأثیر بیشتری ندارد. از نظر هزینه، عددی که اهمیت دارد مجموع توان عملیاتی (throughput) خروجی در حالت اشباع است و "خوب" بودن به معنای رسیدن به نقطه سربه‌سر است. با هزینه 0.65 دلار به ازای هر میلیون توکن روی سروری که 4.47 دلار در ساعت هزینه دارد، این کفِ عملکرد در قیمت‌های ژوئیه 2026، نزدیک به 1,910 توکن خروجی در ثانیه به‌صورت مداوم است. یک جریان روی یک مدل بزرگ هرگز به این عدد نمی‌رسد، و به همین دلیل است که قابلیت batching وجود دارد.

چرا وقتی درخواست‌های همزمان را اضافه می‌کنم، توان عملیاتی Ollama ثابت می‌ماند؟

OLLAMA_NUM_PARALLEL به‌صورت پیش‌فرض روی 1 تنظیم شده است، بنابراین سرور در هر لحظه فقط یک درخواست را برای هر مدل اجرا می‌کند و بقیه را تا سقف OLLAMA_MAX_QUEUE (به‌صورت پیش‌فرض 512) در صف قرار می‌دهد تا زمانی که خطای 503 برگرداند. مجموع خروجی ثابت می‌ماند در حالی که p99 TTFT افزایش می‌یابد؛ این نشانه وجود صف است، نه مشغول بودن GPU. این متغیر را در یک فایل drop-in برای systemd تنظیم کرده و سرویس را restart کنید، سپس ollama ps را بررسی کنید، زیرا هر اسلات موازی، context تخصیص‌یافته را چند برابر می‌کند و ممکن است بخشی از مدل را به سمت CPU سوق دهد.

آیا باید زمان رسیدن به اولین توکن (TTFT) را اندازه بگیرم یا توکن در ثانیه را؟

هر دو را، زیرا با افزایش بار، این دو در جهت مخالف یکدیگر حرکت می‌کنند. TTFT چیزی است که کاربر حس می‌کند و توان عملیاتی خروجی در حالت اشباع چیزی است که در صورت‌حساب شما منعکس می‌شود. مقادیر p50 و p99 TTFT را در هر مرحله از concurrency ثبت کنید، سپس بالاترین concurrency را انتخاب کنید که در آن p99 TTFT همچنان برای شما قابل‌قبول است. توان عملیاتی در آن نقطه را به‌عنوان ظرفیت خود گزارش کنید، نه حداکثر عددی که در بالاترین نقطه نمودار به دست می‌آید.

آیا عدد بالاتر برای توکن در ثانیه همیشه به معنای هزینه کمتر به ازای هر توکن است؟

خیر. هزینه به ازای هر توکن برابر است با قیمت ساعتی تقسیم بر توکن‌هایی که سرور در آن ساعت واقعاً تولید کرده است؛ بنابراین یک سرور سریع که بیشتر روز را در حالت idle می‌ماند، همچنان هزینه بالایی به ازای هر توکن دارد. میزان بهره‌وری (utilisation) تعیین‌کننده است، نه سرعت اوج (peak speed). به واحدها نیز دقت کنید: مجموع توان عملیاتی توکن که در مشخصات ذکر می‌شود، توکن‌های ورودی را هم می‌شمارد؛ بنابراین در نسبت 1:1 ورودی به خروجی، این عدد نزدیک به دو برابر نرخ خروجی است که بابت آن صورت‌حساب دریافت می‌کنید.

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