SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-13

Dlaczego serwer LLM zwalnia przy wielu użytkownikach?

Dowiedz się, dlaczego przy 5 użytkownikach LLM przestaje działać płynnie. Wyjaśniamy rolę parametru num_parallel, fazy prefill, KV cache oraz kolejkowania zapytań w serwerze.

Dlaczego samodzielnie hostowany model LLM zwalnia przy większej liczbie użytkowników?

Samodzielnie hostowany model LLM przestaje płynnie działać przy 5 jednoczesnych użytkownikach, ponieważ serwer generuje w danej chwili tylko jedną odpowiedź, a pozostałe cztery oczekują w kolejce. Dokumentacja Ollama jasno określa ustawienie domyślne: OLLAMA_NUM_PARALLEL to „maksymalna liczba równoległych żądań, które model przetworzy w tym samym czasie, wartość domyślna wynosi 1”. Nie oznacza to awarii. Czterech z pięciu użytkowników po prostu czeka na swoją kolej.

Rozwiązaniem rzadko jest wymiana sprzętu na mocniejszy. Należy zastosować silnik serwujący, który przesyła wiele żądań przez model w jednym przebiegu (forward pass), oraz zapewnić wystarczającą ilość wolnej pamięci, aby utrzymać konwersacje wszystkich użytkowników w trakcie przetwarzania. Obie kwestie są istotne, przy czym to druga z nich faktycznie wyznacza limit wydajności.

Dwie fazy przetwarzania każdego żądania

Faza prefill odczytuje cały prompt jednocześnie i buduje dla niego pamięć podręczną atencji (attention cache). Każdy token promptu przechodzi przez model wspólnie, dlatego prefill jest jedną dużą operacją mnożenia macierzy, ograniczoną przepustowością obliczeniową. Faza decode generuje odpowiedź token po tokenie. Każdy token wymaga ponownego odczytania pełnych wag modelu z pamięci, podczas gdy operacje arytmetyczne dla pojedynczego tokena są znikome. Faza decode jest ograniczona przepustowością pamięci.

Ta asymetria jest głównym powodem, dla którego batching działa. Dekodowanie dla jednego użytkownika odczytuje, przykładowo, 5 GB wag na token, pozostawiając większość jednostek obliczeniowych w stanie bezczynności. Dodanie drugiego żądania sprawia, że silnik odczytuje te same 5 GB raz, a następnie oblicza dwa tokeny. Drugi użytkownik nie generuje niemal żadnego dodatkowego czasu oczekiwania. Obsługa żądań ściśle jedno po drugim marnuje ten potencjał.

Odczucia użytkownika opisują dwie wartości. TTFT (time to first token) to czas oczekiwania w kolejce plus czas fazy prefill. ITL (inter-token latency) to odstęp między przesyłanymi strumieniowo tokenami, określany przez fazę decode. Wolny serwer zazwyczaj wykazuje opóźnienia w jednym z tych obszarów, a metody naprawcze są w obu przypadkach odmienne.

Statyczne przetwarzanie wsadowe powoduje, że wszyscy czekają na najwolniejszą odpowiedź

Statyczne przetwarzanie wsadowe to rozwiązanie naiwne, uzyskiwane w przypadku samodzielnego grupowania żądań w kodzie aplikacji. Silnik gromadzi N żądań, uruchamia je jednocześnie i blokuje każdy slot do momentu zakończenia generowania najdłuższej odpowiedzi w grupie.

Jeden użytkownik proszący o podsumowanie o długości 1200 tokenów powoduje zablokowanie czterech jednowierszowych odpowiedzi wewnątrz wsadu, ponieważ wsad nie zwalnia żadnego slotu, dopóki jego najwolniejszy element nie zakończy pracy.

Pociąga to za sobą dwa rodzaje kosztów. Zakończone sekwencje nadal zajmują sloty, w których nie odbywają się żadne użyteczne obliczenia, przez co efektywna przepustowość spada wraz ze zróżnicowaniem długości danych wyjściowych, a długość odpowiedzi w czatach jest bardzo zmienna. Żądanie, które dotrze jeden krok po utworzeniu wsadu, czeka na jego całkowite opróżnienie przed rozpoczęciem fazy prefill, co oznacza, że czas TTFT jest determinowany przez zadanie innego użytkownika.

Continuous batching przyjmuje i kończy żądania przy każdym tokenie

