گرفتن نخستین پاسخ از مدل معمولاً دشوارترین بخش پروژه نیست. مسئله زمانی عوض میشود که چند کاربر همزمان سؤال میپرسند، یکی سندی بلند میفرستد، دیگری منتظر تکمیل سریع کد است و تیم عملیات باید توضیح دهد چرا زمان پاسخ ناگهان بالا رفته است. در این نقطه، فقط کیفیت مدل و مقدار حافظهٔ GPU تعیینکننده نیست؛ نرمافزاری که درخواستها را میپذیرد، حافظه را تقسیم میکند و اجرای مدل را زمانبندی میکند، بخشی از ظرفیت واقعی خدمت را میسازد.
Ollama برای شروع سریع و مدیریت راحت مدلها انتخاب جذابی است، اما سادگی نصب، معیار کافی برای انتخاب موتور یک سرویس پرترافیک نیست. از طرف دیگر، کنارگذاشتن آن با برچسب «غیرحرفهای» هم مسئله را دقیق بیان نمیکند: ابزار ساده میتواند در یک استقرار محدود و خوبطراحیشده کار مناسبی انجام دهد. برای API سازمانی با بار همزمان، هدف تأخیر مشخص و نیاز جدی به پایش و تنظیم ظرفیت، vLLM و SGLang معمولاً نامزدهای مناسبتری برای شروع بررسیاند؛ برای اجرای محلی و سختافزار متنوع، Ollama و llama.cpp مزیتهای مهمی دارند. این توصیهٔ معماری است، نه ادعای برتری سرعت در تمام مدلها و سختافزارها.
این یادداشت تفاوتها را براساس مستندات و کد رسمیِ بررسیشده در ۲۵ شهریور ۱۴۰۵، برابر با ۱۶ سپتامبر ۲۰۲۶ توضیح میدهد. تنظیمات و پشتیبانی مدلها سریع تغییر میکنند؛ بنابراین برای استقرار، نسخهٔ موتور و شناسهٔ دقیق وزنها باید کنار پیکربندی ثبت شوند. مقایسهٔ پیکربندیهای مشخص در جدول نرمافزارهای اجرا و سرویسدهی تکمیل میشود.
چهار ابزار، با چهار نقطهٔ شروع متفاوت
مدل، موتور استنتاج، سرور API و رابط گفتگو چهار مفهوم جدا هستند، حتی اگر یک محصول چند مورد را کنار هم ارائه کند. وزنهای Qwen یا Llama خودشان صف درخواست و سیاست دسترسی نمیسازند؛ یک رابط چت هم لزوماً مشخص نمیکند درخواست در پشت صحنه چگونه اجرا میشود. تفکیک این لایهها اجازه میدهد رابط محبوب کاربران حفظ شود و موتور اجرا، متناسب با رشد خدمت تغییر کند.
| ابزار | نقطهٔ قوت اصلی | موقعیتی که ارزش بررسی زودتر دارد | مسئلهای که باید خودمان طراحی کنیم |
|---|---|---|---|
| Ollama | دریافت، نگهداری و اجرای سادهٔ مدلها، همراه API | توسعهٔ محلی، ابزار داخلی محدود، آزمایش چند مدل | بودجهٔ حافظه و همزمانی، کنترل بار و لایهٔ عملیات سرویس |
| vLLM | سرویسدهی با زمانبندی و مدیریت حافظهٔ قابلتنظیم | API مشترک با بار همزمان و مدل سازگار | تنظیم متناسب با بار، استقرار نمونهها و کنترل کیفیت |
| SGLang | موتور سرویسدهی با تأکید بر کش، زمانبندی و اجرای توزیعشده | بارهای تکرارشونده، عاملها و سرویسهایی با نیاز به تنظیم جدی | انتخاب backend، سیاست کش و مسیریابی درخواستها |
| llama.cpp | اجرای کموابستگی روی سختافزار متنوع و اکوسیستم GGUF | CPU، Apple Silicon، اجرای ترکیبی CPU/GPU و سرویس GGUF | ساخت و تنظیم backend، ظرفیت slots و اجزای بیرونی سرویس |
اطلاعات جدول از مستندات رسمی Ollama، vLLM، SGLang و llama.cpp گردآوری شدهاند. کاربردهای پیشنهادی بر اساس امکانات هر نرمافزار مشخص شدهاند. vLLM و SGLang منحصر به چند GPU یا دیتاسنتر نیستند و llama.cpp هم صرفاً برنامهای برای خط فرمان نیست.
«چند درخواست همزمان» دقیقاً چه معنایی دارد؟
سرور ممکن است صد اتصال HTTP را باز نگه دارد، درحالیکه فقط چند درخواست واقعاً در موتور اجرا فعالاند و بقیه منتظرند. همچنین ممکن است چند درخواست در یک batch از وزنهای مشترک استفاده کنند، بدون آنکه برای هر کاربر یک نسخهٔ کامل مدل بارگذاری شود. پذیرش اتصال، ورود به صف، اجرای فعال و تکثیر مدل چهار عدد متفاوتاند؛ زیادکردن اولی لزوماً ظرفیت آخریها را بیشتر نمیکند.
در تولید خودبازگشتی، طول پاسخها یکسان نیست. اگر همهٔ اعضای یک batch مجبور باشند تا پایان بلندترین پاسخ منتظر بمانند، منابع آزادشده دیرتر به کار بعدی میرسند؛ continuous batching امکان میدهد ترکیب درخواستهای فعال در طول اجرا تغییر کند. این ایده در کارهایی مانند Orca توضیح داده شده است، اما پیادهسازی زمانبند، محدودیت حافظه و رفتار آن هنگام ورود یک ورودی بلند، بین موتورها تفاوت دارد.
| سازوکار | چه چیزی را بهبود میدهد؟ | چه چیزی از آن نتیجه نمیشود؟ |
|---|---|---|
| Continuous batching | استفاده از ظرفیت با ورود و خروج پویای درخواستها | هر درخواست با همان سرعت اجرای تککاربره پاسخ نمیگیرد |
| PagedAttention و تخصیص بلوکی KV | کاهش اتلاف ناشی از تخصیص حافظهٔ کش و امکان مدیریت منعطفتر آن | حافظهٔ نامحدود یا انتقال رایگان حافظه به دیسک فراهم نمیشود |
| Prefix caching | استفادهٔ دوباره از محاسبهٔ پیشوند مشترک | پاسخ آماده ذخیره نشده و تمام هزینهٔ تولید خروجی حذف نمیشود |
| Chunked prefill | تقسیم پردازش ورودی بلند به بخشهای کوچکتر و تنظیم همزیستی آن با تولید خروجی | بهترین اندازهٔ بخش برای همهٔ بارها یکسان نیست |
| FlashAttention | کاهش جابهجایی داده در محاسبهٔ attention با کرنل مناسب | جای صف، زمانبند یا مدیریت نمونههای مدل را نمیگیرد |
پایهٔ فنی این تفاوتها در مقالهٔ PagedAttention، مقالهٔ FlashAttention و راهنمای تنظیم vLLM آمده است. حضور نام یک قابلیت در دو محصول، برابری پیادهسازی یا سرعت را اثبات نمیکند. همچنین عدد توان عملیاتیِ کل، تجربهٔ یک کاربر را توصیف نمیکند؛ این تمایز در چرا سریعترین GPU لزوماً سریعترین پاسخ را نمیدهد؟ توضیح داده شده است.
Ollama چه چیزی را ساده میکند و کجا به سقف تصمیمهای ساده میرسیم؟
مزیت Ollama کاهش اصطکاک راهاندازی است: مدل دریافت میشود، تنظیمات آن در قالبی قابلمدیریت قرار میگیرد و برنامه میتواند از API استفاده کند. برای تیمی که هنوز مدل نهایی را انتخاب نکرده یا ابزار محلی مشخصی میخواهد، این سادگی ارزش عملی دارد. واردکردن مدل نیز به فهرست آماده محدود نیست؛ مستندات، مسیرهای واردکردن GGUF و وزنهای Safetensors را توضیح میدهند، با این شرط که معماری و جزئیات مدل پشتیبانی شوند.
Ollama پردازش موازی، بارگذاری چند مدل و توزیع یک مدل روی چند GPU را دارد. راهنمای آن توضیح میدهد که اگر مدل روی یک GPU جا شود، همان مسیر را ترجیح میدهد و در صورت نیاز آن را میان GPUها پخش میکند. بنابراین نقد «Ollama فقط یک درخواست میگیرد» یا «چند GPU را نمیشناسد» دقیق نیست؛ محدودیت مهمتر، میزان کنترل و مشاهدهپذیری موردنیاز برای خدمت مشخص است.
بااینحال، مقدار پیشفرض میتواند برداشت اولیه را منحرف کند. در کد نسخهٔ v0.34.1، مقدار پیشفرض OLLAMA_NUM_PARALLEL برابر ۱ است؛ متغیر جداگانهٔ OLLAMA_MAX_LOADED_MODELS سقف مدلهای بارشده را کنترل میکند و افزایش آن، تعداد نسخههای مستقلِ همان مدل را تعیین نمیکند. OLLAMA_MAX_QUEUE نیز ظرفیت انتظار است. مقایسهٔ یک سرویس با تنظیم همزمانی محدود و سرویس دیگر با زمانبندی متناسب، نتیجهای دربارهٔ همهٔ توان محصول نمیدهد.
در محیط مشترک، تعویض مکرر مدلها مسئلهٔ دیگری است: اگر حافظه کافی نباشد، بارگذاری مدل جدید و خارجکردن مدل قبلی میتواند به زمان انتظار اضافه کند. پارامتر keep_alive برای ماندن مدل در حافظه وجود دارد، اما گرم نگهداشتن مدلها به حافظه نیاز دارد؛ این تصمیم را نمیتوان فقط به راحتی فراخوانی API سپرد. گزارش ollama ps برای دیدن محل بارگذاری روی CPU/GPU مفید است.
نقطهٔ مهاجرت زمانی است که برای رسیدن به هدف خدمت، به تنظیم دقیقتر زمانبندی، تحلیل صف و کش، جداسازی بارها یا استقرار تعداد زیادی نمونه نیاز پیدا میکنیم و هزینهٔ ساخت این لایهها دور Ollama بالا میرود. این مرز با تعداد کارکنان سازمان تعیین نمیشود: یک تیم کوچک با عاملهای پرتکرار ممکن است زودتر به آن برسد و یک ابزار محدود در شرکتی بزرگ دیرتر. برای بار سازمانی روبهرشد، بررسی vLLM و SGLang از ابتدای طراحی میتواند هزینهٔ مهاجرت بعدی را کم کند.
vLLM؛ وقتی ظرفیت سرویس باید تنظیم و توضیح داده شود
vLLM از ابتدا با مسئلهٔ سرویسدهی مدل و استفادهٔ مؤثر از حافظه شناخته شد. PagedAttention کش را به بلوکهایی نگاشت میکند که الزاماً در حافظه پشتسرهم نیستند؛ این کار از اتلاف تخصیص میکاهد و مدیریت درخواستهایی با طول متفاوت را آسانتر میکند. نکتهٔ عملی این است که ظرفیت قابلاستفاده به وزنهای مدل محدود نمیماند و موتور برای حافظهٔ گفتگوهای فعال سازوکار مشخص دارد.
برای کنترل بار، سقف توالیهای فعال، بودجهٔ توکن هر گام و طول کانتکست جداگانه تنظیم میشوند. در مسیر V1 مستندشده، chunked prefill میتواند پردازش ورودی را با decode درخواستهای موجود ترکیب کند؛ تغییر بودجهٔ توکن، تعادل میان زمان آغاز پاسخ و ادامهٔ تولید را جابهجا میکند. زیادکردن بیمحابای همزمانی نیز میتواند به کمبود KV و تکرار محاسبه پس از کنارگذاشتن موقت درخواستها منجر شود.
این کنترلها vLLM را به نامزد مناسبی برای API مشترک تبدیل میکنند، اما تنظیمات پیشفرض را به بهترین پیکربندی هر پروژه تبدیل نمیکنند. یک مدل کوچک روی یک GPU هم ممکن است از این امکانات سود ببرد؛ در مقابل، اگر برنامه فقط گهگاه یک درخواست میفرستد، ظرفیت اضافهٔ زمانبند الزاماً منفعت محسوسی ندارد. هزینهٔ وابستگیها، ارتقا و نگهداری باید در کنار ظرفیت تحویلدادهشده دیده شود.
در سرویس عملی ترگمان از نسخهٔ vLLM منتشرشده توسط NVIDIA استفاده کردیم و تغییرات محدودی در لایهٔ سرویس و API دادیم. یک موتور، درخواستهای ترجمه، خلاصهسازی و چت را میگرفت؛ اگر پاسخی تا ۲۰ ثانیه شروع نمیشد، لغو درخواست را به خود موتور هم میفرستادیم تا پردازش بیمصرف ادامه پیدا نکند. برای انتخاب موتور، همین امکان کنترل چرخهٔ درخواست به اندازهٔ اجرای اولیهٔ مدل اهمیت دارد؛ این تجربه مقایسهٔ سرعت vLLM با موتورهای دیگر نبود.
SGLang؛ اهمیت کش و مسیر اجرای درخواست
SGLang امروز یک موتور سرویسدهی کامل است و استفاده از آن به نوشتن برنامه با زبان اختصاصی محدود نمیشود. ایدهٔ RadixAttention در کار اولیهٔ آن، سازماندهی کش پیشوندها برای استفادهٔ مجدد از بخشهای مشترک درخواستها بود. این موضوع برای گفتوگوهای چندمرحلهای، دستورهای ثابت سازمانی و عاملهایی که بارها با پیشوند مشابه به مدل برمیگردند، ارزش بررسی دارد؛ البته میزان اشتراک واقعیِ توکنها تعیینکننده است.
در استقرارهای بزرگتر، اکوسیستم آن ابزارهای بیشتری نیز ارائه میکند. HiCache نگهداری کش را میان حافظهٔ GPU، میزبان و لایههای ذخیرهسازی توسعه میدهد؛ Model Gateway هم امکان مسیریابی با توجه به وضعیت بار و کش workerها را فراهم میکند. این اجزا میتوانند بازاستفاده از محاسبه را بهتر کنند، اما انتقال داده، ظرفیت ذخیرهسازی و ادارهٔ سرویسهای اضافه هزینه دارند و برای هر استقرار کوچک ضروری نیستند.
انتخاب میان SGLang و vLLM را بهتر است با checkpoint، GPU و الگوی درخواست خود پروژه انجام داد. پشتیبانی معماری، کرنل quantization، قالب ابزارها و رفتار نسخهٔ مورداستفاده ممکن است از تفاوت نام محصولات مهمتر باشد. اگر بار کار پیشوند مشترک کمی دارد، از صرفِ وجود RadixAttention نباید انتظار سود بزرگی داشت؛ vLLM نیز کش پیشوند دارد و این قابلیت انحصاری SGLang نیست.
llama.cpp؛ اجرای سبک، با سروری جدیتر از تصور رایج
llama.cpp برای اجرای مدل روی طیفی از سختافزارها و با وابستگیهای محدود اهمیت دارد. CPU، Metal روی Apple Silicon، CUDA و مسیرهای دیگری مانند Vulkan بخشی از دامنهٔ آن هستند؛ اجرای ترکیبی CPU/GPU نیز میتواند مدل بزرگتر از حافظهٔ GPU را قابلاستفاده کند. این قابلیت برای ابزار توکار، دستگاه لبه و سیستم محدود به حافظه مفید است، به شرط آنکه تأخیر حاصل با نیاز کاربرد سازگار باشد.
جزء llama-server، API سازگار در مسیرهای مشخص، slots موازی، continuous batching، کش پرامپت و خروجی معیارهای Prometheus دارد. نسخهٔ بررسیشده همچنین حالت router برای مدیریت چند مدل ارائه میکند. بنابراین برابرگرفتن llama.cpp با «فقط اجرای تککاربره» درست نیست؛ انتخاب آن برای سرویس GGUF میتواند آگاهانه باشد، هرچند عملیات چندمیزبانه همچنان نیازمند طراحی است.
وقتی مدل روی CPU یا بخشی روی CPU اجرا میشود، کاهش نیاز به GPU ممکن است با افزایش زمان پاسخ و مصرف منابع میزبان همراه شود. برای یک ابزار کممراجعه، این مبادله گاهی مطلوب است؛ برای خدمت تعاملیِ شلوغ شاید نباشد. اجرای لایهبهلایه و offload نیز همین پرسش اقتصادی را پیش میآورند که در یادداشت AirLLM و اجرای لایهبهلایه جداگانه بررسی شده است.
مسیر Apple silicon: MLX LM
برای Mac دارای Apple silicon، MLX LM یکی از مسیرهای اجرای محلی مدلهای سازگار است. تولید متن، کش پرامپت، کوانتیزیشن و فاینتیون را پشتیبانی میکند؛ انتخاب آن به مدل، قالب وزن و حافظهٔ دستگاه بستگی دارد. قابلیت memory wiring برای مدلهای بزرگ به macOS 15 یا جدیدتر نیاز دارد.
GGUF، Safetensors و «مدل چهاربیتی» را هممعنی نگیریم
GGUF قالب نگهداری مدل و فراداده است؛ هر فایل GGUF لزوماً چهاربیتی نیست. Safetensors نیز قالب ذخیرهسازی tensorهاست و بهتنهایی روش محاسبه یا تعداد بیت وزنها را تعیین نمیکند. نامهایی مانند AWQ، GPTQ و FP8 به جنبههای دیگری از نمایش و اجرای وزن مربوطاند؛ بنابراین پیدا کردن فایل مدل در هاگینگفیس، پایان بررسی سازگاری نیست. رابطهٔ این مفاهیم در چهاربیتیکردن مدل چه چیزی را ارزان میکند؟ توضیح داده شده است.
برای GGUF، llama.cpp مسیر مهم و شناختهشدهای است و Ollama نیز امکان واردکردن آن را دارد. در vLLM هم پشتیبانی GGUF وجود دارد و در مستندات فعلی به نصب جداگانهٔ vllm-gguf-plugin نیاز دارد. این مسیر آزمایشی است؛ پس جملهٔ «vLLM فایل GGUF را اجرا نمیکند» دقیق نیست و جملهٔ «پس همهٔ قابلیتها با همان کیفیت کار میکنند» هم نتیجه نمیشود. برای سرویس vLLM یا SGLang باید checkpoint و روش quantization متناسب با کرنل و GPU انتخاب شوند.
مقایسهٔ یک Q4 در Ollama با وزن BF16 در vLLM فقط مقایسهٔ موتور نیست؛ مقدار حافظه، کیفیت عددی و مسیر محاسبه نیز تغییر کردهاند. دو نوع مقایسه مفید داریم: آزمایش تا حد ممکن کنترلشده برای فهم اثر موتور، و مقایسهٔ بهترین پیکربندی قابلقبول هر راهحل برای انتخاب محصول. هر دو ارزش دارند، اما باید معلوم باشد نتیجه به موتور نسبت داده میشود یا به کل پیکربندی.
حافظهٔ کاربران کجا میرود؟ یک مثال قابلمحاسبه
بودجهٔ حافظه تقریباً از وزنها، KV cache، فضای کاری کرنلها و activationها، بافرهای احتمالی CUDA Graph و مقداری حاشیهٔ عملیاتی تشکیل میشود. KV همان اطلاعات کلید و مقدارِ توکنهای پردازششده است که برای مراحل بعدی نگه داشته میشود. در attention متعارف، مقدار آن با تعداد لایهها، سرهای KV، ابعاد سر، دقت ذخیرهسازی و مجموع طول توالیهای نگهداریشده رشد میکند؛ تعداد سرهای query را نباید در مدل GQA جای تعداد سرهای KV گذاشت.
مدلی فرضی با ۳۲ لایه، ۸ سر KV در هر لایه، بعد سر ۱۲۸ و ذخیرهسازی دوبایتی در نظر بگیریم. برای هر توکن، دو tensor کلید و مقدار داریم؛ بنابراین 2 × 32 × 8 × 128 × 2 برابر ۱۳۱٬۰۷۲ بایت، یعنی ۱۲۸ KiB است. با این فرض، نگهداری ۸۱۹۲ توکن برای یک توالی دقیقاً ۱ GiB فضای خام KV میخواهد. این حساب مربوط به attention کامل با همین مشخصات است؛ برای MLA، مدلهای hybrid یا کش با پنجرهٔ لغزان نباید همین ضریب را کپی کرد.
| تعداد توالیهای همزمان | توکن نگهداریشده در هر توالی | مجموع فضای خام KV در مثال |
|---|---|---|
| ۱ | ۸۱۹۲ | 1 GiB |
| ۸ | ۸۱۹۲ | 8 GiB |
| ۱۶ | ۸۱۹۲ | 16 GiB |
| ۸ | ۳۲۷۶۸ | 32 GiB |
جدول، اشتراک پیشوند، quantization کش، سربار تخصیص و سایر مصرفکنندگان حافظه را وارد نمیکند؛ هدفش نشاندادن اندازهٔ مسئله است. تعداد توکن، ورودی و خروجیِ انباشتهشدهٔ همان توالی را شامل میشود و جدول فرض میکند همهٔ توالیها واقعاً به طول نوشتهشده رسیدهاند. در موتورهای با تخصیص پویا، تعیین سقف کانتکست الزاماً به معنی اشغال همان حجم برای تکتک درخواستها از لحظهٔ ورود نیست؛ رفتار رزرو و تخصیص موتور باید جداگانه خوانده شود.
نتیجهٔ عملی روشن است: ردیف آخر، حتی پیش از افزودن وزنها، در ۲۴ GiB جا نمیشود. پس «مدل هشتمیلیاردی روی کارت من اجرا میشود» به معنی ظرفیت هشت کاربر با کانتکست بلند نیست. استفاده از مدل کوچکتر، محدودکردن ورودیِ بیفایده، تنظیم همزمانی و روش مناسب KV میتواند از خرید عجولانهٔ GPU جلوگیری کند؛ راهنمای انتخاب اندازهٔ مدل و تفاوت ۲۴ و ۴۸ گیگابایت روی RTX 4090 این تصمیم را تکمیل میکنند.
کدام تنظیمها واقعاً به تصمیم ظرفیت مربوطاند؟
جدول زیر نقطهٔ ورود به تنظیمات است؛ پارامترهای همردیف الزاماً معنای اجرایی یکسان ندارند. بهویژه ظرفیت صف با درخواست فعال، طول کانتکست با بودجهٔ توکن یک گام، و سهم حافظهٔ executor با اندازهٔ کش یکی نیست. مقدار مناسب باید از محدودیت خدمت و رفتار بار به دست آید، نه از بزرگترین عددی که سرور با آن روشن میشود.
| هدف | Ollama | vLLM | SGLang | llama-server |
|---|---|---|---|---|
| تعیین طول کانتکست | num_ctx و OLLAMA_CONTEXT_LENGTH | --max-model-len | --context-length | --ctx-size؛ با توجه به حالت KV و slots |
| کنترل اجرای موازی | OLLAMA_NUM_PARALLEL | --max-num-seqs | --max-running-requests | --parallel |
| تنظیم حافظهٔ اجرای مدل | بودجهٔ حاصل از مدل، کانتکست و موازیسازی | --gpu-memory-utilization؛ یا بودجهٔ صریح KV | --mem-fraction-static برای وزن و مخزن KV | تنظیم KV، لایههای GPU و نحوهٔ تقسیم مدل |
| کنترل کارِ ورودی در زمانبند | کنترلهای سطح سرویس؛ هممعنی بودجهٔ توکن دو ستون بعد نیست | --max-num-batched-tokens؛ بودجهٔ مشترک prefill و decode | --chunked-prefill-size | اندازههای batch و micro-batch در مسیر اجرا |
| مشاهدهٔ وضعیت | ollama ps و آمار پاسخ API | معیارهای /metrics | معیارها با --enable-metrics | /metrics با --metrics و وضعیت slots |
در تنظیم طول کانتکست Ollama، سقف ورودی را باید همراه با میزان حافظهٔ در دسترس انتخاب کرد. تنظیمهای همزمانی و حافظه در Ollama، vLLM و SGLang معنای یکسانی ندارند؛ جدول بالا این تفاوتها را کنار هم نشان میدهد. در llama-server باید ظرفیت گزارششدهٔ هر slot و شیوهٔ اشتراک KV دیده شود؛ تعبیر یک عدد ctx-size به «همین مقدار برای هر کاربر» در همهٔ حالتها معتبر نیست.
در vLLM، بالا بودن حافظهٔ رزروشده در nvidia-smi بهتنهایی نشانهٔ بار پردازشی زیاد نیست. همچنین --gpu-memory-utilization محدودکنندهٔ درصد استفاده از هستههای GPU نیست؛ بودجهٔ حافظهٔ executor را مشخص میکند، و تنظیم صریح حافظهٔ KV میتواند مسیر محاسبهٔ آن را عوض کند. در SGLang نیز --mem-fraction-static به وزنها و مخزن KV مربوط است و باید برای activationها و بافرهای دیگر جا بماند.
چند GPU: یک مدل بزرگ یا چند خدمت مستقل؟
وقتی مدل همراه با حافظهٔ موردنیاز خدمت روی یک GPU جا میشود، تکثیر نمونههای کامل برای درخواستهای مستقل ارزش بررسی دارد. در مقابل، tensor parallelism بخشی از محاسبهٔ یک نمونه را میان GPUها تقسیم میکند و pipeline parallelism تقسیم را در امتداد بخشهای مدل انجام میدهد. این روشها میتوانند برای جا دادن یا شتابدادن یک نمونه لازم باشند، اما هزینهٔ ارتباط و هماهنگی دارند؛ تعداد GPU بیشتر بهتنهایی افزایش متناسب ظرفیت را تضمین نمیکند.
روی یک میزبان با سه RTX 4090، اگر مدل مناسب روی هر کارت کامل جا شود، سه نمونهٔ مستقل با توزیع درخواست میتواند نامزد خوبی برای افزایش توان عملیاتی باشد. اگر یک نمونه روی هر سه کارت پخش شود، سه خدمت مستقل نداریم و از کار افتادن یک بخش میتواند همان نمونه را مختل کند. ضمناً نمیتوان هر معماری را صرفاً با انتخاب عدد ۳ برای tensor parallelism تقسیم کرد؛ قیود معماری و backend و اتصال میان کارتها باید بررسی شوند. برای GPUهای فاقد NVLink، مستندات vLLM بررسی pipeline parallelism را نیز مطرح میکند.
این سه نمونه روی یک میزبان، خرابی همان میزبان را پوشش نمیدهند. HA به محل استقرار، ظرفیت باقیمانده پس از خرابی، وضعیت درخواستهای در حال اجرا و وابستگیهای مشترک نیاز دارد. همچنین نمونهسازی مستقل با تمام حالتهای data parallel در مدلهای MoE یکسان نیست؛ بعضی گروهها در اجرای متخصصها با هم ارتباط دارند. جزئیات در از یک کاربر تا سرویس سازمانی آمده است.
برای رشد سرویس نیز موتور اجرا تمام مسئله نیست. لایهٔ مسیریابی باید هم بار workerها را ببیند و هم در صورت اهمیت، محل کش را در نظر بگیرد؛ چسباندن همهٔ درخواستهای مشابه به یک worker میتواند بهرهٔ کش را با صف طولانی عوض کند. SGLang Model Gateway برای چنین موازنهای امکانات مشخص دارد، اما راهاندازی یک موتور یا یک router بهتنهایی سیاست کامل مقیاسپذیری و تحمل خرابی نمیسازد.
API مشابه، رفتار کاملاً مشابه نمیسازد
سازگاری با API شناختهشده، هزینهٔ اتصال برنامه را کم میکند، اما endpoint یکسان تضمین نمیکند پارامترها، streaming، نقش پیامها، قالب ابزار و شمارش توکنها یکسان باشند. هنگام مهاجرت، chat template، tokenizer، توقف تولید و تنظیمات sampling باید کنترل شوند؛ تغییر خروجی همیشه ناشی از «کیفیت موتور» نیست. مستندات Ollama نیز سازگاری را برای مسیرها و قابلیتهای مشخص تعریف میکند.
برای عاملها، پشتیبانی tool calling باید در ترکیب مدل، قالب گفتگو، parser و کلاینت درست کار کند. توان تولید JSON با انتخاب صحیح ابزار یا درستبودن آرگومانهای آن یکی نیست؛ اعتبارسنجی خروجی و کنترل اجرای ابزار همچنان وظیفهٔ برنامه است. vLLM و SGLang برای این مسیر parserهای مشخص دارند و llama.cpp نیز وابستگی به template و مدل را توضیح میدهد.
حتی تغییر موتور هم همیشه به بازنویسی کلاینت نیاز ندارد: SGLang در مستندات فعلی مسیرهای سازگار با Ollama را ارائه میکند و میتواند پشت برخی کلاینتهای آن قرار بگیرد. این امکان، مسیر مهاجرت را کوتاهتر میکند، ولی باید endpointها و رفتار واقعاً استفادهشده آزمایش شوند. نگهداشتن تجربهٔ سادهٔ کاربران با تغییر موتور پشت سرویس منافاتی ندارد.
برای embedding و reranker، تصمیم جدا بگیریم
سرویس تولید متن، embedding و reranking الگوی محاسبه و معیار کیفیت یکسانی ندارند. ممکن است مولد روی vLLM یا SGLang اجرا شود و embedding کوچک روی CPU یا سرویس جداگانه کار کند؛ ضرورتی ندارد همهٔ اجزا به یک مدل یا یک موتور سپرده شوند. جداسازی میتواند مانع شود یک پردازش دستهایِ اسناد، حافظه یا زمان سرویس گفتگوی تعاملی را مصرف کند، هرچند هزینهٔ عملیات بیشتری هم دارد.
در انتخاب موتورِ embedding باید معماری، pooling، نرمالسازی و ابعاد خروجی با مدلی که ایندکس را ساخته تطبیق داشته باشد. در reranker نیز امتیاز و ترتیب اسناد اهمیت دارد؛ عدد token/s معیار مشترک مناسبی برای همهٔ این اجزا نیست. بررسی این مسیر در انتخاب مدل زبانی، embedding و reranker برای دستیار اسناد سازمانی آمده است؛ تغییر موتور را هم باید مانند تغییر پیکربندی بازیابی، با چند پرسش و سند واقعی کنترل کرد.
سرویس حرفهای باید قابلمشاهده و قابلکنترل باشد
آمار یک پاسخ برای بررسی اولیه مفید است، اما برای پیدا کردن علت افت خدمت باید توزیع زمانها و وضعیت صف و حافظه در طول زمان دیده شود. Ollama در پاسخ تولید، شمارندهها و زمانهایی مانند load_duration، prompt_eval_duration و eval_duration ارائه میکند؛ این اعداد برای تفکیک بارگذاری و محاسبه مفیدند، اما جای اندازهگیری انتهابهانتها از سمت کاربر و پایش تجمیعی را نمیگیرند.
vLLM و SGLang معیارهای Prometheus برای اجرای فعال، صف و تأخیر ارائه میکنند. نام دقیق metric، نوع histogram و زمان شروع اندازهگیری باید در همان نسخه دیده شود؛ زمان تا نخستین توکن در سرور لزوماً شامل تمام مسیر شبکه و پراکسی نیست. برای تصمیم ظرفیت، این آمار باید با بار ورودی و گزارش خطاهای برنامه کنار هم قرار گیرد.
| علامت مشاهدهشده | برداشت اولیهٔ قابلبررسی | اقدام مفید پیش از خرید GPU |
|---|---|---|
| نخستین پاسخ پس از بیکاری کند است | بارگذاری مدل یا گرمسازی در مسیر درخواست افتاده است | زمان load و سیاست گرمماندن را بررسی کنیم |
| زمان آغاز پاسخ زیر بار بالا میرود | صف، prefill یا مرحلهٔ پیش از موتور گلوگاه شده است | زمانها را تفکیک و سیاست پذیرش بار را تنظیم کنیم |
| مجموع token/s بالا، ولی هر کاربر ناراضی است | توان عملیاتی با تأخیر فردی مبادله شده است | سقف همزمانی و هدف تأخیر هر درخواست را بازتنظیم کنیم |
| با سند بلند خطای حافظه رخ میدهد | KV، activation یا بودجهٔ prefill کافی نیست | طول ورودی، بخشبندی prefill و مصرف حافظه را جدا ببینیم |
| preemption یا پسکشیدن درخواستها تکرار میشود | فشار حافظه باعث کار دوباره میشود | بودجهٔ KV و سقف درخواست فعال را با هم تنظیم کنیم |
| پس از تکثیر نمونهها بهرهٔ کش افت میکند | پیشوندهای مشترک میان workerها پخش شدهاند | تعادل میان توزیع بار و حفظ locality کش را بررسی کنیم |
اینها فرضیههای عیبیابیاند، نه تشخیص قطعی از روی یک نمودار. برای مثال، کندشدن پاسخ میتواند از بازیابی سند، شبکه یا اجرای ابزار باشد و با تعویض موتور حل نشود. افزایش طول صف هم ظرفیت پردازش نمیسازد؛ فقط میتواند زمان انتظار را بیشتر کند و خطا را دیرتر به کاربر نشان دهد.
در لایهٔ دسترسی نیز نباید API خام را معادل سرویس سازمانی دانست. مستندات Ollama برای API محلی احراز هویت را الزامی نمیداند؛ هنگام عرضه در شبکه باید مرز دسترسی و کنترل مصرف ساخته شود. در vLLM هم مستندات امنیت هشدار میدهد که --api-key همهٔ endpointهای حساس را پوشش نمیدهد؛ وجود این گزینه جای جداسازی شبکه و سیاست پراکسی را نمیگیرد.
همچنین نام Ollama بهتنهایی به معنی محلیبودن پردازش نیست؛ محصول مسیر اجرای ابری هم دارد. برای غیرفعالکردن قابلیتهای ابری Ollama، OLLAMA_NO_CLOUD=1 را تنظیم میکنیم. در مسیر Hugging Face، پس از دریافت وزن، tokenizer و کد لازم، HF_HUB_OFFLINE=1 مراجعه به Hub را متوقف میکند؛ برای خاموشکردن گزارش مصرف vLLM نیز VLLM_NO_USAGE_STATS=1 وجود دارد. این تنظیمها جای آزمون راهاندازی و پاسخگویی با شبکهٔ قطعشده را نمیگیرند. در هر چهار مسیر، سیاست نگهداری پرامپت در log، دسترسی به مدل و ابزار، timeout، لغو درخواست و سقف مصرف باید بخشی از طراحی باشد، نه چیزی که از نام موتور استنتاج فرض میشود.
مقایسهای انجام دهیم که به انتخاب منجر شود
برای شروع، چند دسته از کار واقعی انتخاب شود: ورودی کوتاه و بلند، خروجی کوتاه و بلند، درخواست ابزار و پرسشهای فارسیِ مهم پروژه. هر سناریو در حالت گرم و سرد، با کش سرد و گرم، و زیر بار روبهرشد اجرا شود. علاوه بر تعداد درخواست همزمان، نرخ ورود درخواست نیز باید کنترل شود؛ آزمونی که با کندشدن سرور خودش درخواست کمتری میفرستد، ممکن است صف واقعیِ زمان اوج را پنهان کند.
نتیجه باید دستکم زمان تا نخستین توکن، تأخیر ادامهٔ تولید، زمان تکمیل، توزیع تأخیر از جمله p95، نرخ خطا و حجم کارِ عبورکرده از معیار کیفیت را نشان دهد. برای قضاوت دربارهٔ تأخیر دنباله، نمونه و مدت آزمون کافی لازم است؛ یک اجرای کوتاه تککاربره جای آن را نمیگیرد. ابزارهای vllm bench serve و sglang.bench_serving امکان ساخت آزمون بار را فراهم میکنند، اما دادهٔ آزمون و معیار پذیرش همچنان باید از کاربرد انتخاب شوند.
نسخهٔ موتور، revision وزن و tokenizer، quantization، chat template، backend و نسخهٔ وابستگیها باید همراه نتیجه ثبت شوند. تغییر نسخهٔ FlashInfer، PyTorch یا مسیر کرنل میتواند اجرای متفاوتی بسازد؛ موفقیت نصب یا روشنشدن سرور به معنی انتخاب کرنل موردنظر نیست. نام backend انتخابشده و پیامهای fallback باید در log آغاز کار دیده شوند. برای قالبهای کمدقت نیز راهنمای پشتیبانی واقعی GPU مکمل بررسی موتور است.
برای کدام وضعیت، از کدام ابزار شروع کنیم؟
جدول زیر پیشنهاد ترتیب بررسی است. انتخاب نهایی باید با همان مدل و پیکربندیِ موردنیاز انجام شود؛ امکان دارد محدودیت یک معماری یا مزیت یک backend نتیجهٔ اولیه را تغییر دهد. «سازمانی» نیز بهخودیخود به معنی خرید GPU گران یا پیادهسازی پیچیدهترین پشته نیست.
| نیاز غالب | نقطهٔ شروع پیشنهادی | دلیل انتخاب | چه چیزی ممکن است انتخاب را عوض کند؟ |
|---|---|---|---|
| آزمایش مدل و توسعهٔ محلی | Ollama | مدیریت راحت مدل و اتصال سریع ابزارها | نیاز به تنظیم سطح پایین یا شکل خاص وزن |
| GGUF روی CPU، لپتاپ یا CPU/GPU | llama.cpp؛ یا Ollama برای مدیریت سادهتر | مسیرهای متنوع اجرا و کنترل منابع محلی | زمان پاسخ و پشتیبانی معماری دقیق |
| ابزار داخلی با بار محدود | Ollama یا llama-server | پیچیدگی عملیاتی متناسب با نیاز | رشد صف، کانتکست و نیاز به مشاهدهپذیری بیشتر |
| API مشترک با بار همزمان | vLLM و SGLang | کنترل زمانبندی، حافظه و معیارهای سرویس | پشتیبانی مدل، backend و نتیجهٔ آزمون بار |
| عامل یا گفتگو با پیشوندهای مشترک زیاد | SGLang و vLLM، با بررسی رفتار کش | امکان استفادهٔ مجدد از محاسبه | میزان اشتراک واقعی و توزیع درخواست میان نمونهها |
| مدل بزرگتر از ظرفیت یک GPU | vLLM یا SGLang؛ llama.cpp برای مسیر GGUF و offload | گزینههای تقسیم مدل یا کاهش نیاز به حافظهٔ GPU | اتصال کارتها، سرعت موردنیاز و قیود معماری |
| رشد اقتصادی و ادامهٔ خدمت هنگام خرابی | موتور مناسب بهعلاوهٔ نمونههای مستقل و لایهٔ مسیریابی | افزایش ظرفیت و امکان طراحی تحمل خرابی | محل استقرار، ظرفیت باقیمانده و وابستگیهای مشترک |
مجوز موتور هم از مجوز وزن مدل جداست: نسخههای بررسیشدهٔ Ollama و llama.cpp با MIT و vLLM و SGLang با Apache-2.0 منتشر شدهاند. این اطلاعات، مجوز همهٔ مدلها، افزونهها یا خدمات ابری متصل به آنها را تعیین نمیکند؛ آن موارد باید مستقل ثبت شوند.
برای تیمی که امروز با Ollama شروع کرده، تصمیم مفید حفظ یا حذف یک نام نیست؛ باید معلوم شود کدام بخش خدمت به کنترل بیشتری نیاز دارد. ممکن است ابزارهای توسعه همچنان از Ollama استفاده کنند، API اصلی روی vLLM یا SGLang قرار بگیرد و یک جزء GGUF با llama.cpp اجرا شود. این تفکیک وقتی ارزش دارد که ظرفیت، کیفیت یا هزینهٔ نگهداری را بهتر کند. معیار اقتصادی مقایسه، هزینهٔ کل اجرا بهازای هر کار پذیرفتهشده با کیفیت و زمان پاسخ یکسان است.
