I motori che eseguono i pesi: da llama.cpp allo streaming dal disco
Il pezzo sulle evoluzioni ha chiuso con un bilancio in tre livelli: i pesi, con la loro architettura; l’addestramento che li ha prodotti; e in mezzo il motore di inferenza - il software che prende i pesi e li trasforma in risposte. La serie ha aperto l’architettura e l’addestramento; questo pezzo apre il motore. Chi usa un modello di linguaggio, oggi, ha a che fare con i motori anche senza saperlo: quello che gira su un portatile, quello che serve migliaia di richieste al minuto, quello che porta i modelli nei browser. Sono mondi diversi con lo stesso mestiere, e una novità che li sta attraversando tutti: i pesi che arrivano dal disco, non dalla memoria.
Che cosa fa un motore
Il motore carica i pesi, esegue il percorso del modello - embedding, blocchi, testa - gestisce la cache di chiavi e valori e serve le richieste. I motori si dividono in due mondi: il personale, che serve una macchina, e il servizio, che serve tanti utenti.
Il mestiere del motore è quello che la serie ha già descritto nel pezzo sul Transformer - caricare i pesi, far passare la sequenza dai blocchi, gestire la cache di chiavi e valori durante la generazione, campionare il prossimo token - eseguito però alla velocità che l’uso richiede. E un motore vero fa molto di più, perché deve rispondere a tre domande pratiche che quel pezzo non si era posto. Come stanno i pesi in memoria - e quanto occupano? Come si accelera il calcolo - sulle schede grafiche, sul processore, su chip specializzati? E come si serve il risultato - a una persona che aspetta, o a cento richieste in fila?
Da queste tre domande nasce la divisione del mondo in due famiglie. I motori personali girano su una macchina, per una persona: vogliono far stare il modello nella memoria che c’è, e renderlo veloce a sufficienza. I motori di servizio girano su un server, per molti utenti: vogliono massimizzare il numero di richieste che riescono a servire con la stessa memoria. L’architettura è la stessa; le ottimizzazioni sono due.
llama.cpp: la via maestra
llama.cpp è il motore personale per eccellenza: gira sul processore e sulle schede, definisce il formato GGUF che porta i pesi ovunque, e la quantizzazione che li comprime. Quasi tutti gli altri motori gli devono qualcosa.
llama.cpp è il motore che ha aperto la strada, e il suo ruolo si vede da quanto ha lasciato agli altri. Ha definito il formato GGUF - il contenitore che porta i pesi di un modello su qualunque macchina, con dentro i metadati e la struttura del modello - e la quantizzazione: la tecnica che comprime i pesi da sedici bit a otto o quattro, facendo stare modelli grandi in memoria a scapito di un po’ di precisione. Gira sul processore con la memoria normale, scarica gli strati sulla scheda grafica quando c’è, e grazie alla memoria mappata sul file (mmap) il sistema operativo carica i pesi dal disco al bisogno, pagina dopo pagina, invece di doverli leggere tutti in anticipo.
llama.cpp non è solo un motore: è anche il riferimento su cui gli altri si appoggiano. Il motore di antirez, che incontreremo fra poco, dichiara apertamente che senza llama.cpp e il suo ecosistema GGUF non esisterebbe.
MLX: il motore di Apple
MLX è il motore nativo dei chip Apple: sfrutta la memoria unificata - la stessa memoria per processore e scheda grafica - e carica i pesi pigramente, dal disco alla memoria al bisogno.
MLX è il motore che Apple ha costruito per i suoi chip, e la sua differenza sta nell’hardware: i Mac hanno una memoria unificata, in cui il processore e la scheda grafica leggono e scrivono la stessa memoria fisica. Un modello che in un computer normale dovrebbe stare nella memoria della scheda grafica, sul Mac può usare tutta la memoria della macchina - è il motivo per cui i Mac con molta memoria sono diventati macchine adatte a far girare i modelli in locale.
MLX carica i pesi pigramente: i pesi sono mappati sul file e arrivano in memoria solo quando servono davvero, una parte alla volta. È lo stesso principio di mmap, portato dentro un motore moderno - e la comunità ci ha costruito sopra lo streaming dei pesi vero e proprio: progetti come mlx-flash o LightLX fanno girare su Apple Silicon modelli più grandi della memoria della macchina, leggendo i pesi dal disco durante la generazione.
I motori di servizio: vLLM e gli altri
vLLM serve molte richieste con la stessa memoria: pagina la cache di chiavi e valori come un sistema operativo pagina la memoria, e mette in coda le richieste per riempire ogni passaggio. Accanto a lui, gli altri motori di servizio.
I motori di servizio risolvono un problema diverso: come servire centinaia di richieste con una memoria limitata. vLLM è il riferimento, e le sue due idee sono diventate il vocabolario del settore. La prima è la cache di chiavi e valori paginata: invece di riservare a ogni richiesta uno spazio fisso per la sua cache, la memoria si pagina come fa un sistema operativo con la RAM - i blocchi si assegnano al bisogno, e lo spazio non si spreca. È la cache del pezzo sulle evoluzioni, gestita con l’ingegneria della memoria virtuale. La seconda è il batching continuo: le richieste entrano nel calcolo appena arrivano ed escono appena hanno finito - ogni passaggio del modello lavora per quante richieste sono pronte in quel momento, e la scheda non sta mai ferma.
Accanto a vLLM ci sono gli altri nomi del mestiere, e valgono una riga ciascuno: la lista cambia in fretta, il mestiere no.
| Motore | Che cos’è | Che cosa lo distingue |
|---|---|---|
| SGLang | motore di servizio | la cache dei prefissi: le richieste che cominciano allo stesso modo riusano il calcolo già fatto |
| TensorRT-LLM | motore di servizio di NVIDIA | compila il modello per la scheda esatta, ottimizzando i kernel e la memoria |
| TGI | motore di servizio di Hugging Face | l’opzione integrata con l’ecosistema della casa |
| Ollama | non un motore: un involucro | mette llama.cpp dietro un comando semplice e un’API, per chi non vuole configurarlo |
| ExLlama | motore personale su GPU | ottimizzato per i modelli quantizzati sulle schede NVIDIA |
| CTranslate2 | motore personale e di servizio | esegue modelli quantizzati anche senza scheda grafica, sul processore |
DwarfStar: il motore stretto
DwarfStar è il motore di antirez - il creatore di Redis - deliberatamente stretto: ottimizzato per DeepSeek V4 Flash e GLM, sfrutta la tolleranza alla quantizzazione degli esperti del MoE e lo streaming dal disco per girare su macchine personali.
L’approccio opposto al generalista è l’ultimo arrivato tra i nomi importanti: DwarfStar, il motore che Salvatore Sanfilippo - antirez, il creatore di Redis - ha costruito per un pugno di modelli. È deliberatamente stretto: niente supporto a qualunque GGUF, ma l’ottimizzazione profonda di pochi modelli - DeepSeek V4 Flash e GLM, con DeepSeek V4 PRO sulle macchine più grandi. Gira su Metal (i Mac), su CUDA (le schede NVIDIA, anche in multi-GPU) e su ROCm (i sistemi Strix Halo).
Le sue motivazioni sono una lezione di architettura. I modelli a miscela di esperti come DeepSeek tollerano una quantizzazione aggressiva degli esperti: i parametri attivi possono essere compressi molto senza perdere troppo, perché il router ne usa pochi per token. Le cache di chiavi e valori compresse e i dischi veloci rendono i contesti lunghi pratici. E quando la memoria non basta, lo streaming dal disco fa girare il modello comunque, a una velocità decente. Il principio: per pochi modelli, un motore specializzato batte il generalista - il rovescio esatto della filosofia di llama.cpp.
Più macchine insieme: pipeline e tensori
I motori possono spartire il modello fra più computer in due modi: per gruppi di livelli, e allora le attivazioni attraversano la rete da una macchina all’altra a ogni token; o per fette di matrice, e allora ogni strato richiede uno scambio di somme parziali. Il primo somma la capacità, il secondo la velocità.
Un modello che non sta in una sola macchina si può anche spartire fra più computer, e i motori lo permettono. Le tecniche sono due, e la differenza sta in che cosa attraversa la rete.
Il parallelismo per livelli - la pipeline - spartisce il modello per gruppi di strati: ogni computer tiene un gruppo di strati con i suoi pesi, e i pesi non si muovono. Per ogni token, la sequenza passa dai primi strati sulla prima macchina, poi le attivazioni - i vettori trasformati, non i pesi - attraversano la rete verso la seconda, che ha gli strati successivi, e così via. Detto con precisione: i dati che viaggiano sono le attivazioni, e la rete li porta da uno stadio all’altro a ogni token.
Il parallelismo tensoriale - il tensor parallelism - spartisce il modello per fette di matrice: ogni computer tiene una parte di ogni strato, e a ogni strato, a ogni token, le macchine scambiano le somme parziali (un all-reduce) prima di proseguire. Niente strati interi da trasferire, ma uno scambio a ogni livello - il che richiede un’interconnessione velocissima.
Il costo della pipeline va contato per fasi, perché il lavoro ne ha due. Nella lettura del prompt - il testo d’ingresso, che il modello riceve tutto insieme - le attivazioni dell’intera sequenza attraversano ogni confine una volta: T token per D dimensioni per 2 byte - con 128 token e 768 dimensioni sono circa 196 kilobyte per confine, un decimo di millisecondo su una rete a 10 gigabit, un millisecondo e mezzo su una a 1 gigabit. In generazione, grazie alla cache di chiavi e valori che ogni stadio tiene per i propri strati, a ogni confine passa l’attivazione del solo token nuovo: un chilobyte e mezzo, che qualunque rete trasmette in pochi microsecondi. Il collo di bottiglia della generazione non è la banda ma il viaggio: ogni token attraversa tutti gli stadi in fila, e ogni confine aggiunge la sua latenza.
I motori lo offrono in forme diverse. llama.cpp espone il RPC: si decide quanti strati finiscono su quale macchina, e i livelli remoti vengono chiamati via rete. MLX ha il suo distributed, pensato per più Mac collegati in rete - Thunderbolt raccomandato per la banda. DwarfStar fa entrambe le cose: il tensor parallelism via RDMA fra due Mac ad alta memoria, per la velocità, e la pipeline per sommare la RAM di più sistemi e far girare modelli più grandi. vLLM, dal lato servizio, combina tensor, pipeline e data parallelism sui cluster di schede.
I limiti vanno detti con la stessa precisione. La pipeline somma la capacità, non la velocità: un modello che non starebbe in una macchina sì, ma la generazione va al passo dello stadio più lento, e all’inizio e alla fine di ogni sequenza le macchine restano in attesa - il «buco» della pipeline. Il parallelismo tensoriale senza interconnessione veloce è controproducente: l’all-reduce a ogni strato a ogni token vuole NVLink, InfiniBand, RDMA o Thunderbolt, non una rete normale. E il contesto lungo pesa due volte: allunga la lettura del prompt e ingrossa la cache di chiavi e valori che ogni stadio deve tenere per i propri strati.
Lo streaming dei pesi dal disco: come funziona
Quando il modello non sta in memoria, i pesi arrivano dal disco al bisogno. Tre meccanismi: la memoria mappata sul file, il caricamento pigro degli esperti del MoE, e lo streaming con cache dei neuroni attivi. Il MoE è il caso migliore: solo i parametri attivi servono a ogni token.
La novità che attraversa tutti i motori è la stessa: quando il modello è più grande della memoria, i pesi si leggono dal disco al bisogno. I meccanismi sono tre, e si sommano.
Il primo è la memoria mappata sul file (mmap): i pesi non si copiano in memoria, si mappano - il sistema operativo li porta dal disco alla RAM pagina dopo pagina, quando servono, e li scarica quando servono altri. È la base di llama.cpp e di MLX, ed è il motivo per cui un modello può avviarsi quasi subito anche se è grande: si comincia a generare mentre il resto dei pesi arriva.
Il secondo è il caricamento pigro degli esperti, e qui l’architettura
a miscela di esperti del pezzo sulle evoluzioni diventa un vantaggio
decisivo. Un modello MoE ha parametri totali enormi ma ne attiva pochi
per token - DeepSeek-V3 ne attiva 37 su 671. Il motore può tenere in
memoria solo gli esperti che servono in questo momento e leggere gli
altri dal disco quando il router li chiama: llama.cpp lo fa con la sua
opzione --lazy-experts per i modelli più grandi della RAM, e i motori
specializzati nello streaming lo portano al limite. Un modello denso
non può farlo: deve leggere quasi tutti i pesi a ogni token, perché li
usa tutti.
Il terzo è lo streaming con cache, ed è il più sofisticato: si appoggia alla sparsità delle attivazioni - la regolarità per cui una piccola frazione di neuroni è «calda», attivata da quasi tutti i token, mentre la maggior parte è fredda e si attiva di rado. I motori come PowerInfer tengono i neuroni caldi in memoria e leggono dal disco quelli freddi, con una cache che indovina quali serviranno. Su questo principio PowerInfer-2 fa girare modelli da 47 miliardi su un telefono, leggendo i pesi da un NVMe.
I limiti dello streaming
Il disco è più lento della memoria di un ordine di grandezza: un NVMe legge pochi gigabyte al secondo, la RAM decine o centinaia. Lo streaming funziona se il motore indovina quali pesi servono - e se i pesi sono abbastanza piccoli da arrivare in tempo.
Lo streaming non è magia, e i suoi limiti vanno detti per intero. Il primo è la banda del disco: un NVMe legge qualche gigabyte al secondo, la memoria decine o centinaia. I pesi attivi di DeepSeek sono 37 miliardi di parametri - a quattro bit, circa 18 gigabyte da leggere a ogni token: dal disco sarebbero secondi per token, inaccettabili. Lo streaming funziona perché il motore non legge tutto a ogni token: la cache tiene in memoria gli esperti caldi, che il router richiama in continuazione, e dal disco arrivano solo quelli freddi, di rado. È l’indovinello della cache, e la sua qualità decide la velocità.
Il secondo limite è la latenza del primo accesso: caricare un esperto dal disco costa millisecondi, e un token che lo richiede aspetta. I motori mascherano il ritardo anticipando i caricamenti, ma il margine è stretto. Il terzo è la quantizzazione, che è insieme l’alleato e il prezzo: comprimere i pesi a quattro bit li fa arrivare in tempo dal disco, ma la qualità si paga - e non tutti i modelli la sopportano allo stesso modo: è la differenza che DwarfStar sfrutta con la sua scelta di modelli.
Messi in fila, i tre limiti dicono questo: lo streaming porta modelli che non starebbero in memoria, ma il prezzo è la velocità - i motori specializzati nello streaming riportano decine di token al secondo, non centinaia. È la differenza fra poter far girare il modello e poterlo servire a pieno ritmo, un compromesso che chi legge la scheda di un modello dovrebbe saper pesare.
Il bilancio
L’architettura decide quanto lo streaming può aiutare (il MoE attiva pochi pesi), la quantizzazione decide quanto pesano (e quanto costa in qualità), il motore decide come gestirli. Tre leve, la stessa domanda: che cosa si è disposti a pagare.
Il viaggio nel motore chiude il bilancio del pezzo sulle evoluzioni, e le tre leve sono ora tutte sul tavolo. L’architettura decide il margine: un modello a miscela di esperti può lavorare coi pesi che arrivano dal disco, perché ne serve una frazione per token; un denso no. La quantizzazione decide il peso: a quattro bit gli stessi parametri occupano un quarto e arrivano quattro volte più in fretta, e la qualità dichiara il prezzo. Il motore decide l’ingegneria: come pagina la cache, come indovina gli esperti, come riempie le richieste.
E la lezione è la stessa di tutta la serie, portata al livello pratico: non esiste la risposta giusta, esiste il compromesso giusto per la macchina che si ha. Un modello che pensa, sul portatile, con i pesi che arrivano dal disco - è la stessa storia che la serie ha raccontato dal neurone di carta ai modelli di ragionamento, vista dal lato di chi deve farlo girare.
Quale motore per te
Non esiste il motore migliore in assoluto: esiste il motore migliore per il vostro caso. Scegliete l’hardware, date un peso alle funzionalità che contano, e la tabella fa il conto - i punteggi sono il giudizio della serie, i pesi sono vostri.
La scelta del motore si riduce a una domanda: che cosa conta per voi? La tabella qui sotto dà a ogni motore un punteggio da 1 a 5 su quattro funzionalità - facilità d’uso, velocità di generazione, modelli grandi in poca memoria, servire molte richieste. I punteggi sono il giudizio della serie, fondato sulle capacità documentate in questo pezzo. A ogni funzionalità assegnate poi un peso da 0 a 5 - qui il peso è l’importanza che le date voi, e non c’entra coi pesi del modello - e la tabella fa il conto.
Come si legge, con due casi. Se avete un Mac e vi interessano soprattutto la memoria e la velocità - facilità 1, velocità 4, memoria 5, richieste 0 - il confronto esclude i motori che non girano su Mac e vince MLX, con llama.cpp vicino. Se invece dovete servire molti utenti su schede NVIDIA - richieste 5, velocità 3 - vince un pareggio fra vLLM, SGLang e TensorRT-LLM: i motori di servizio sono davvero vicini, e la scelta si decide sui dettagli - l’ecosistema, la cache dei prefissi, il compilatore.
I concetti che questo articolo introduce
Sette voci coprono il motore, la compressione che lo alimenta, la memoria su cui gira, lo streaming dal disco con la regolarità che lo rende indovinabile, e i due modi di spartire il modello fra più macchine.
| Concetto | Ambito | Che cos’è | Si lega a |
|---|---|---|---|
| Motore di inferenza | machine-learning | Il software che carica i pesi di un modello e li esegue per produrre le risposte: gestisce la cache, il campionamento e le richieste | esegue l’architettura del blocco del Transformer; gestisce la cache di chiavi e valori; è il livello distinto dall’addestramento del bilancio delle evoluzioni |
| Quantizzazione | machine-learning | La compressione dei pesi da sedici bit a otto o quattro: il modello occupa meno memoria e arriva più in fretta, a scapito di un po’ di precisione | agisce sui pesi di miscela di esperti e modello denso; è l’alleato dello streaming dei pesi |
| Memoria unificata | machine-learning | La memoria condivisa fra processore e scheda grafica, come nei chip Apple: un modello può usare tutta la memoria della macchina | è la condizione che rende pratici il motore di inferenza personale e lo streaming dei pesi |
| Streaming dei pesi | machine-learning | La lettura dei pesi dal disco al bisogno invece di caricarli tutti in memoria: con mmap, col caricamento pigro degli esperti del MoE, o con la cache dei neuroni attivi | è favorito dalla miscela di esperti (pochi parametri attivi per token); è limitato dalla banda del disco; lo usano llama.cpp, MLX e DwarfStar |
| Sparsità delle attivazioni | machine-learning | La regolarità per cui una piccola frazione di neuroni è attiva su quasi tutti i token, mentre la maggior parte si attiva di rado: è ciò che rende indovinabile lo streaming | alimenta lo streaming dei pesi con cache (PowerInfer); si lega alla miscela di esperti e ai suoi pochi parametri attivi per token |
| Parallelismo per livelli | machine-learning | La spartizione del modello fra più computer per gruppi di strati: le attivazioni attraversano la rete da uno stadio all’altro a ogni token; somma la capacità delle macchine | è un modo di eseguire il motore di inferenza su più macchine; si contrappone al parallelismo tensoriale; la rete è il suo collo di bottiglia |
| Parallelismo tensoriale | machine-learning | La spartizione del modello per fette di matrice: ogni macchina tiene una parte di ogni strato e scambia le somme parziali a ogni passaggio; richiede un’interconnessione velocissima | è un modo di eseguire il motore di inferenza su più macchine; richiede l’all-reduce fra le macchine |
Fonti
Le affermazioni portanti vengono dai progetti e dai paper citati, letti per questo pezzo; i rapporti di DeepSeek e Qwen sono già in Fonti dei pezzi precedenti.
- Improve and Manage,
serie-machine-learning,
GitHub, 2026 - il repository dei widget della serie: qui sta il
confronto «Quale motore per te» di questo pezzo (cartella
motori/), insieme ai widget di tutti gli altri pezzi della serie. - Georgi Gerganov e contributori,
llama.cpp, licenza MIT,
codice e discussioni lette - il motore personale di riferimento: il
formato GGUF, la quantizzazione, mmap, e l’opzione
--lazy-experts(richiesta di modifica 26003) per i modelli MoE più grandi della RAM. - Apple,
MLX, codice e discussioni lette
- il motore per Apple Silicon: memoria unificata, caricamento pigro dei pesi (mmap), e la richiesta di streaming out-of-core (issue 2878); i progetti della comunità mlx-flash e LightLX per modelli più grandi della memoria.
- Salvatore Sanfilippo (antirez), DwarfStar (ds4), README letto - il motore stretto per DeepSeek V4 Flash e GLM: Metal, CUDA e ROCm, la quantizzazione aggressiva degli esperti del MoE, lo streaming dal disco e il debito dichiarato verso llama.cpp e GGML.
- Woosuk Kwon e colleghi, Efficient Memory Management for Large Language Model Serving with PagedAttention, SOSP 2023, primaria aperta, letto l’abstract - vLLM: la cache di chiavi e valori paginata e il batching continuo.
- Yixin Song e colleghi, PowerInfer e PowerInfer-2, progetti letti - la sparsità delle attivazioni e lo streaming da NVMe con cache DRAM: modelli da 47 miliardi su un telefono.
- Reiner Pope, Sholto Douglas, Aakanksha Chowdhery e altri (Google), Efficiently Scaling Transformer Inference (arXiv:2211.05102, 2022), primaria aperta e letta - la distinzione fra la lettura del prompt, che elabora tutti i token in un passaggio, e la generazione, che produce un token nuovo per passo: è la ragione del costo per fasi della pipeline.