Continuous batching planuje pracę na poziomie pojedynczego kroku dekodowania. Po każdym kroku harmonogram usuwa sekwencje, które właśnie wygenerowały token stopu, a następnie przyjmuje oczekujące żądania w zwolnione miejsca. Odpowiedź kończąca się w kroku 40 zwalnia miejsce w kroku 40, a nie dopiero po zakończeniu całej partii.

Nie jest to rozwiązanie egzotyczne. llama-server opisuje -cb, --cont-batching jako „czy włączyć continuous batching (znany również jako dynamic batching) (domyślnie: włączone)”, a vLLM jest zbudowany w oparciu o tę koncepcję. Ollama również obsługuje żądania równoległe. Domyślne ustawienie ogranicza liczbę żądań do jednego, co jest powodem, dla którego wielu użytkowników błędnie zakłada, że ich sprzęt nie obsługuje współbieżności, podczas gdy w rzeczywistości wynika to z konfiguracji.

Publikowane wyniki wydajności continuous batching są zazwyczaj mierzone na kartach klasy serwerowej, które dysponują zarówno nadmiarem mocy obliczeniowej, jak i dziesiątkami gigabajtów pamięci na cache. Charakterystyka tych wyników przekłada się na lokalne środowisko, jednak ich skala – nie, co wyjaśnia poniższa sekcja dotycząca pamięci.

Prefill konkuruje z dekodowaniem o te same zasoby obliczeniowe

Gdy nowe żądanie trafia do systemu w trakcie strumieniowania czterech odpowiedzi, jego prompt musi zostać najpierw przetworzony w fazie prefill, która jest kosztowna obliczeniowo. Jeśli harmonogram zadań przydzieli tej fazie osobny krok, czterech użytkowników otrzymujących strumień danych nie otrzyma w tym czasie żadnego tokena. W przypadku długiego promptu jest to zauważalna pauza w każdym otwartym oknie. To właśnie to zacięcie użytkownicy określają mianem "czkawki" serwera, występującej w momencie, gdy ktoś inny wysyła zapytanie.

Chunked prefill dzieli długi prompt na fragmenty i miesza każdy z nich z tym samym krokiem, w którym wykonywane jest dekodowanie. Przewodnik optymalizacji vLLM jasno określa ten kompromis: mniejsze budżety fragmentów "zapewniają lepszy ITL, ponieważ mniej operacji prefill spowalnia dekodowanie", podczas gdy wyższe wartości "zapewniają lepszy czas do pierwszego tokena (TTFT), ponieważ w jednej partii można przetworzyć więcej tokenów prefill". Wybór zależy od tego, czyje doświadczenie ma być priorytetowe: osoby czekającej na rozpoczęcie odpowiedzi, czy osób obserwujących strumieniowanie tekstu.

Długość promptu decyduje o skali tego zjawiska. Prompt o długości 6000 tokenów z odpowiedzią 200 tokenów oznacza 6000 tokenów pracy prefill w porównaniu do 200 kroków dekodowania. Czat z wykorzystaniem RAG oraz długie prompty systemowe wprowadzają system w ten reżim, przez co prefill przestaje być pomijalnym kosztem i staje się głównym czynnikiem wpływającym na czas oczekiwania użytkownika. Prefix caching pomaga, gdy długa część promptu się powtarza: vLLM udostępnia --enable-prefix-caching, co pozwala na ponowne wykorzystanie pamięci podręcznej dla współdzielonego prefiksu promptu zamiast ponownego obliczania go dla każdego żądania.

Pamięć, która kończy się najszybciej, to KV cache

Każdy token w aktywnej konwersacji pozostawia wektor klucza i wektor wartości w każdej warstwie modelu. Jest to KV cache (pamięć podręczna kluczy/wartości), która pozwala procesowi dekodowania uniknąć ponownego obliczania całego promptu dla każdego nowego tokena. Rozmiar pamięci na token jest określony przez strukturę modelu: 2 (jeden klucz, jedna wartość) razy liczba warstw, razy liczba głowic kluczy/wartości, razy wymiar głowicy, razy liczba bajtów na wartość. Wartości te należy odczytać z config.json modelu.

Wykonanie obliczeń raz pozwala zrozumieć ograniczenia. Typowy model 8B z 36 warstwami, 8 głowicami kluczy/wartości i wymiarem głowicy 128, przechowujący cache w formacie 16-bitowym, zajmuje 2 36 8 128 2 bajtów na token. Daje to 147 456 bajtów, czyli około 144 KiB. Konwersacja o długości 8 192 tokenów wymaga zatem około 1,2 GB pamięci cache. Pięć takich konwersacji wymaga około 6 GB pamięci, poza wagami modelu, co stanowi rzeczywistą odpowiedź na pytanie o liczbę obsługiwanych użytkowników.

