Co to buduje
Jedna instancja GPU udostępniająca model o otwartych wagach przez API HTTP mówiące schematem zgodnym z OpenAI, więc każda biblioteka kliencka, którą już masz, zadziała z nią po zmianie jednego base URL. Za nginx, z TLS, kluczem API i jednostką systemd, która przetrwa restart.
Napisane na G-L40S: czterdzieści osiem gigabajtów VRAM na jednej karcie, przekazane do instancji przez PCIe, a nie dzielone czasowo między dzierżawcami. Ta różnica to różnica między przewidywalnym opóźnieniem a czekaniem za cudzym zadaniem treningowym. Karta jest twoja, dopóki nie anulujesz.
Zanim zaczniesz
- G-L40S z Debianem 13. G-ADA z dwudziestoma gigabajtami działa dla mniejszych modeli; arytmetyka w kroku czwartym powie ci, które.
- Dwa terabajty NVMe w tym planie, to właściwe miejsce na wagi. Pobieranie czterdziestu gigabajtów dwa razy, bo cache był na root filesystem, to irytujący sposób na spędzenie godziny.
- Nazwa hosta wskazująca na instancję,
llm.example.componiżej.
1. Sterownik
sed -i "s/ main$/ main contrib non-free-firmware non-free/" /etc/apt/sources.list.d/debian.sources
apt update
apt install -y nvidia-driver firmware-misc-nonfree build-essential
rebootPo powrocie:
nvidia-smiChcesz, aby karta była wymieniona, wersja sterownika wydrukowana, a użycie pamięci blisko zera. Brak karty w tym momencie to prawie zawsze nieświeży initramfs; update-initramfs -u i zrestartuj jeszcze raz przed otwarciem zgłoszenia.
nvidia-smi -q -d PERFORMANCE | grep -A3 "Clocks Event Reasons"
nvidia-smi -pm 1Tryb persistencji utrzymuje sterownik załadowany między procesami, co usuwa kilka sekund inicjalizacji z każdego restartu.
2. Środowisko wykonawcze
apt install -y python3-venv python3-pip
install -d -o root -g root /srv/models /opt/vllm
python3 -m venv /opt/vllm/venv
/opt/vllm/venv/bin/pip install --upgrade pip
/opt/vllm/venv/bin/pip install vllmInstalacja pobiera duży zestaw wheel linked with CUDA i zajmuje chwilę. W międzyczasie zdecyduj, który model.
3. Wybór tego, co się mieści
Wagi to podłoga, nie budżet. Model w precyzji szesnastobitowej potrzebuje mniej więcej dwóch gigabajtów VRAM na miliard parametrów, plus key-value cache dla każdego równoczesnego żądania, plus gigabajt lub więcej na narzut runtime.
| Karta | Wagi w 16-bit | Realistyczny rozmiar modelu | Zostaje na cache |
|---|---|---|---|
| L40S, 48 GB | 2 GB na miliard | Do około 20 miliardów | 6 do 8 GB |
| L40S, 48 GB, 8-bit | 1 GB na miliard | Do około 34 miliardów | 10 GB |
| RTX 4000 Ada, 20 GB | 2 GB na miliard | Do około 7 miliardów | 5 GB |
| Dwie × L40S, 96 GB | 2 GB na miliard | Do około 40 miliardów | 12 GB |
Kolumna cache określa, ile osób może korzystać z endpointu jednocześnie. Wypełnij kartę po brzegi wagami i zbudujesz bardzo szybką zabawkę dla jednego użytkownika.
4. Serwowanie
Skonfiguruj cache na NVMe i uruchom serwer. Podstaw identyfikator repozytorium wybranego modelu o otwartych wagach; runtime pobierze go przy pierwszym starcie.
cat > /etc/systemd/system/vllm.service <<EOF
[Unit]
Description=vLLM inference server
After=network-online.target
[Service]
Environment=HF_HOME=/srv/models
Environment=VLLM_API_KEY=<a long random string>
ExecStart=/opt/vllm/venv/bin/vllm serve <org>/<model> \\
--host 127.0.0.1 --port 8000 \\
--served-model-name local \\
--max-model-len 16384 \\
--gpu-memory-utilization 0.92 \\
--max-num-seqs 32
Restart=on-failure
RestartSec=10
TimeoutStartSec=1800
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now vllm
journalctl -fu vllmWiązanie z loopback jest celowe. Sprawdzanie klucza API w runtime to pojedynczy wspólny sekret bez limitu szybkości za nim, więc nginx robi ekspozycję, a runtime nigdy nie dotyka publicznego interfejsu.
Hojny limit czasu startu istnieje, ponieważ pierwsze uruchomienie pobiera dziesiątki gigabajtów, a potem kompiluje jądra. Kolejne starty zajmują mniej niż minutę.
5. Proxy i TLS
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name llm.example.com;
ssl_certificate /etc/letsencrypt/live/llm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;
location /v1/ {
proxy_pass http://127.0.0.1:8000;
proxy_buffering off;
proxy_read_timeout 600s;
proxy_set_header Host $host;
}
}proxy_buffering off to linia, która sprawia, że streamingowe odpowiedzi strumieniują. Zostaw to włączone, a tokeny przyjdą w uporządkowanych partiach, gdy nginx uzna, że bufor jest pełny, co wygląda dokładnie jak wolny model, a nie jest.
Zweryfikuj to
Zacznij od karty:
nvidia-smi --query-gpu=memory.used,memory.total,utilization.gpu --format=csvUżyta pamięć powinna wynosić około dziewięćdziesięciu procent całości, bo o to prosi --gpu-memory-utilization. Potem endpoint:
curl -s https://llm.example.com/v1/models -H "Authorization: Bearer <the key>" | head -20Jeden model, nazwany local. Teraz prawdziwe uzupełnienie i zmierz czas:
time curl -s https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer <the key>" \
-H "Content-Type: application/json" \
-d '{"model":"local","messages":[{"role":"user","content":"List three prime numbers."}],"max_tokens":64}'Na koniec zmierz to pod obciążeniem, a nie jedno żądanie na raz – to jedyna liczba, którą warto cytować:
/opt/vllm/venv/bin/vllm bench serve \
--backend openai-chat \
--base-url https://llm.example.com \
--endpoint /v1/chat/completions \
--model local --num-prompts 200 --request-rate 8Przeczytaj trzy liczby z wyniku: zagregowane tokeny wyjściowe na sekundę, medianę czasu do pierwszego tokena i 99. percentyl end-to-end. Na pojedynczej L40S z modelem w zakresie dziesięciu do dwudziestu miliardów, zagregowana przepustowość wyjściowa w wysokich setkach tokenów na sekundę i czas do pierwszego tokena znacznie poniżej sekundy to oczekiwany kształt. Czas do pierwszego tokena rosnący wraz z równoczesnością oznacza, że twój key-value cache jest za mały, więc obniż --max-model-len lub --max-num-seqs i uruchom ponownie.
Potem
Obserwuj temperaturę i throttling zegara przez pierwszy tydzień za pomocą nvidia-smi dmon, ponieważ karta, która termicznie throttluje pod ciągłym obciążeniem, wytwarza dokładnie ten rodzaj sporadycznej spowolnienia, który jest zrzucany na sieć. Pod względem rachunków pamiętaj, że instancja GPU kosztuje tyle samo, czy karta jest zajęta, czy bezczynna, więc grupuj zadania, a nie zostawiaj jej w cieple. Cennik jest na stronie GPU.