Ollama vs vLLM: quale server scegliere per LLM
Scopri le differenze tra Ollama e vLLM. Scegli Ollama per uso locale singolo su CPU o GPU, oppure vLLM per massimizzare il throughput su server multi-utente con accelerazione.
Ollama contro vLLM, in sintesi
Ollama è un gestore di modelli con server integrato: scarica i pesi quantizzati, li carica in memoria e risponde sulla porta 127.0.0.1:11434, utilizzando la CPU se il sistema non dispone di altro. vLLM è un motore ottimizzato per il throughput: mantiene una GPU satura gestendo molteplici richieste simultanee ed è lo strumento inadatto su macchine prive di accelerazione hardware. Questa è l'unica discriminante. Un singolo utente che interagisce con un assistente locale è il caso d'uso ideale per Ollama. Un'applicazione che serve un intero team richiede vLLM.
Entrambi espongono un'API HTTP compatibile con OpenAI, pertanto il codice client può passare dall'uno all'altro semplicemente modificando la base URL. La differenza non risiede nell'API, ma in ciò che accade quando arriva una seconda richiesta mentre la prima sta ancora generando token.
Che cos’è realmente Ollama
Ollama è un livello di praticità. Con un solo comando di installazione fornisce un registro dei modelli (ollama pull llama3.1:8b), un archivio locale dei pesi, un prompt di chat, un servizio systemd e un’API HTTP. La maggior parte dei modelli che serve è costituita da file GGUF, generalmente quantizzati a 4 bit. Per questo un modello 7B o 8B occupa circa 5 GB su disco invece di 16 GB. La quantizzazione riduce la memoria necessaria per l’inferenza su CPU. Sui Mac con Apple Silicon può anche eseguire modelli basati su safetensors tramite un motore MLX. A partire dalla versione v0.40.0 (settembre 2026), le architetture supportate vengono eseguite automaticamente su MLX.
Il runner GGUF si basa su llama.cpp, la libreria di inferenza C++ che ha reso pratica la quantizzazione GGUF su hardware comune. A ottobre 2026 Ollama supporta due motori, llama.cpp e MLX. Le build Linux supportano inoltre l’inferenza MLX con CUDA. La guida allo sviluppo abilita questo backend con cmake -B build . -DOLLAMA_MLX_BACKENDS=cuda_v13. I prerequisiti sono CUDA 13+ e cuDNN 9+. Quindi, quando si confronta Ollama con llama.cpp, si confronta soprattutto un livello orientato alla semplicità d’uso con il componente che esso integra.
Il progetto è pensato per un singolo utente. A ottobre 2026 il valore predefinito di OLLAMA_NUM_PARALLEL è 1. Questo significa che un modello elabora una sola richiesta alla volta e tutte le altre restano in una coda che contiene 512 elementi per impostazione predefinita (OLLAMA_MAX_QUEUE). È possibile aumentare il numero di elaborazioni parallele. La sezione seguente spiega quali risorse aggiuntive richiede. Se non hai mai eseguito Ollama, inizia da ospitare Ollama su un VPS e mantenere chiusa la porta 11434, perché l’API locale non richiede autenticazione.
Che cos’è realmente vLLM
vLLM è un server di inferenza e nient’altro. Non gestisce una libreria di modelli, fornisce un client vllm chat per un server in esecuzione e non scarica un modello al momento della richiesta. All’avvio si specifica un repository Hugging Face, vLLM carica quel modello e lo rende disponibile finché non si arresta il processo.
Il vantaggio di questa specializzazione è il throughput. Il lavoro è svolto da due meccanismi. PagedAttention memorizza la KV cache (cache key-value, ovvero lo stato dell’attenzione per token che un modello conserva per ogni richiesta attiva) in blocchi di dimensione fissa, come un sistema operativo suddivide la memoria in pagine. Una richiesta non richiede più una singola allocazione contigua di grandi dimensioni, calcolata sul caso peggiore. La memoria che prima rimaneva riservata e inutilizzata diventa così disponibile per un numero maggiore di richieste simultanee. Il continuous batching consente a una nuova richiesta di entrare nel batch in esecuzione al passaggio successivo della decodifica, invece di attendere il completamento del batch corrente. Quando una sequenza termina, viene rimossa immediatamente dal batch e il relativo slot viene riassegnato.
Il risultato pratico è il seguente: su una singola GPU, passare da un utente simultaneo a trenta aumenta nettamente il numero totale di token al secondo, mentre la velocità per utente diminuisce molto meno di quanto ci si aspetterebbe. Con la configurazione predefinita di Ollama, passare da un utente a trenta fa semplicemente aspettare ventinove persone.
Il continuous batching fa la differenza
Immaginate cinque richieste che raggiungono ciascun server nello stesso momento, su hardware identico.
Con le impostazioni predefinite, Ollama completa la prima richiesta, poi la seconda e così via. Il quinto chiamante attende quattro generazioni complete. Il throughput complessivo è all'incirca quello di una singola generazione, perché il processore elabora una sola sequenza alla volta.
vLLM esegue il decoding di tutte e cinque le richieste nello stesso forward pass. Generare un token per cinque sequenze costa appena più che generare un token per una sequenza, perché la parte costosa consiste nel leggere i pesi del modello dalla memoria e questa lettura viene condivisa dall'intero batch. È lo stesso limite della larghezza di banda della memoria che rende lenta l'inferenza sulla CPU: il costo principale è trasferire i pesi, non eseguire i calcoli.
È possibile impostare OLLAMA_NUM_PARALLEL=4 e ottenere parte di questo comportamento. Il costo è la memoria. Ogni slot parallelo richiede una propria KV cache e Ollama moltiplica l'allocazione del contesto invece di suddividerla: la relativa FAQ specifica che la RAM necessaria cresce di OLLAMA_NUM_PARALLEL volte OLLAMA_CONTEXT_LENGTH. Quindi, con quattro richieste parallele verso un modello configurato per 8192 token, ogni richiesta mantiene 8192 token, ma il server deve contenere una cache per 32768 token complessivi. Anche quel valore di 8192 è una scelta, non un valore predefinito, quindi aumentare num_ctx e dimensionare la RAM necessaria è il passaggio che determina se quattro slot possono essere supportati. La cache paginata di vLLM evita di riservare in anticipo l'intera finestra per ogni slot, perché i blocchi vengono allocati a una richiesta man mano che questa cresce. In ogni caso, il limite al numero di utenti che un singolo server può servire contemporaneamente dipende dalla dimensione della KV cache, dal costo del prefill e dalla profondità della coda: è per questo che un server adeguato per una sola persona rallenta fino a diventare inutilizzabile con cinque.
Installazione e distribuzione con Ollama
curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3.1:8b
ollama run --verbose llama3.1:8b "Write two sentences about Linux."Lo script di installazione crea un utente di sistema ollama, installa il binario e registra ollama.service associato a 127.0.0.1:11434. La riga eval rate stampata da --verbose indica i tuoi reali token al secondo su quella macchina. Considerala più affidabile di qualsiasi dato pubblicato. Una singola lettura da un prompt è un punto di partenza piuttosto che un valore di capacità; pertanto, misurare i token al secondo attraverso una scansione della concorrenza è ciò che ti dice se la macchina regge il carico che ti aspetti realmente e se il noleggio di una GPU sia più conveniente rispetto al pagamento per singolo token.
Per aumentare la concorrenza, utilizza un drop-in di systemd in modo che un aggiornamento non sovrascriva la modifica:
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_KEEP_ALIVE=30m"sudo systemctl restart ollama
ollama psollama ps mostra cosa è caricato e la sua colonna PROCESSOR riporta il dato reale. 100% CPU significa che non viene utilizzata alcuna GPU, il che è la spiegazione onesta per la maggior parte delle segnalazioni in cui Ollama risulta lento. La riga OLLAMA_KEEP_ALIVE=30m in quel drop-in è altrettanto importante su una macchina poco utilizzata, poiché per impostazione predefinita il modello viene scaricato dopo cinque minuti senza richieste. Mantenere il modello residente tra una richiesta e l'altra evita che il primo prompt dopo una pausa fino a mezz'ora debba subire nuovamente l'intero tempo di caricamento. Se i tuoi periodi di inattività sono più lunghi, imposta un valore superiore.
Installare ed esporre il servizio con vLLM
Le build GPU di vLLM richiedono Linux. macOS su Apple Silicon supporta solo la CPU tramite un wheel precompilato nella release 0.32.0; l'accelerazione GPU su questi Mac è fornita da vLLM-Metal, un plugin separato gestito dalla community e basato su MLX. Per Python, la release attuale (0.32.0, ottobre 2026) supporta le versioni dalla 3.11 alla 3.14, e la guida all'installazione indica lo stesso intervallo. Il supporto per Python 3.10 è stato rimosso in 0.32.0, quindi 3.12, usato di seguito, è la scelta più sicura. Installalo in un ambiente virtuale dedicato, perché installa una build specifica di PyTorch:
uv venv --python 3.12 --seed
source .venv/bin/activate
uv pip install vllm --torch-backend=auto
vllm download-kernelsL'ultima riga è presente nella guida all'installazione di vLLM per NVIDIA a ottobre 2026. Installa i kernel precompilati di FlashInfer. Senza questi kernel, vLLM li scarica e li compila all'avvio; secondo la guida, questa operazione può richiedere diversi minuti sulle GPU Hopper e successive. Esegui di nuovo il comando dopo ogni aggiornamento di vLLM, perché FlashInfer rifiuta di essere importato quando i kernel non corrispondono.
Ora avvia il servizio del modello. Il nome è l'identificativo di un repository Hugging Face, non un tag abbreviato:
vllm serve Qwen/Qwen2.5-1.5B-InstructIl primo avvio è lento, perché il sistema scarica i pesi e poi analizza la GPU per determinare quanti blocchi della cache KV possono essere allocati. Il servizio resta in ascolto sulla porta 8000. Verificalo prima di scrivere il codice del client:
curl http://localhost:8000/v1/models
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "Qwen/Qwen2.5-1.5B-Instruct", "messages": [{"role": "user", "content": "Who won the world series in 2020?"}]}'Se Docker è già installato sul server, l'immagine ufficiale evita di gestire manualmente le dipendenze CUDA:
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HF_TOKEN=$HF_TOKEN" \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model Qwen/Qwen3-0.6B--ipc=host consente al container di accedere alla memoria condivisa dell'host; aumentare --shm-size è un'altra possibilità. PyTorch trasferisce i tensori tra processi tramite la memoria condivisa, in particolare per l'inferenza tensor-parallel.
In produzione, i flag più importanti sono --max-model-len, cioè la finestra di contesto che si è disposti a pagare, --gpu-memory-utilization, cioè la frazione della GPU che vLLM può utilizzare (0.92 per impostazione predefinita a ottobre 2026), --tensor-parallel-size, per distribuire un singolo modello su più GPU, e --api-key.
L’autenticazione è gestita da un flag in vLLM ed è assente nell’API locale di Ollama
vLLM applica un bearer token se ne specifichi uno:
vllm serve Qwen/Qwen2.5-1.5B-Instruct --api-key token-abc123Lo stesso valore può provenire dalla variabile d’ambiente VLLM_API_KEY. Una richiesta all’endpoint /v1 priva del token restituisce HTTP 401. Tuttavia, la chiave non protegge l’intero server. La guida alla sicurezza di vLLM e il codice di autenticazione nel sorgente della versione 0.32.0 applicano il controllo solo agli endpoint con i prefissi di percorso /v1, /v2, /inference e /cohere. Il testo della guida --api-key nella pagina vllm serve elenca solo i primi tre, ma il codice controlla tutti e quattro. Sia la guida sia il testo della guida indicano che gli altri endpoint, in particolare /invocations, che espone la stessa inferenza di /v1, non sono autenticati. Questo è un motivo sufficiente per non pubblicare la porta 8000 su un’interfaccia pubblica. La guida alla sicurezza di vLLM lascia inoltre il rate limiting a un reverse proxy anteposto al server; inoltre, un token inviato tramite HTTP non cifrato è leggibile durante il transito. Il flag indica comunque che il server riconosce un chiamante.
L’API locale di Ollama non richiede autenticazione. I modelli cloud, la pubblicazione dei modelli e il download di modelli privati richiedono l’accesso a un account; l’accesso diretto all’API di ollama.com richiede una API key. Qualsiasi processo in grado di raggiungere la porta 11434 può eseguire, scaricare o eliminare modelli. Mantienila in ascolto solo sul loopback e raggiungila tramite una VPN WireGuard gestita autonomamente, oppure tramite un reverse proxy che richieda autenticazione e gestisca la terminazione TLS (Transport Layer Security).
Hardware: requisiti per ciascuno
Ollama usa la CPU. Un modello quantizzato a 4 bit richiede circa mezzo gigabyte di RAM per ogni miliardo di parametri, oltre a circa un gigabyte di overhead del runtime e a una quantità aggiuntiva per il contesto. Un modello 3B richiede quindi circa 4 GB di memoria libera, mentre un modello 8B ne richiede circa 8 GB. La velocità su una vCPU condivisa va da pochi token al secondo a valori a due cifre contenuti. Questo dipende dalla larghezza di banda della memoria, non da una configurazione errata, e nessun flag può risolvere il problema. Per osservare questi calcoli su una release specifica invece di affidarsi a una stima indicativa, eseguire Nemotron 3.5 Lightning su un VPS consente di individuare il tag esatto da scaricare, la RAM occupata dopo il caricamento e se le prestazioni con la sola CPU sono sufficienti per l'uso previsto.
vLLM presuppone la presenza di una GPU. Per impostazione predefinita, serve pesi non quantizzati con precisione a 16 bit. Il consumo è di circa 2 GB per ogni miliardo di parametri: un modello 8B richiede circa 16 GB di memoria video soltanto per i pesi, prima di considerare la cache KV che consente la concorrenza per cui avete installato vLLM. Su una scheda da 24 GB resta spazio sufficiente per una cache utilizzabile. Su una scheda da 16 GB, invece, non è così. Dovete quindi scegliere un modello più piccolo, passare --quantization (con un checkpoint quantizzato oppure per quantizzare i pesi a piena precisione al momento del caricamento) oppure spostare parte dei pesi nella RAM di sistema con --cpu-offload-gb. In quest'ultimo caso la precisione resta invariata, ma le prestazioni peggiorano perché i pesi vengono trasferiti alla GPU a ogni passaggio forward. Esiste anche un backend CPU, con wheel separate, ma in questo modo viene meno il motivo stesso per usare vLLM.
Nella maggior parte dei casi, quindi, la scelta dell'hardware determina quella del software. Se non avete una GPU, usate Ollama. Se una GPU a noleggio resta al 5% di utilizzo perché le richieste vengono serializzate, usate vLLM.
Quale scegliere per il proprio carico di lavoro
- Un singolo utente, un VPS con una CPU, per stesura e riassunti: Ollama. La velocità è accettabile e non esiste nulla di più semplice.
- Un assistente alla programmazione, o un server MCP che collega i tuoi strumenti a un modello locale, utilizzato solo da te: Ollama. Una concorrenza pari a uno è il carico di lavoro reale.
- Confronto tra cinque modelli questa settimana: Ollama. Scaricare ed eliminare modelli tramite tag è esattamente ciò che sa fare meglio, mentre vLLM richiede il riavvio del processo per ogni modello.
- Un'applicazione interna, un prodotto di chat o una pipeline di recupero dati con utenti reali: vLLM. È qui che il batching giustifica il costo di una GPU.
- Un job batch per elaborare centomila documenti durante la notte: vLLM, con un
--max-num-seqselevato. Il throughput è l'unica metrica che conta e la latenza per singolo documento è irrilevante. - Una piattaforma di agenti in cui diversi agenti IA self-hosted interrogano il modello contemporaneamente: vLLM, poiché il traffico degli agenti è per natura a picchi e parallelo.
Modalità di errore e stringhe visualizzate
vLLM non si avvia e segnala un errore nella cache KV. Il messaggio riporta entrambi i valori:
ValueError: To serve at least one request with the model's max seq len (32768), (4.00 GiB KV cache is needed, which is larger than the available KV cache memory (1.00 GiB). Based on the available memory, the estimated maximum model length is 8192. Try increasing `gpu_memory_utilization` (which also controls CPU memory on the CPU backend) or decreasing `max_model_len` when initializing the engine. See https://docs.vllm.ai/en/latest/configuration/conserving_memory/ for more details.Il modello dichiara una finestra di contesto più grande della memoria disponibile dopo il caricamento dei pesi. Riducila con --max-model-len 8192 oppure aumenta --gpu-memory-utilization, se nessun altro processo utilizza la scheda.
Ollama visualizza Killed durante la generazione. Il killer OOM di Linux ha terminato il processo perché il modello richiedeva più RAM di quella disponibile sul server. Verifica con sudo dmesg | grep -i oom. La soluzione consiste nell'usare un modello più piccolo o con una quantizzazione più spinta, non nel modificare un'impostazione.
Ollama risponde correttamente da solo, ma si blocca sotto carico. Non compare alcun errore. Le richieste richiedono semplicemente più tempo all'aumentare dei client, perché OLLAMA_NUM_PARALLEL=1 le serializza. Le risposte lunghe peggiorano la coda: un client che occupa l'unico slot finché il modello non decide di interrompersi blocca tutti i client successivi. limitare la risposta con num_predict imposta quindi un limite alla durata di una singola richiesta e al tempo per cui può occupare il server. Aumenta l'impostazione della parallelizzazione e considera la RAM aggiuntiva richiesta dal contesto di ogni slot, oppure sposta il carico di lavoro su vLLM.
vLLM restituisce 401 per ogni chiamata /v1. Lo hai avviato con --api-key, ma il client non invia alcun header Authorization. La maggior parte delle librerie client OpenAI invia come chiave il valore specificato dall'utente. Imposta quindi la chiave nella libreria invece di rimuovere il flag.
vLLM segnala che il modello non è stato trovato. Ollama scarica i modelli su richiesta, mentre vLLM non lo fa. Il campo model nel corpo della richiesta deve corrispondere all'ID del repository con cui hai avviato il server, oppure al valore di --served-model-name, se lo hai impostato. Verifica la stringa esatta con curl http://localhost:8000/v1/models.
Eseguirli entrambi è una soluzione ragionevole
Non sono esclusivi. Una configurazione comune prevede vLLM su un'istanza GPU che serve l'applicazione, con Ollama sulla normale VPS a fianco per script locali, cron job e per testare nuove release di modelli. Entrambi gli endpoint sono compatibili con OpenAI, quindi una singola libreria client e un cambio di base-URL sono sufficienti per gestirli. Il controllo dei costi è più importante della scelta del motore, poiché una GPU inattiva ha lo stesso costo di una sotto carico, e mantenere prevedibili i costi di agenti e inferenza è una disciplina distinta dalla scelta del server.
FAQ
vLLM è più veloce di Ollama?
Per una singola richiesta sulla stessa GPU, la differenza è contenuta, perché entrambi eseguono gli stessi calcoli. Con molte richieste simultanee, vLLM è nettamente più veloce, perché il continuous batching decodifica ogni sequenza attiva in un'unica passata forward, mentre l'esecuzione predefinita di Ollama le gestisce una alla volta. Su una macchina con sola CPU, entrambi supportano l'inferenza, mentre vLLM usa pacchetti CPU separati.
vLLM può funzionare senza una GPU?
Sì, tramite il backend CPU. I pacchetti standard sono destinati alle GPU NVIDIA o AMD e, su una CPU, viene meno il motivo principale per cui esiste vLLM: mantenere un acceleratore a pieno carico con richieste raggruppate. Esiste un backend CPU, con pacchetti separati per x86 e Arm. Per l'inferenza effettiva su CPU, usa direttamente Ollama o llama.cpp.
Qual è la differenza tra Ollama e llama.cpp?
llama.cpp è la libreria di inferenza, mentre GGUF è il formato dei pesi quantizzati. Ollama usa llama.cpp per l'inferenza GGUF e aggiunge un registro dei modelli, download con tag, gestione dei modelli e un'unità systemd. Ollama include anche un motore MLX che esegue modelli basati su safetensors su Apple Silicon e supporta build CUDA su Linux; pertanto i due strumenti non sono sempre identici a livello sottostante.
Quanta memoria GPU richiede vLLM per un modello 8B?
Con precisione a 16 bit, i soli pesi occupano circa 16 GB, cioè approssimativamente 2 GB per ogni miliardo di parametri, e occorre aggiungere spazio per la cache KV. Una scheda da 24 GB offre un margine adeguato. Con una scheda da 16 GB serve un modello quantizzato, un modello più piccolo oppure --cpu-offload-gb per spostare parte dei pesi nella RAM di sistema, con una riduzione della velocità. vLLM usa la frazione della memoria della scheda indicata da --gpu-memory-utilization, che a ottobre 2026 ha valore predefinito 0.92.
Devo modificare il codice dell'applicazione per passare da uno all'altro?
Di solito è sufficiente modificare l'URL di base, la chiave API e il nome del modello. Ollama espone la propria interfaccia compatibile con OpenAI su http://127.0.0.1:11434/v1 e ignora la chiave, mentre vLLM espone http://localhost:8000/v1 e verifica la chiave sulle route /v1 se ne imposti una. I nomi dei modelli hanno formati diversi: llama3.1:8b per Ollama e un ID completo del repository, come Qwen/Qwen2.5-1.5B-Instruct, per vLLM.