Współbieżność zwielokrotnia kontekst, co potwierdza dokumentacja narzędzi. FAQ Ollama: „Równoległe przetwarzanie żądań dla danego modelu skutkuje zwiększeniem rozmiaru kontekstu o liczbę żądań równoległych. Na przykład kontekst 2K przy 4 żądaniach równoległych spowoduje użycie kontekstu 8K i dodatkową alokację pamięci”. Wymagana pamięć RAM skaluje się zgodnie z OLLAMA_NUM_PARALLEL pomnożonym przez OLLAMA_CONTEXT_LENGTH. W llama-server kontekst zdefiniowany przez -c jest dzielony między sloty -np, więc zwiększenie liczby slotów automatycznie zmniejsza ilość miejsca dostępnego dla każdego żądania. Należy odczytać kontekst na slot z dziennika startowego, zamiast zakładać jego wartość.

vLLM stosuje prealokację. --gpu-memory-utilization (domyślnie 0.92) to „ułamek pamięci GPU używany przez executor modelu”. Wszystko, co pozostaje po załadowaniu wag, staje się pulą stronicowanego KV cache, a gdy pula ta się wyczerpie, scheduler usuwa żądanie zamiast doprowadzić do błędu:

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.

W silniku V1 vLLM domyślnym trybem preempcji jest RECOMPUTE, więc usunięte żądanie odrzuca swój cache i ponownie wykonuje prefill po ponownym przyjęciu. Praca ta jest wykonywana dwukrotnie. Dokumentacja ostrzega, że „preempcja i ponowne obliczenia mogą negatywnie wpływać na opóźnienia end-to-end”, a ten wpis w dzienniku jest najlepszym wyjaśnieniem, dlaczego jeden użytkownik czekał znacznie dłużej niż pozostali, podczas gdy średnie statystyki wyglądały poprawnie. Należy ustawić disable_log_stats=False, aby logować skumulowaną liczbę zdarzeń, lub odczytać licznik preempcji z metryk Prometheus udostępnianych przez vLLM.

Zmiany przy 2, 5 i 20 użytkownikach jednoczesnych

Dwóch użytkowników. Obciążenie jest niemal niezauważalne na GPU z zapasem pamięci podręcznej, ponieważ drugi strumień dekodowania jest przetwarzany równolegle z pierwszym przy minimalnym narzucie czasowym. Na serwerze VPS opartym wyłącznie na CPU z 4 do 8 GB pamięci RAM nie jest to operacja bezkosztowa: oba strumienie współdzielą tę samą niewielką liczbę vCPU oraz przepustowość pamięci RAM. W rezultacie każdy użytkownik otrzymuje mniej więcej połowę liczby tokenów na sekundę, a zapotrzebowanie na pamięć podręczną podwaja się w ramach znacznie mniejszego budżetu zasobów.

Pięciu użytkowników. Na tym etapie ustawienia domyślne przestają być wystarczające, a problem zaczyna się od kolejkowania zadań. Przy OLLAMA_NUM_PARALLEL ustawionym na 1, cztery osoby oczekują na zakończenie generowania długiej odpowiedzi przez pierwszą z nich, po czym każda z nich otrzymuje odpowiedź z normalną prędkością w swojej kolejce. Zwiększenie liczby zadań równoległych zmienia charakter problemu: pięć slotów po 8K kontekstu każdy wymaga 40K tokenów pamięci podręcznej. Jeśli nie mieszczą się one w VRAM, silnik przenosi warstwy do pamięci RAM systemu, a jeśli nie mieszczą się w RAM, serwer zaczyna korzystać z pliku wymiany (swap), co powoduje drastyczny spadek liczby tokenów na sekundę.

Dwudziestu użytkowników. Dwudziestu ludzi korzystających z interfejsu czatu zazwyczaj nie generuje dwudziestu jednoczesnych żądań, co jest kluczową kwestią do zrozumienia przed zakupem sprzętu. Użytkownik czyta odpowiedź i zastanawia się przez 20 do 60 sekund między kolejnymi turami, więc większość czasu sesji pozostaje bezczynna. Dwudziestu agentów lub dwadzieścia zadań podsumowywania dokumentów to dwadzieścia rzeczywistych strumieni bez czasu bezczynności. Wymaga to zupełnie innej konfiguracji sprzętowej.

Czy użytkownicy są aktywni jednocześnie, czy tylko zalogowani?

