محاسبه دقیق توکن در ثانیه برای مدلهای زبانی محلی
اجاره GPU تنها زمانی از API بهصرفهتر است که نرخ خروجی بالایی داشته باشید. با اجرای یک تست همزمانی (concurrency sweep) در vLLM، نرخ واقعی توکن در ثانیه را بسنجید.
چرا تعداد توکن در ثانیه تعیینکننده صرفه اقتصادی GPU است
تعداد توکن در ثانیه (Tokens per second)، نرخ تولید متن خروجی توسط سرور شماست و عددی است که تعیین میکند آیا اجاره یک GPU ارزانتر از پرداخت هزینه به ازای هر توکن در یک API است یا خیر. هزینه یک GPU بهصورت ساعتی محاسبه میشود، فارغ از اینکه در حال پردازش باشد یا بیکار. در مقابل، هزینه APIهای میزبانیشده بر اساس تعداد توکن محاسبه میشود. بنابراین، استفاده از GPU تنها زمانی بهصرفه است که نرخ خروجی بالایی را در اکثر ساعات اجارهای حفظ کنید.
این یعنی شما به یک اندازهگیری دقیق نیاز دارید، نه عددی که از منابع دیگر میخوانید. این صفحه چهار عددی را که ارزش ثبت دارند تعریف میکند، سپس دستوراتی را ارائه میدهد که این اعداد را تولید میکنند و در نهایت محاسباتی را شرح میدهد که آنها را به یک تصمیم نهایی تبدیل میکند.
چرا عدد توکن در ثانیه منتشرشده، عدد واقعی شما نیست
DigitalOcean در ژوئیه 2026 ارقام توان عملیاتی (throughput) را برای یک NVIDIA H200 که llama3.3-70b-instruct را در حالت FP8 (ممیز شناور 8 بیتی) تحت vLLM اجرا میکند، منتشر کرد. این ارقام مفید هستند اما متعلق به شما نیستند.
دادههای پشت این نمودار
[
{
"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 توکن در ثانیه، مربوط به یک H100 تکی روی همان مدل است که توسط KV cache (حافظه کلید و مقدار، یعنی حافظه اختصاصی هر درخواست که مکالمه در حال سرویس را روی کارت نگه میدارد) محدود شده است. یک کارت 80 گیگابایتی درخواستهای همزمان کمتری را برای یک مدل 70B نگه میدارد، بنابراین زودتر به اشباع میرسد.
مدل را تغییر دهید یا نسبت ورودی به خروجی را عوض کنید تا تمام اعداد بالا تغییر کنند. ارقام منتشرشده انتظارات شما را تعیین میکنند، نه بودجه شما را؛ این همان قاعدهای است که در بنچمارک صادقانه یک VPS روی دیسک و شبکه نیز صدق میکند.
چهار عددی که اهمیت دارند
- زمان تا اولین توکن (TTFT): تأخیر بین ارسال درخواست و رسیدن اولین توکن خروجی. این زمان شامل زمان پیشپردازش (prefill) بهعلاوه زمان انتظار در صف است. کاربر این مورد را مستقیماً حس میکند.
- تعداد توکن خروجی در ثانیه، برای هر جریان (stream): سرعت نوشتن یک پاسخ پس از شروع آن. بالاتر از حدود 20 توکن در ثانیه، سرعت از توان خواندن اکثر افراد بیشتر است، بنابراین افزایش سرعت در این بخش دستاورد چندانی ندارد.
- حداکثر توان عملیاتی خروجی (Saturated total output throughput): مجموع تمام جریانهای همزمان در حالتی که سرور کاملاً تحت بار است. این عدد نشاندهنده ظرفیت است و همان عددی است که هزینههای GPU را توجیه میکند.
- مقادیر p50 و p99 برای TTFT تحت شرایط همزمانی: مقدار p50 نشاندهنده درخواست میانی است. مقدار p99 عددی است که 99 درخواست از هر 100 درخواست، سریعتر از آن انجام میشوند. تأخیر ناشی از صف همیشه ابتدا در 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 جنبههای حافظه در این انتخاب را پوشش میدهد.
اندازهگیری یک استریم در ابتدا
با سادهترین حالت شروع کنید. این یک بررسی سلامت سیستم و تعیین سقف عملکرد است. 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 به یک درخواست استریمینگ نیاز دارید و 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 لحظهای است که اولین بایت از بدنه پاسخ دریافت میشود. در یک تکمیل چت استریمینگ، آن بایت متعلق به اولین رویداد ارسالشده توسط سرور است که یا اولین توکن محتواست یا یک delta فقط شامل نقش (role) که درست پیش از آن ارسال شده است. بنابراین این مقدار را با تقریب یک رویداد، همان TTFT در نظر بگیرید. این مقدار برای مقایسه دو اجرا روی یک سرور به اندازه کافی دقیق است.
اعداد مربوط به تکاستریم، عملکرد سختافزار را بیش از حد واقعی نشان میدهند. TTFT در این حالت بهترین وضعیت ممکن است، زیرا هیچ درخواستی پیش از شما در صف قرار ندارد. نرخ هر استریم نیز بهترین وضعیت ممکن است، زیرا کل کارت گرافیک در حال پاسخدهی به یک درخواست است. هیچکدام از اینها ظرفیت واقعی سرور را نشان نمیدهند.
چگونه یک concurrency sweep اجرا کنیم؟
یک sweep، یک بار کاری ثابت را با افزایش سطح همزمانی (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 تعداد درخواستهای در حال اجرا را محدود میکند و متغیری است که در حال 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 چاپ میکند.
در این خروجی، نرخ به ازای هر استریم وجود ندارد، اما با یک تقسیم ساده قابل محاسبه است. Mean TPOT (ms): میانگین زمان برای هر توکن خروجی پس از توکن اول است؛ بنابراین 25 میلیثانیه به ازای هر توکن، معادل 40 توکن بر ثانیه برای هر استریم است. تقسیم خروجی کلی (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"
doneoutput_throughput نشاندهنده توکنهای خروجی در ثانیه است. total_token_throughput توکنهای ورودی را نیز به آن اضافه میکند؛ بنابراین در نسبت 1:1، مقدار آن تقریباً دو برابر میشود. p99_ttft_ms تنها به این دلیل وجود دارد که --metric-percentiles شامل 99 بوده است؛ اگر درصدی (percentile) را درخواست کنید که قبلاً آن را نخواستهاید، jq مقدار null را چاپ میکند.
پویش همروندی (concurrency sweep) دقیقاً چه چیزی را نشان میدهد؟
دادههای پشت این نمودار
[
{
"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 اجارهای کوچک با مقیاسهای منطقی است. اینها اندازهگیری سرور شما نیستند و ارقام تبلیغاتی فروشنده نیز محسوب نمیشوند. حلقه بالا را اجرا کنید و مقادیر خود را جایگزین آنها کنید.
الگو را تحلیل کنید، چرا که این الگو همان چیزی است که تعمیم مییابد. در یک جریان (stream)، کل سرور 92 توکن در ثانیه با p99 TTFT معادل 61 میلیثانیه تولید میکند. در 128 streams، مجموع به 2304 توکن در ثانیه میرسد که بیستوپنج برابر بیشتر است، در حالی که سرعت هر جریان به 18 توکن در ثانیه کاهش یافته و p99 TTFT به 3820 میلیثانیه میرسد. نرخ کلی خروجی (throughput) افزایش مییابد زیرا دستهبندی (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 اشاره میکنند که یک context با اندازه 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) بوده است. اولین درخواست، هزینه بارگذاری وزنها را میپردازد و در vLLM ممکن است هزینه ضبط گراف (graph capture) را نیز شامل شود. یک دسته (batch) برای گرم کردن مدل ارسال کنید و نتیجه آن را نادیده بگیرید.
- کش کردن پیشوند (prefix caching) به جای شما پاسخ داده است. vLLM بهصورت پیشفرض قابلیت automatic prefix caching را فعال میکند؛ بنابراین ارسال مکرر یک پرامپت مشابه، به جای اندازهگیری مرحله prefill، در حال اندازهگیری کش است و TTFT به کسری از مقدار واقعی خود کاهش مییابد.
--dataset-name randomاز این مسئله جلوگیری میکند زیرا هر پرامپت متفاوت است. برای اطمینان، سرور را با--no-enable-prefix-cachingراهاندازی کنید. - خروجیها کوتاه بودهاند. با پاسخهای 32 توکنی، TTFT بر هر درخواست غلبه میکند و نرخ توکن بر ثانیه شما در واقع فقط مرحله prefill را توصیف میکند. از
--ignore-eosبا طول خروجی واقعبینانه استفاده کنید. - شما همزمانی (concurrency) را روی 1 گزارش کردهاید. این دوستانهترین عدد در برگه گزارش است اما هیچ ارتباطی با هزینهها ندارد.
تبدیل عدد اندازهگیریشده به یک تصمیم
خروجی throughput اشباعشده را از sweep خود استخراج کنید (نه نرخ تکرشتهای) و آن را با قیمتگذاری به ازای هر توکن مقایسه کنید. نقطه سربهسر (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 توکن خروجی در ثانیه را به دست میدهد. قیمتها متعلق به آنهاست و تقسیم متعلق به ما. زمانی که در 7 اکتبر 2026 بررسی کردیم، قیمت endpoint H200 همچنان 4.47 دلار در ساعت بود، اما DigitalOcean سرویس serverless مدل Llama 3.3 70B را در 18 آگوست 2026 بازنشسته کرد و کاربران را به Llama 4 Maverick ارجاع میدهد که قیمت آن 0.87 دلار به ازای هر میلیون توکن خروجی درج شده است. این یک مدل متفاوت است، بنابراین پیش از آنکه مقایسه معنایی داشته باشد، به sweep مخصوص خود نیاز دارد.
کلمهای که این تصمیم را تعیین میکند، پایداری (sustained) است. رسیدن به 1,910 توکن در ثانیه در حالت اشباع برای دو ساعت در روز، به معنای 1,910 توکن در ثانیه به صورت پایدار نیست، زیرا شما هزینه بیست و دو ساعت دیگر را نیز پرداخت میکنید. اجاره کارت به عنوان یک GPU Droplet نیز این مانع را کاهش نمیدهد: در 7 اکتبر 2026، قیمتگذاری Droplet در DigitalOcean برای H200 به صورت on-demand برابر با 4.47 دلار در ساعت بود (همان قیمت endpoint) و ارزانترین NVIDIA Dropletهای آنها، یعنی RTX 4000 با قیمت 0.76 دلار در ساعت و L40S یا RTX 6000 با قیمت 1.57 دلار در ساعت، برای جای دادن یک مدل 70B در فرمت FP8 بسیار کوچک هستند. بنابراین با ارقام بالا، یک H200 که در 2,036 توکن خروجی در ثانیه به اشباع میرسد، باید به طور میانگین حدود 94 درصد از آن پیک را در تمام ساعاتی که هزینه پرداخت میکنید حفظ کند تا با قیمت 0.65 دلار به ازای هر میلیون توکن برابری کند؛ پایینتر از آن، قیمت به ازای هر توکن برنده است. ساعات بیکاری GPU، نه کند بودن توکنها، چیزی است که معمولاً self-hosting را غیراقتصادی میکند.
بنابراین تصمیم شما دو ورودی دارد. sweep به شما سقف را میدهد. الگوی ترافیک شما، کسری از آن سقف را که واقعاً استفاده میکنید مشخص میکند. آنها را در هم ضرب کنید، سپس نتیجه را به مقایسه GPU VPS با نقطه سربهسر API به ازای هر توکن ببرید و پاسخ را برای حجم کاری خود بخوانید.
FAQ
نرخ مناسب توکن در ثانیه برای یک LLM که بهصورت self-hosted اجرا میشود چقدر است؟
دو پاسخ برای این پرسش وجود دارد، زیرا این معیار دو وظیفه متفاوت را انجام میدهد. برای یک نفر که خروجی را میخواند، هر سرعتی بالاتر از حدود 20 توکن در ثانیه برای هر جریان، سریعتر از سرعت خواندن است و افزایش آن کمکی نمیکند. از نظر هزینه، عددی که اهمیت دارد، مجموع توان عملیاتی خروجی در حالت اشباع است و «خوب» به معنای هر مقداری است که هزینههای شما را پوشش دهد. با در نظر گرفتن قیمت 0.65 دلار به ازای هر میلیون توکن روی سروری که 4.47 دلار در ساعت هزینه دارد، این نقطه سربهسر در نرخ حدود 1,910 توکن خروجی در ثانیه (با قیمتهای ژوئیه 2026) قرار میگیرد. یک جریان روی یک مدل بزرگ هرگز به این عدد نمیرسد، و به همین دلیل است که قابلیت batching وجود دارد.
چرا وقتی درخواستهای همزمان را اضافه میکنم، توان عملیاتی Ollama ثابت میماند؟
OLLAMA_NUM_PARALLEL بهصورت پیشفرض روی 1 تنظیم شده است، بنابراین سرور در هر لحظه فقط یک درخواست را برای هر مدل اجرا میکند و بقیه درخواستها را تا سقف OLLAMA_MAX_QUEUE (بهصورت پیشفرض 512) در صف قرار میدهد و پس از آن خطای 503 برمیگرداند. مجموع خروجی ثابت میماند در حالی که p99 TTFT افزایش مییابد؛ این نشانه وجود صف است، نه مشغول بودن GPU. این متغیر را در یک فایل drop-in برای systemd تنظیم کرده و سرویس را restart کنید، سپس ollama ps را بررسی کنید، زیرا هر slot موازی، context تخصیصیافته را چند برابر میکند و ممکن است بخشی از مدل را به سمت CPU سوق دهد.
آیا باید زمان رسیدن به اولین توکن (TTFT) را اندازه بگیرم یا توکن در ثانیه را؟
هر دو را، زیرا با افزایش بار، این دو در جهت مخالف یکدیگر حرکت میکنند. TTFT چیزی است که کاربر حس میکند و توان عملیاتی خروجی در حالت اشباع، چیزی است که در صورتحساب شما منعکس میشود. مقادیر p50 و p99 TTFT را در هر مرحله از افزایش همزمانی ثبت کنید، سپس بالاترین سطح همزمانی را انتخاب کنید که در آن p99 TTFT همچنان برای شما قابلقبول است. توان عملیاتی در آن نقطه را بهعنوان ظرفیت خود گزارش دهید، نه حداکثر عددی که در بالاترین نقطه نمودار مشاهده میشود.
آیا عدد بالاتر برای توکن در ثانیه همیشه به معنای هزینه کمتر به ازای هر توکن است؟
خیر. هزینه به ازای هر توکن برابر است با قیمت ساعتی تقسیم بر تعداد توکنهایی که سرور در آن ساعت واقعاً تولید کرده است؛ بنابراین یک سرور سریع که بیشتر روز را در حالت idle میماند، همچنان هزینه بالایی به ازای هر توکن دارد. میزان بهرهوری (Utilisation) تعیینکننده است، نه سرعت در حالت اوج. به واحدها نیز دقت کنید: توان عملیاتی کل توکن که اعلام میشود، توکنهای ورودی را هم میشمارد؛ بنابراین در نسبت 1:1 ورودی به خروجی، این عدد نزدیک به دو برابر نرخ خروجی است که بابت آن صورتحساب دریافت میکنید.