Mengapa LLM Dihoskan Sendiri Perlahan Untuk Ramai Pengguna
LLM anda perlahan kerana tetapan num_parallel lalai hanya memproses satu permintaan. Ketahui bagaimana batching dan KV cache mempengaruhi kapasiti pelayan anda hari ini.
Mengapakah LLM yang dihoskan sendiri menjadi perlahan apabila pengguna bertambah?
LLM yang dihoskan sendiri terhenti pada 5 pengguna serentak kerana pelayan masih menjana satu balasan pada satu masa, manakala empat pengguna yang lain berada dalam baris gilir. Dokumentasi Ollama menyatakan secara terus terang tentang tetapan lalai: OLLAMA_NUM_PARALLEL ialah "bilangan maksimum permintaan selari yang akan diproses oleh setiap model pada masa yang sama, lalai 1." Tiada apa-apa yang rosak. Empat daripada lima pengguna anda sedang menunggu giliran.
Penyelesaiannya jarang sekali memerlukan pelayan yang lebih berkuasa. Ia memerlukan enjin penyajian yang menolak banyak permintaan melalui model dalam satu laluan ke hadapan (forward pass), serta memori simpanan yang mencukupi untuk menampung perbualan setiap orang semasa proses tersebut berjalan. Kedua-dua bahagian ini penting, dan bahagian kedua itulah yang sebenarnya menetapkan had kapasiti anda.
Dua fasa yang dilalui oleh setiap permintaan
Prefill membaca keseluruhan prompt sekali gus dan membina cache perhatian (attention cache) untuknya. Setiap token prompt melalui model secara serentak, jadi prefill merupakan satu pendaraban matriks yang besar dan ia dihadkan oleh throughput aritmetik. Decode pula menulis jawapan satu token pada satu masa. Setiap token memerlukan pemberat (weights) penuh model dibaca daripada memori sekali lagi, manakala pengiraan aritmetik yang dilakukan pada token tunggal tersebut adalah sangat kecil. Decode dihadkan oleh lebar jalur memori (memory bandwidth).
Ketidaksimetrian tersebut adalah sebab utama batching berfungsi. Proses decoding untuk seorang pengguna membaca, katakan, 5 GB pemberat bagi setiap token dan membiarkan kebanyakan unit aritmetik tidak digunakan. Tambahkan permintaan kedua dan enjin akan membaca 5 GB yang sama sekali, kemudian mengira dua token daripadanya. Pengguna kedua hampir tidak memerlukan masa tambahan. Melayan permintaan secara berturutan (satu demi satu) akan mensia-siakan kelebihan ini.
Dua angka menggambarkan apa yang dirasai oleh pengguna. TTFT (time to first token) ialah masa menunggu dalam baris gilir ditambah dengan prefill. ITL (inter-token latency) ialah jurang antara token yang distrim, dan ia ditentukan oleh decode. Pelayan yang perlahan biasanya mengalami masalah pada salah satu fasa ini, dan penyelesaiannya tidak sama. Anda perlu menentukan fasa mana yang menjadi masalah sebelum mengubah sebarang tetapan, dan mengukur prefill dan decode secara berasingan ialah cara untuk mengetahuinya.
Batching statik menyebabkan semua orang menunggu respons yang paling perlahan
Batching statik ialah versi naif, dan inilah yang anda peroleh jika anda mengumpulkan permintaan sendiri dalam kod aplikasi. Enjin mengumpul N permintaan, menjalankannya bersama-sama, dan menahan setiap slot sehingga penjanaan paling lama dalam kumpulan tersebut selesai.
Seorang pengguna yang meminta ringkasan 1,200 token menyebabkan empat jawapan satu baris terkunci dalam batch tersebut, kerana batch tidak melepaskan sebarang slot sehingga ahli yang paling perlahan selesai.
Dua kos akan timbul. Jujukan yang telah selesai terus menduduki slot yang tidak mengira apa-apa yang berguna, jadi throughput berkesan menurun apabila panjang output berbeza-beza, dan panjang output sembang sangat berbeza. Permintaan yang tiba satu langkah selepas batch dibentuk perlu menunggu keseluruhan batch selesai sebelum ia bermula dengan prefill, yang bermaksud TTFT bagi permintaan tersebut ditentukan oleh esei orang lain.
Continuous batching menerima dan menamatkan permintaan bagi setiap token
Continuous batching menjadualkan pada tahap langkah penyahkodan tunggal. Selepas setiap langkah, penjadual akan menggugurkan jujukan yang baru sahaja mengeluarkan token henti, kemudian menerima permintaan yang menunggu ke dalam slot yang kosong. Balasan yang berakhir pada langkah 40 akan mengosongkan slotnya pada langkah 40, bukan pada penghujung kelompok (batch).
Ini bukanlah sesuatu yang luar biasa. llama-server mendokumentasikan -cb, --cont-batching sebagai "sama ada untuk mendayakan continuous batching (juga dikenali sebagai dynamic batching) (lalai: didayakan)", dan vLLM dibina berdasarkan konsep ini. Ollama juga melayani permintaan selari. Tetapan lalai hanya mengehadkan bilangan kepada satu, itulah sebabnya ramai orang membuat kesimpulan bahawa perkakasan mereka tidak mampu melakukan konkurensi, sedangkan konfigurasi merekalah yang menetapkan sebaliknya.
Hasil continuous batching yang diterbitkan biasanya diukur pada kad pusat data yang mempunyai kedua-dua pengkomputeran lebihan dan puluhan gigabait untuk cache. Bentuk hasil tersebut boleh diguna pakai pada mesin anda. Namun, saiznya tidak sama, dan bahagian memori di bawah menjelaskan sebabnya.
Prefill bersaing dengan decode untuk sumber pengiraan yang sama
Apabila permintaan baharu tiba semasa empat balasan sedang distrim, promptnya perlu diprefill terlebih dahulu, dan prefill adalah proses yang berat dari segi pengiraan. Jika penjadual memberikan langkah tersendiri kepada prefill tersebut, empat pengguna yang sedang menstrim tidak akan menerima token sepanjang tempoh itu. Bagi prompt yang panjang, ini merupakan jeda yang ketara dalam setiap tetingkap yang terbuka. Inilah yang dimaksudkan sebagai "stutter" apabila pengguna mengatakan pelayan tersangkut setiap kali ada orang lain menekan butang hantar.
Chunked prefill memecahkan prompt yang panjang kepada beberapa bahagian dan mencampurkan setiap bahagian ke dalam langkah yang sama dengan proses decode yang sedang berjalan. Panduan penalaan vLLM menyatakan pertukaran (tradeoff) ini secara terus: bajet chunk yang lebih kecil "mencapai ITL yang lebih baik kerana terdapat lebih sedikit prefill yang melambatkan proses decode", manakala nilai yang lebih tinggi "mencapai masa ke token pertama (TTFT) yang lebih baik kerana anda boleh memproses lebih banyak token prefill dalam satu batch". Anda sedang memilih pengalaman pengguna mana yang ingin dilindungi: orang yang menunggu balasan bermula, atau orang yang sedang melihat teks distrim.
Panjang prompt menentukan sejauh mana kesan ini dirasai. Prompt sepanjang 6,000 token dengan jawapan 200 token bermakna 6,000 token kerja prefill berbanding 200 langkah decode. Sembang yang dipertingkatkan dengan perolehan (RAG) dan prompt sistem yang panjang kedua-duanya menolak anda ke dalam situasi tersebut, jadi prefill bukan lagi sekadar ralat pembundaran tetapi menjadi perkara yang ditunggu oleh pengguna. Prefix caching membantu apabila bahagian yang panjang itu berulang: vLLM mendedahkan --enable-prefix-caching, yang menggunakan semula cache untuk awalan prompt yang dikongsi dan bukannya mengira semula untuk setiap permintaan.
Memori yang kehabisan ruang terlebih dahulu ialah KV cache
Setiap token dalam setiap perbualan aktif meninggalkan vektor kunci (key vector) dan vektor nilai (value vector) dalam setiap lapisan model. Inilah yang dipanggil KV cache (key/value cache), dan ia membolehkan proses penyahkodan (decode) mengelakkan pengiraan semula keseluruhan prompt bagi setiap token baharu. Saiznya bagi setiap token ditetapkan oleh bentuk model: 2 (satu kunci, satu nilai) didarab dengan bilangan lapisan, didarab dengan bilangan kepala kunci/nilai, didarab dengan dimensi kepala, didarab dengan bait bagi setiap nilai. Baca nombor-nombor tersebut daripada config.json model.
Kira sekali dan had maksimum tersebut tidak lagi menjadi misteri. Model 8B tipikal dengan 36 lapisan, 8 kepala kunci/nilai dan dimensi kepala 128, yang menyimpan cache dalam 16-bit, memerlukan 2 36 8 128 2 bait bagi setiap token. Ini bersamaan dengan 147,456 bait, kira-kira 144 KiB. Oleh itu, satu perbualan dengan 8,192 token memerlukan kira-kira 1.2 GB cache. Lima perbualan memerlukan kira-kira 6 GB, di samping berat model (weights), dan itulah jawapan sebenar bagi persoalan berapa ramai pengguna yang boleh ditampung.
Konkurensi (concurrency) mendarabkan konteks, dan alatan yang digunakan menyatakan perkara ini dengan jelas. FAQ Ollama: "Pemprosesan permintaan selari bagi model tertentu akan meningkatkan saiz konteks mengikut bilangan permintaan selari tersebut. Sebagai contoh, konteks 2K dengan 4 permintaan selari akan menghasilkan konteks 8K dan peruntukan memori tambahan." RAM yang diperlukan berskala mengikut OLLAMA_NUM_PARALLEL didarab dengan OLLAMA_CONTEXT_LENGTH. Dalam llama-server, konteks yang anda minta dengan -c dikongsi merentasi -np slot, jadi meningkatkan bilangan slot secara sendirinya akan mengecilkan kapasiti yang boleh ditampung oleh setiap permintaan. Baca konteks bagi setiap slot daripada log permulaan dan jangan hanya membuat andaian.
vLLM melakukan praperuntukan (preallocate) sebagai gantinya. --gpu-memory-utilization (lalai 0.92) ialah "pecahan memori GPU yang akan digunakan untuk pelaksana model". Apa sahaja yang berbaki selepas berat model dimuatkan akan menjadi kolam KV berpag (paged KV pool), dan apabila kolam itu kehabisan ruang, penjadual akan menyingkirkan (evict) permintaan tersebut dan bukannya membiarkannya gagal:
WARNING 05-09 00:49:33 scheduler.py:1057] Sequence group 0 is preempted by PreemptionMode.RECOMPUTE mode because there is not enough KV cache space.Dalam enjin V1 vLLM, mod prapenuntutan (preemption) lalai ialah RECOMPUTE, jadi permintaan yang disingkirkan akan membuang cache-nya dan melakukan praisi (prefill) semula apabila ia diterima masuk semula. Kerja tersebut dilakukan dua kali. Dokumentasi memberi amaran bahawa "prapenuntutan dan pengiraan semula boleh menjejaskan kependaman (latency) hujung-ke-hujung secara negatif", dan baris log ini merupakan penjelasan terbaik mengapa seorang pengguna yang kurang bernasib baik terpaksa menunggu jauh lebih lama daripada orang lain walaupun purata prestasi anda kelihatan sihat. Tetapkan disable_log_stats=False untuk mencatat kiraan kumulatif, atau baca pembilang prapenuntutan daripada metrik Prometheus yang didedahkan oleh vLLM.
Perubahan pada 2, 5 dan 20 pengguna serentak
Dua pengguna. Hampir tidak kelihatan pada GPU dengan cache yang mencukupi, kerana aliran nyahkod kedua berjalan bersama aliran pertama dengan tambahan masa yang sangat sedikit. Pada VPS berasaskan CPU dengan 4 hingga 8 GB RAM, ia tidak percuma: kedua-dua aliran berkongsi bilangan vCPU dan lebar jalur RAM yang sama, jadi setiap pengguna melihat kira-kira separuh daripada token sesaat, dan permintaan cache meningkat dua kali ganda berbanding bajet yang jauh lebih kecil.
Lima pengguna. Di sinilah tetapan lalai tidak lagi mencukupi, dan ia bermula sebagai masalah baris gilir. Dengan OLLAMA_NUM_PARALLEL pada 1, empat orang menunggu sesiapa sahaja yang meminta jawapan panjang, dan setiap daripada mereka melihat kelajuan biasa sebaik sahaja giliran mereka tiba. Tingkatkan kiraan selari dan masalah tersebut berubah bentuk: lima slot pada 8K konteks setiap satu bermakna 40K token cache perlu dicari. Jika ia tidak muat dalam VRAM, enjin akan memindahkan lapisan ke RAM sistem, dan jika ia tidak muat dalam RAM, pelayan akan melakukan swap dan token sesaat akan merosot.
Dua puluh pengguna. Dua puluh manusia dalam UI sembang biasanya bukan dua puluh permintaan serentak, dan ini adalah perkara paling berguna untuk difahami sebelum membeli perkakasan. Seseorang membaca balasan dan berfikir selama 20 hingga 60 saat antara giliran, jadi kebanyakan sesi mereka adalah melahu. Dua puluh ejen, atau dua puluh kerja meringkaskan dokumen, adalah dua puluh aliran sebenar tanpa masa melahu langsung. Itu memerlukan mesin yang berbeza. Seorang pembangun yang telah menghalakan ejen pengekodan ke pelayan Ollama mereka sendiri berada lebih dekat dengan kes kedua berbanding yang pertama, kerana ejen tersebut terus menghantar permintaan selagi tugas berjalan dan tidak meninggalkan jeda membaca seperti yang dilakukan oleh manusia.
Adakah pengguna anda serentak, atau sekadar log masuk?
Tentukan permintaan yang sedang diproses sebelum anda menetapkan saiz apa pun. Pengiraannya mudah: permintaan serentak bersamaan dengan bilangan pengguna, didarab dengan saat yang dihabiskan untuk menjana bagi setiap pusingan, dibahagikan dengan saat antara pusingan.
- Ukur kelajuan aliran tunggal anda sendiri terlebih dahulu, kedua-dua prefill dan decode. Jangan meminjam nombor daripada kad orang lain: ukur token sesaat pada mesin anda sendiri dan gunakan nilai yang anda perolehi.
- Anggarkan kitaran tugas (duty cycle). Dua puluh pengguna sembang, 12 saat penjanaan bagi setiap pusingan, satu pusingan setiap 90 saat, memberikan 20 * 12 / 90, iaitu kira-kira 2.7 permintaan serentak.
- Tetapkan bilangan slot sedikit melebihi jumlah tersebut, kemudian semak terhadap memori: slot didarab dengan konteks bagi setiap permintaan mestilah muat di dalam token cache yang anda miliki.
- Pastikan baris gilir pendek supaya limpahan gagal dengan cepat dan jelas.
Token cache yang tersedia adalah memori bebas selepas pemberat (weights), dibahagikan dengan kos bagi setiap token daripada bahagian di atas. Kad 24 GB yang menjalankan model 8B dalam 16-bit menggunakan kira-kira 16 GB untuk pemberat dan mempunyai kira-kira 6 GB cache yang boleh digunakan pada penggunaan lalai, iaitu sekitar lima perbualan 8K. Untuk memuatkan lebih banyak, pendekkan konteks bagi setiap permintaan, atau simpan cache dalam 8-bit (llama-server mengambil --cache-type-k q8_0). Kedua-duanya meningkatkan keserentakan dengan mengorbankan sesuatu, dan versi jujur mengenai pertukaran tersebut wajar dibaca sebelum anda melaburkan wang pada perkakasan: di mana GPU VPS mencapai titik pulang modal berbanding token API.
Apabila tetapan lalai Ollama tidak lagi mencukupi
Tingkatkan kiraan selari melalui unit servis, kerana eksport shell tidak akan sampai kepada daemon yang diuruskan oleh systemd.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_MAX_QUEUE=64"sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment
ollama pssystemctl show sepatutnya memaparkan tiga pemboleh ubah yang baru anda tetapkan. Jika tidak, fail drop-in tersebut tidak disimpan dan sebarang tindakan lain tidak akan memberi kesan. ollama ps kemudian menyenaraikan model yang dimuatkan dengan saiz yang lebih besar daripada berat (weights) sahaja, kerana empat slot pada 8,192 token akan menempah 32,768 token cache di sampingnya. Lajur PROCESSOR yang menunjukkan sebahagian model berada pada CPU sedangkan anda menjangkakan semuanya pada GPU bermakna anda meminta lebih banyak cache daripada kapasiti kad yang tinggal. Rendahkan salah satu daripada dua nombor tersebut. Mengurangkan konteks biasanya lebih selamat, namun tetingkap yang terlalu kecil akan memotong prompt yang panjang secara senyap tanpa mengeluarkan ralat, jadi adalah lebih baik untuk menentukan num_ctx secara sengaja daripada mengurangkannya sehingga model tersebut muat.
Nilai lalai baris gilir (queue) perlu diperiksa semula. Ollama menyusun sehingga OLLAMA_MAX_QUEUE permintaan, dan "nilai lalai ialah 512". Melebihi had itu, ia akan membalas "dengan ralat 503 yang menunjukkan pelayan terlebih beban". Baris gilir sedalam 512 pada mesin yang melayani empat permintaan serentak adalah janji yang tidak dapat anda tunaikan, kerana klien pada kedudukan 300 akan tamat tempoh (timeout) jauh sebelum gilirannya tiba. Baris gilir yang pendek akan mengembalikan ralat yang boleh dicuba semula atau dilaporkan oleh aplikasi anda, yang lebih baik daripada penunjuk muat (spinner) yang tidak pernah selesai.
Uji perkara ini secara sebenar. Hantar dua permintaan pada saat yang sama dari dua terminal dan perhatikan kedua-duanya. Jika permintaan kedua tidak menghasilkan apa-apa sehingga permintaan pertama selesai, tetapan selari tersebut tidak berkesan.
Apabila enjin penyajian sebenar mula memberikan pulangan
vLLM memberikan nilai setara dengan usaha penyediaannya apabila anda mempunyai GPU dengan ruang lebihan dan lebih daripada kira-kira empat permintaan yang sedang diproses secara serentak. Penjadualnya berfungsi mengikut token, cache-nya dipetakan (paged) supaya serpihan memori yang bebas digunakan semula, dan ia menukarkan VRAM terbiar kepada konkurensi dan bukannya membiarkannya tidak digunakan. Setakat Ogos 2026, pemasangan dan pelancaran yang didokumentasikan hanya memerlukan dua arahan:
uv pip install vllm --torch-backend=auto
vllm serve Qwen/Qwen2.5-1.5B-Instructcurl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [{"role": "user", "content": "Say hello."}]
}'Balasan yang mengandungi tatasusunan choices bermaksud pelayan telah aktif dan model telah dimuatkan. Di bawah beban kerja, dua tetapan yang penting ialah --max-num-seqs, iaitu "bilangan maksimum jujukan yang diproses dalam satu lelaran", dan --max-num-batched-tokens, iaitu "bilangan maksimum token yang boleh diproses dalam satu lelaran". Tetapan pertama mengehadkan konkurensi. Tetapan kedua ialah belanjawan pra-pengisian (prefill) berketul yang diterangkan sebelum ini.
Di bawah kira-kira empat permintaan yang sedang diproses, atau pada mana-mana mesin tanpa GPU yang disokong, vLLM hanya menambah kerumitan tanpa memberikan banyak manfaat. Ia memerlukan kad kelas CUDA dan menuntut sebahagian besar memori semasa permulaan, yang merupakan pertukaran yang tidak wajar pada VPS bersaiz 4 hingga 8 GB. Dalam situasi tersebut, penyelesaiannya ialah model yang lebih kecil dengan konteks yang lebih pendek dan baris gilir yang anda kawal. perbezaan antara Ollama dan vLLM sebagai enjin penyajian merangkumi pilihan tersebut sepenuhnya, dan menjalankan Qwen 3 8B pada VPS menunjukkan keperluan model bersaiz sederhana sebelum anda menambah seorang pun pengguna tambahan.
Pertukaran yang disembunyikan oleh cerita rakyat
Continuous batching meningkatkan jumlah throughput, dan ia biasanya menambah baik median latency juga, kerana permintaan yang beratur bermula lebih awal. Tail latency bergerak ke arah sebaliknya, dan separuh bahagian itu jarang disebut.
Setiap urutan tambahan dalam satu langkah menambah sedikit kerja, jadi ITL meningkat untuk semua orang apabila batch penuh. Prefill bagi permintaan baharu mengambil sebahagian daripada langkah yang sepatutnya dimiliki oleh pengguna streaming. Di bawah tekanan cache, scheduler akan melakukan preemption, yang menghantar permintaan yang separuh dijana kembali ke permulaan prefill-nya.
UI sembang menunjukkan tail, bukan purata. Stream yang terhenti selama dua saat di tengah ayat kelihatan rosak walaupun jumlah masa untuk selesai adalah baik. Ukur p95 TTFT dan p95 ITL di bawah beban yang anda jangkakan, dan anggap purata token per saat sebagai nombor kapasiti dan bukannya gambaran pengalaman pengguna.
Tetapan praktikal adalah berdasarkan perkara tersebut. Hadkan concurrency sedikit di bawah apa yang dibenarkan oleh memori, supaya enjin tidak perlu melakukan preemption. Barisan yang pendek dan boleh diramal adalah lebih baik daripada batch yang dalam tetapi mengalami thrashing, kerana pengguna yang menunggu selama empat saat dan kemudian melakukan streaming dengan lancar adalah lebih gembira berbanding pengguna yang bermula serta-merta tetapi terhenti dua kali.
Perkara yang perlu diperiksa apabila sistem menjadi perlahan
Setiap pengguna adalah normal, tetapi masa menunggu lama. Ini adalah masalah baris gilir, bukan masalah kelajuan. Periksa tetapan selari (parallel) terlebih dahulu. Model sedang beroperasi dengan betul, satu permintaan pada satu masa.
HTTP 503 daripada Ollama. Baris gilir sudah penuh. Sama ada pelayan benar-benar mencapai kapasiti maksimum, atau OLLAMA_MAX_QUEUE ditetapkan rendah secara sengaja untuk mengurangkan beban, yang merupakan tindakan yang sepatutnya dilakukan.
Token sesaat (tokens per second) merosot di bawah beban pada pelayan CPU. Jalankan vmstat 1 semasa ia berlaku. Lajur si dan so yang bukan sifar bermakna mesin sedang melakukan swapping, jadi pemberat (weights) sedang dibaca daripada cakera pada setiap token. Tiada perubahan konfigurasi yang dapat mengatasi masalah ini. Kurangkan saiz model atau bilangan slot.
Seorang daripada sepuluh pengguna menunggu jauh lebih lama daripada yang lain. Cari preempted dalam log vLLM. Preemption dan pengiraan semula (recompute) adalah punca biasa, dan ini bermakna cache telah terlebih langgan (oversubscribed) untuk panjang konteks yang anda benarkan.
TTFT (Time To First Token) adalah buruk walaupun pelayan melahu. Ini adalah masalah prefill, bukan konkurensi. Prompt yang panjang mengambil masa sebenar sebelum token pertama muncul, jadi lihat pada saiz prompt dan prefix caching sebelum anda melihat perkakasan. Jika masa menunggu yang lama hanya berlaku kepada orang pertama selepas tempoh senyap dan semua orang selepas mereka adalah baik, itu bukanlah masalah prefill, sebaliknya Ollama memunggah (unload) model dan membaca semula pemberat daripada cakera. Perkara ini patut diselesaikan dengan mengekalkan model dalam memori antara permintaan.
FAQ
Mengapakah LLM yang saya hos sendiri menjadi perlahan apabila orang kedua menggunakannya?
Kebiasaannya, ia tidak menjadi perlahan. Ia beratur. Ollama dihantar dengan OLLAMA_NUM_PARALLEL pada 1, jadi permintaan kedua menunggu sehingga permintaan pertama mengeluarkan token terakhirnya. Bezakan kedua-dua kes ini dengan mengukur masa aliran satu pengguna sementara pengguna lain menunggu: jika token sesaat mereka adalah normal sebaik sahaja mereka bermula, anda mempunyai baris gilir, dan meningkatkan kiraan selari akan menyelesaikannya. Jika kedua-dua aliran berjalan pada separuh kelajuan, anda sebenarnya berkongsi lebar jalur memori, dan itu adalah had perkakasan.
Berapa ramai pengguna serentak yang boleh diservis oleh satu GPU kecil?
Kira memori, bukan pengguna. Berat (weights) didahulukan, kemudian cache KV, yang menelan kos 2 kali ganda lapisan kali kepala kunci/nilai kali dimensi kepala kali bait, bagi setiap token, bagi setiap perbualan aktif. Model 8B tipikal dengan 36 lapisan, 8 kepala kunci/nilai dan dimensi kepala 128 menelan kos kira-kira 144 KiB bagi setiap token dalam 16-bit, jadi perbualan 8,192 token memerlukan kira-kira 1.2 GB. Kad 24 GB yang memuatkan model tersebut dalam 16-bit mempunyai kira-kira 6 GB yang tinggal untuk cache, iaitu kira-kira lima perbualan pada konteks penuh, atau lebih jika anda memendekkan konteks.
Adakah continuous batching menjadikan balasan setiap pengguna lebih perlahan?
Latensi median biasanya bertambah baik, kerana permintaan berhenti menunggu keseluruhan kelompok selesai. Latensi ekor menjadi lebih teruk. Setiap urutan tambahan menambah kerja pada setiap langkah penyahkodan, prefill ketibaan baharu mencuri sebahagian langkah daripada pengguna yang sedang menstrim, dan permintaan yang didahului (preempted) perlu melakukan prefill dua kali. Ukur latensi antara token p95, bukan purata, kerana tetingkap sembang menjadikan jeda jelas kelihatan dengan cara yang disembunyikan oleh purata.
Patutkah saya meningkatkan OLLAMA_NUM_PARALLEL atau beralih ke vLLM?
Tingkatkan kiraan selari dahulu. Ia percuma dan hanya memerlukan satu fail drop-in, dan ia menyelesaikan kes biasa di mana empat orang beratur di belakang satu jawapan yang panjang. Memori adalah hadnya: permintaan selari mendarabkan konteks yang perlu anda pegang, jadi perhatikan lapisan yang melimpah ke CPU. Beralih ke vLLM apabila anda mempunyai GPU dengan VRAM yang mencukupi dan lebih daripada kira-kira empat permintaan yang benar-benar sedang berjalan, kerana itu adalah titik di mana cache berpag (paged cache) dan penjadualan setiap token memberikan hasil yang lebih berbaloi daripada kosnya.
Adakah lebih banyak teras CPU akan membaiki pelayan LLM yang perlahan?
Tidak untuk bahagian yang paling disedari oleh pengguna. Penyahkodan membaca keseluruhan model daripada memori untuk setiap token, jadi ia terikat dengan lebar jalur RAM, dan teras tambahan berhenti membantu sebaik sahaja lebar jalur tepu. Prefill memang berskala dengan teras, jadi lebih banyak teras memendekkan masa untuk token pertama pada prompt yang panjang. Pada VPS 4 hingga 8 GB, kekangan pengikatan biasanya adalah kapasiti memori, dan penyelesaian yang berkesan ialah model yang lebih kecil atau konteks yang lebih pendek dan bukannya lebih banyak vCPU.