Przed dobraniem rozmiaru zasobów należy określić liczbę żądań w toku. Obliczenia są proste: liczba żądań w toku równa się liczbie użytkowników pomnożonej przez czas generowania w sekundach na turę, podzielonej przez czas w sekundach między turami.

  1. Najpierw zmierz własną prędkość dla pojedynczego strumienia, uwzględniając zarówno prefill, jak i dekodowanie. Nie należy przyjmować wartości z cudzej karty: zmierz liczbę tokenów na sekundę na własnym sprzęcie i użyj uzyskanego wyniku.
  2. Oszacuj cykl pracy. Dwudziestu użytkowników czatu, 12 sekund generowania na turę, jedna tura co 90 sekund, daje 20 * 12 / 90, czyli około 2,7 żądania w toku.
  3. Ustaw liczbę slotów nieco powyżej tej wartości, a następnie sprawdź ją pod kątem pamięci: liczba slotów pomnożona przez kontekst na żądanie musi mieścić się w dostępnych tokenach pamięci podręcznej.
  4. Utrzymuj krótką kolejkę, aby przepełnienie było wykrywane szybko i w sposób widoczny.

Dostępne tokeny pamięci podręcznej to wolna pamięć po załadowaniu wag, podzielona przez koszt na token określony w poprzedniej sekcji. Karta 24 GB obsługująca model 8B w 16-bitach zużywa około 16 GB na wagi i ma około 6 GB użytecznej pamięci podręcznej przy domyślnym wykorzystaniu, co odpowiada mniej więcej pięciu konwersacjom 8K. Aby zmieścić więcej, należy skrócić kontekst na żądanie lub przechowywać pamięć podręczną w 8-bitach (llama-server wymaga --cache-type-k q8_0). Obie metody zwiększają współbieżność kosztem innych parametrów, dlatego warto zapoznać się z uczciwą analizą tego kompromisu przed zainwestowaniem w sprzęt: kiedy GPU VPS staje się bardziej opłacalny niż tokeny API.

Kiedy domyślne ustawienia Ollama przestają wystarczać

Zwiększ liczbę równoległych zadań poprzez jednostkę serwisową, ponieważ zmienne wyeksportowane w powłoce nie dotrą do demona zarządzanego przez 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 ps

systemctl show powinno wyświetlić trzy zmienne, które właśnie ustawiono. Jeśli tak się nie stanie, plik typu drop-in nie został zapisany i dalsze działania nie przyniosą efektu. ollama ps wyświetla następnie załadowany model o rozmiarze większym niż same wagi, ponieważ cztery sloty po 8,192 tokeny rezerwują dodatkowo 32,768 tokenów pamięci podręcznej. Kolumna PROCESSOR pokazująca część modelu na CPU, mimo oczekiwania pełnego załadowania na GPU, oznacza, że przydzielono więcej pamięci podręcznej, niż karta posiadała w wolnych zasobach. Należy zmniejszyć jedną z tych dwóch wartości.

Domyślna kolejka wymaga ponownego rozważenia. Ollama kolejkuje do OLLAMA_MAX_QUEUE żądań, a „wartość domyślna to 512”. Powyżej tej liczby odpowiada „błędem 503 wskazującym na przeciążenie serwera”. Kolejka o głębokości 512 na serwerze obsługującym cztery zadania jednocześnie to obietnica bez pokrycia, ponieważ klient na pozycji 300 przekroczy limit czasu oczekiwania na długo przed swoją koleją. Krótka kolejka zwraca błąd, który aplikacja może ponowić lub zaraportować, co jest lepszym rozwiązaniem niż nieskończenie ładujący się wskaźnik.

Przeprowadź testy w warunkach rzeczywistych. Wyślij dwa żądania w tym samym momencie z dwóch terminali i obserwuj oba. Jeśli drugie żądanie nie generuje odpowiedzi, dopóki pierwsze się nie zakończy, ustawienie równoległości nie weszło w życie.

Kiedy silnik serwujący zaczyna przynosić korzyści

vLLM zyskuje na znaczeniu, gdy dysponujesz GPU z zapasem mocy i obsługujesz więcej niż około cztery żądania jednocześnie. Harmonogram działa na poziomie tokenów, pamięć podręczna jest stronicowana, co pozwala na ponowne wykorzystanie wolnych fragmentów, a niewykorzystana pamięć VRAM jest przekształcana w większą współbieżność zamiast pozostawać bezczynną. Według stanu na sierpień 2026 r. udokumentowana instalacja i uruchomienie sprowadzają się do dwóch poleceń:

uv pip install vllm --torch-backend=auto
vllm serve Qwen/Qwen2.5-1.5B-Instruct
curl 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."}]
    }'

Odpowiedź zawierająca tablicę choices oznacza, że serwer działa, a model został załadowany. Przy obciążeniu kluczowe są dwa parametry: --max-num-seqs, czyli „maksymalna liczba sekwencji przetwarzanych w jednej iteracji”, oraz --max-num-batched-tokens, czyli „maksymalna liczba tokenów, które mogą zostać przetworzone w jednej iteracji”. Pierwszy z nich ogranicza współbieżność. Drugi stanowi budżet przetwarzania wstępnego (prefill) opisany wcześniej.

Przy mniej niż czterech żądaniach w toku lub na maszynie bez wspieranego GPU, vLLM wprowadza niepotrzebną złożoność, nie oferując wymiernych korzyści. Oprogramowanie wymaga karty klasy CUDA i rezerwuje większość pamięci przy starcie, co jest nieefektywne w przypadku VPS z 4 do 8 GB RAM. W takiej sytuacji lepszym rozwiązaniem jest mniejszy model z krótszym kontekstem i własna kolejka żądań. różnice między Ollama a vLLM jako silnikami serwującymi szczegółowo omawia ten wybór, a uruchamianie Qwen 3 8B na VPS pokazuje wymagania średniej wielkości modelu, zanim dodasz choćby jednego dodatkowego użytkownika.

Kompromis pomijany w obiegowych opiniach

Continuous batching zwiększa całkowitą przepustowość i zazwyczaj poprawia medianę opóźnień, ponieważ kolejkowane żądanie rozpoczyna się wcześniej. Opóźnienia w ogonie rozkładu (tail latency) zachowują się odwrotnie, a o tym aspekcie wspomina się rzadko.

Każda dodatkowa sekwencja w kroku generuje niewielki narzut, więc ITL rośnie dla wszystkich użytkowników w miarę zapełniania się partii. Prefill nowego żądania zajmuje część kroku, który w przeciwnym razie byłby dostępny dla użytkowników korzystających ze streamingu. W warunkach presji na pamięć podręczną scheduler wykonuje preempcję, co powoduje cofnięcie częściowo wygenerowanego żądania do początku fazy prefill.

Interfejs czatu odzwierciedla opóźnienia w ogonie, a nie średnie. Stream, który zatrzymuje się na dwie sekundy w połowie zdania, jest odbierany jako uszkodzony, nawet jeśli całkowity czas zakończenia generowania jest zadowalający. Należy mierzyć p95 TTFT oraz p95 ITL pod przewidywanym obciążeniem, a średnią liczbę tokenów na sekundę traktować jako wskaźnik wydajności, a nie opis odczuć użytkownika.

Z tego wynikają praktyczne ustawienia. Należy ograniczyć współbieżność nieco poniżej limitów pamięci, aby silnik nigdy nie musiał wykonywać preempcji. Krótka, przewidywalna kolejka jest lepsza niż duża partia powodująca thrashing, ponieważ użytkownik, który czeka cztery sekundy, a następnie otrzymuje płynny strumień, jest bardziej zadowolony niż użytkownik, który zaczyna natychmiast, ale doświadcza dwóch zacięć.

Co sprawdzić w przypadku niskiej wydajności

Każdy użytkownik działa poprawnie, ale czas oczekiwania jest długi. Jest to problem kolejkowania, a nie szybkości. W pierwszej kolejności należy sprawdzić ustawienie równoległości. Model obsługuje żądania poprawnie, ale pojedynczo.

Błąd HTTP 503 z Ollama. Kolejka jest pełna. Serwer osiągnął swoje rzeczywiste limity wydajnościowe lub wartość OLLAMA_MAX_QUEUE została celowo ustawiona na niskim poziomie w celu odciążenia systemu, co jest pożądanym zachowaniem.

Liczba tokenów na sekundę drastycznie spada przy obciążeniu na serwerze CPU. W trakcie występowania problemu należy uruchomić vmstat 1. Wartości niezerowe w kolumnach si oraz so oznaczają, że system korzysta ze swapu, co powoduje odczytywanie wag z dysku przy generowaniu każdego tokena. Żadna zmiana konfiguracji tego nie naprawi. Należy zmniejszyć rozmiar modelu lub liczbę slotów.

Jeden na dziesięciu użytkowników czeka znacznie dłużej niż pozostali. W dzienniku vLLM należy wyszukać preempted. Najczęstszą przyczyną jest preemption i związana z nim rekonfiguracja, co oznacza, że cache jest nadmiernie obciążony w stosunku do dopuszczalnej długości kontekstu.

Czas TTFT jest wysoki nawet przy bezczynnym serwerze. Jest to problem fazy prefill, a nie współbieżności. Długie prompty wymagają czasu przed wygenerowaniem pierwszego tokena, dlatego przed analizą sprzętu należy sprawdzić rozmiar promptu oraz mechanizm prefix caching.

FAQ

Dlaczego mój samodzielnie hostowany LLM zwalnia, gdy korzysta z niego druga osoba?

Najczęściej nie zwalnia, lecz ustawia się w kolejce. Ollama jest dostarczana z OLLAMA_NUM_PARALLEL ustawionym na 1, więc drugie żądanie czeka, aż pierwsze wyemituje swój ostatni token. Rozróżnij te dwa przypadki, mierząc czas strumienia jednego użytkownika, podczas gdy drugi czeka: jeśli liczba tokenów na sekundę jest normalna po rozpoczęciu generowania, oznacza to kolejkę, a zwiększenie liczby równoległych zadań rozwiąże problem. Jeśli oba strumienie działają z połową prędkości, faktycznie współdzielisz przepustowość pamięci, co jest ograniczeniem sprzętowym.

Ilu jednoczesnych użytkowników może obsłużyć jedna mała karta GPU?

Licz pamięć, nie użytkowników. Najpierw wagi, potem pamięć podręczna KV, która kosztuje 2 razy liczba warstw razy liczba głowic klucza/wartości razy wymiar głowicy razy bajty, na token, na aktywną konwersację. Typowy model 8B z 36 warstwami, 8 głowicami klucza/wartości i wymiarem głowicy 128 kosztuje około 144 KiB na token w formacie 16-bitowym, więc konwersacja na 8,192 tokeny wymaga około 1.2 GB. Karta 24 GB mieszcząca ten model w 16-bitach ma około 6 GB wolnego miejsca na pamięć podręczną, co wystarcza na około pięć konwersacji przy pełnym kontekście lub więcej, jeśli skrócisz kontekst.

Czy przetwarzanie wsadowe (continuous batching) spowalnia odpowiedź dla każdego użytkownika?

Mediana opóźnień zazwyczaj się poprawia, ponieważ żądania przestają czekać na zakończenie całego wsadu. Opóźnienia w ogonie rozkładu (tail latency) stają się gorsze. Każda dodatkowa sekwencja dodaje pracę do każdego kroku dekodowania, prefill nowego żądania zabiera część kroku użytkownikom w trakcie strumieniowania, a przerwane żądanie musi być przetwarzane (prefill) dwukrotnie. Mierz opóźnienie między tokenami na poziomie p95, a nie średnią, ponieważ w oknie czatu pauzy są zauważalne w sposób, który średnie ukrywają.

Czy powinienem zwiększyć OLLAMA_NUM_PARALLEL czy przejść na vLLM?

Najpierw zwiększ liczbę równoległych zadań. Jest to darmowe, wymaga tylko jednego pliku konfiguracyjnego i rozwiązuje typowy przypadek, w którym cztery osoby czekają w kolejce za jedną długą odpowiedzią. Ograniczeniem jest pamięć: równoległe żądania mnożą kontekst, który musisz przechowywać, więc obserwuj, czy warstwy nie są przenoszone do CPU. Przejdź na vLLM, gdy masz GPU z wolną pamięcią VRAM i więcej niż około cztery żądania faktycznie w trakcie przetwarzania, ponieważ to moment, w którym stronicowana pamięć podręczna i szeregowanie na poziomie tokena dają więcej korzyści niż kosztów.

Czy więcej rdzeni CPU naprawi wolny serwer LLM?

Nie w przypadku części, którą użytkownicy zauważają najbardziej. Dekodowanie odczytuje cały model z pamięci dla każdego tokena, więc jest ograniczone przepustowością pamięci RAM, a dodatkowe rdzenie przestają pomagać, gdy przepustowość jest nasycona. Prefill skaluje się wraz z rdzeniami, więc ich większa liczba skraca czas do pierwszego tokena przy długich promptach. Na serwerze VPS z 4 do 8 GB pamięci RAM ograniczeniem jest zazwyczaj pojemność pamięci, a skutecznym rozwiązaniem jest mniejszy model lub krótszy kontekst, a nie więcej vCPU.