ELAI S.r.l.

Perché un servizio AI rallenta prima di esaurire la capacità

Un calcolo da 100 ms può diventare una risposta da 750 ms. Code, variabilità e margine di capacità spiegati con derivazione ed esperimento riproducibile.

Perché un servizio AI rallenta prima di esaurire la capacità

Otto richieste al secondo per un server che ne gestisce dieci

Un servizio di inferenza impiega in media 100 millisecondi per una richiesta. Potrebbe quindi completarne dieci al secondo, lavorando senza pause. Ne arrivano soltanto otto al secondo: perché gli utenti osservano attese ben superiori a 100 millisecondi? Il conto della capacità media non considera quando arrivano le richieste né quanto variano le durate. Tre richieste ravvicinate possono formare una coda anche se più tardi il server resterà inattivo. Il tempo libero futuro non può essere usato per elaborare una richiesta prima che arrivi.

Abstract. Studiamo un server che elabora una richiesta alla volta, in ordine di arrivo. Separiamo servizio, attesa e risposta; ricaviamo la formula della coda M/G/1 e confrontiamo tre distribuzioni di durata con la stessa media. Nell’esempio, la risposta media passa da 300 a 500 o 750 ms senza cambiare né il numero medio di richieste né il servizio medio di 100 ms. Una simulazione a eventi verifica l’ordine di grandezza e rende esplicita la variabilità statistica. Il modello è didattico: non è un test di carico EL-AI né una previsione di una GPU con batching dinamico.

Prima la sequenza concreta, poi il modello

Quattro richieste arrivano ai tempi 0, 40, 80 e 500 ms. Ciascuna richiede esattamente 100 ms. La prima inizia subito; la seconda inizia a 100 ms e aspetta 60 ms; la terza inizia a 200 ms e aspetta 120 ms; la quarta trova il server libero e inizia a 500 ms. L’elaborazione ha sempre la stessa durata, ma le risposte richiedono 100, 160, 220 e 100 ms. Non è necessario che il modello diventi più lento perché il servizio percepito rallenti.

inizioᵢ / startᵢ = max(arrivoᵢ / arrivalᵢ, fineᵢ₋₁ / endᵢ₋₁) fineᵢ / endᵢ = inizioᵢ / startᵢ + Sᵢ Tᵢ = Wᵢ + Sᵢ

S indica il tempo di servizio, cioè quanto il server lavora su quella richiesta; W il tempo in coda prima di iniziare; T il tempo totale nel sistema. La prima relazione è il cuore del simulatore: si può iniziare soltanto dopo l’arrivo e dopo il completamento precedente. Qui non includiamo trasporto di rete, autenticazione o pre-elaborazione esterna; se esistono, vanno misurati e aggiunti coerentemente. Il nome “latenza” da solo non dice quale di questi intervalli stiamo osservando.

Le ipotesi che rendono risolvibile la coda

Nel modello M/G/1 gli arrivi seguono un processo di Poisson con tasso λ, in richieste al secondo. Questo implica intervalli indipendenti esponenziali tra arrivi; non implica richieste regolarmente distanziate. G indica una distribuzione generale dei tempi di servizio, indipendenti e identicamente distribuiti e indipendenti dagli arrivi. Il numero 1 indica un solo server. Assumiamo coda illimitata, nessun abbandono, nessuna priorità, nessuna interruzione di una richiesta in corso e ordine FIFO, first in first out.

Scriviamo m=E[S] per il servizio medio e ρ=λm per il carico medio, senza unità. Con λ=8 e m=0,1 s otteniamo ρ=0,8. Occorre ρ<1 per una distribuzione stazionaria stabile in questo modello; inoltre serve un secondo momento E[S²] finito per l’attesa media finita della formula che useremo. Stabilità significa che la coda non cresce indefinitamente nel lungo periodo, non che ogni richiesta rispetti una scadenza. Il nostro 80% è il carico di un server ideale, non una lettura automatica del contatore di utilizzo GPU.

Perché compare il quadrato della durata

Chi arriva trova eventualmente una richiesta già in servizio e altre in coda. Deve aspettare il servizio residuo R della prima e il servizio completo delle richieste davanti. Una richiesta lunga non soltanto dura di più: è anche più probabile incontrarla ancora in corso. Questa osservazione spiega perché conoscere soltanto la media delle durate non basta. Se una lavorazione dura s secondi, il suo residuo scende linearmente da s a zero; l’area sotto questa discesa è s²/2. Le durate lunghe pesano quindi quadraticamente sul residuo medio visto nel tempo.

E[R] = λ E[S²] / 2 E[W] = E[R] + m E[N_q] E[N_q] = λ E[W] E[W] = λ E[S²] / (2(1−ρ))

N_q è il numero di richieste in attesa, esclusa quella in servizio. La terza riga usa la relazione di Little tra numero medio, flusso e attesa. Gli arrivi Poisson osservano le medie temporali, proprietà chiamata PASTA, Poisson Arrivals See Time Averages: è il collegamento tra la fotografia vista all’arrivo e la media lungo il tempo. Sostituendo la terza riga nella seconda e raccogliendo E[W] otteniamo la formula di Pollaczek–Khinchin. λ ha unità s⁻¹, E[S²] s²: il risultato è correttamente in secondi.

Stessa media, tre attese diverse

Nel primo caso ogni servizio dura esattamente 0,1 s: E[S²]=0,01 s². Nel secondo la durata è esponenziale con media 0,1 s: il secondo momento è 0,02 s². Nel terzo, nove richieste su dieci richiedono 0,05 s e una su dieci 0,55 s, indipendentemente dalle precedenti. La media resta 0,9·0,05+0,1·0,55=0,1 s, ma il secondo momento è 0,9·0,05²+0,1·0,55²=0,0325 s². Nessuna distribuzione deriva da un log aziendale: sono alternative sintetiche costruite per isolare la variabilità.

DistribuzioneE[S] (ms)E[W] (ms)E[T] (ms)
S = 0.1 s100200300
S ~ Exp(mean=0.1 s)100400500
P(S=0.05 s)=0.9; P(S=0.55 s)=0.1100650750

Per la miscela calcoliamo 8·0,0325/[2·(1−0,8)]=0,65 s di coda, a cui aggiungere 0,1 s di servizio. Il server lavora mediamente la stessa frazione di tempo in tutti i casi. Cambia il danno che un lavoro lungo trasferisce alle richieste dietro di sé. Un indicatore comodo è C_s²=Var(S)/m², il quadrato del coefficiente di variazione: vale 0, 1 e 2,25 nei tre casi. Poiché E[S²]=m²(1+C_s²), l’attesa media è ρm(1+C_s²)/[2(1−ρ)].

Avvicinarsi al limite rende costose piccole variazioni

Il denominatore 1−ρ è il margine residuo. Con servizio esponenziale di media 100 ms, portare gli arrivi da 8 a 9 al secondo fa crescere la risposta media da 0,5 a 1 s: un aumento del traffico del 12,5% raddoppia la risposta. A 9,5 richieste al secondo la risposta è 2 s. Non c’è una soglia magica all’80% valida per ogni servizio; c’è una curva che dipende da distribuzioni, obiettivi e architettura. Per scegliere una riserva di capacità bisogna decidere quale risposta è accettabile e verificare che il modello descriva il sistema.

Risposta media teorica al crescere del carico ρ, mantenendo servizio medio 100 ms. Le tre curve differiscono solo per la distribuzione delle durate. Sono medie stazionarie del modello, non percentili né misure di produzione.
Risposta media teorica al crescere del carico ρ, mantenendo servizio medio 100 ms. Le tre curve differiscono solo per la distribuzione delle durate. Sono medie stazionarie del modello, non percentili né misure di produzione.

Un miglioramento del calcolo può avere un effetto non lineare sulla risposta. Nel caso esponenziale, ridurre il servizio medio da 100 a 80 ms con otto arrivi al secondo porta ρ da 0,8 a 0,64 e la risposta media da 500 a circa 222 ms. Non stiamo promettendo questo guadagno su una macchina: abbiamo cambiato un parametro mantenendo tutte le altre ipotesi. Aggiungere un secondo server, invece, cambia il modello; non basta sostituire m con m/2 nella formula del server singolo. Anche il bilanciamento del carico e la possibilità di condividere la coda contano.

Una simulazione che non nasconde il proprio errore

Abbiamo eseguito otto simulazioni indipendenti per ciascuna distribuzione. Ogni simulazione parte vuota, scarta le prime 20.000 richieste come riscaldamento e ne conserva 300.000. Gli intervalli di arrivo sono esponenziali di media 1/8 s; il programma applica la ricorrenza mostrata all’inizio. NumPy 2.5.3 genera 24 flussi casuali distinti mediante SeedSequence(20260929).spawn(24), in ordine costante, esponenziale, miscela. Le attese medie osservate, mediate sulle otto repliche, sono rispettivamente 199,0, 403,7 e 658,0 ms, contro 200, 400 e 650 ms teorici.

Gli errori standard stimati dalle otto medie indipendenti sono circa 1,0, 4,7 e 6,1 ms. Le richieste consecutive nella stessa coda non sono osservazioni indipendenti: un accumulo influenza molti clienti successivi. Trattarle come campioni indipendenti produrrebbe un’incertezza ingannevolmente piccola. Le repliche aiutano a vedere questo limite, ma otto non costituiscono una dimostrazione asintotica né eliminano ogni effetto del riscaldamento. La formula è il risultato analitico sotto ipotesi; la simulazione ne è un controllo numerico finito, con scarti dichiarati.

Dove questo modello smette di descrivere l’inferenza

In un motore di inferenza reale, più richieste possono essere elaborate insieme. Il batching modifica il servizio in funzione della coda: viene meno l’indipendenza richiesta qui. Generare testi di lunghezza diversa, interrompere richieste, riusare cache o condividere l’acceleratore con altri processi introduce ulteriori dipendenze. Gli arrivi possono essere a raffiche, anziché Poisson. Anche un limite alla coda cambia l’interpretazione: alcune richieste saranno rifiutate, quindi una bassa latenza delle sole richieste accettate può nascondere un servizio in difficoltà.

Per applicare l’analisi servirebbero timestamp di arrivo, inizio e fine, classe della richiesta, esito e politica di scheduling. Bisognerebbe verificare la forma degli intervalli, la variabilità del servizio e le correlazioni nel tempo, poi confrontare previsioni e prove di carico fuori dal campione usato per stimare i parametri. Queste attività non sono state eseguite su EL-AI. La formula della media non determina il 95° o 99° percentile: due distribuzioni possono condividere media e varianza e differire nelle code. Un obiettivo sui percentili richiede misure o un modello distributivo ulteriore.

La capacità disponibile non è tempo di risposta garantito

Un servizio rallenta prima della saturazione perché deve assorbire irregolarità nel tempo, non soltanto una quantità media di lavoro. Il margine di capacità consente di smaltire gli accumuli; la variabilità decide quanto spesso e quanto a lungo tali accumuli si formano. Nel nostro caso di otto richieste al secondo, ridurre la variabilità cambia l’attesa pur lasciando invariato il calcolo medio. Questa è la conclusione utile per progettare: misurare separatamente servizio e coda, e scegliere il margine rispetto a un obiettivo verificabile, anziché inseguire il massimo utilizzo come unico indicatore di efficienza.

Riferimento e riproducibilità

Eytan Modiano, MIT — M/G/1 Queues, Lectures 8–9, course 6.263J, Fall 2002, slides 2–6.

Il riferimento espone ipotesi, formula e dimostrazione tramite servizio residuo. I numeri del servizio AI, la miscela e le simulazioni sono esempi didattici svolti per questo articolo. Il codice seguente riproduce il confronto analitico; l’archivio contiene il simulatore completo, risultati per replica e grafici. Non sono riproduzioni di un benchmark degli autori né ricerca originale sottoposta a peer review.

mean_service = 0.1  # seconds
arrival_rate = 8.0  # requests per second
rho = arrival_rate * mean_service
for name, second_moment in [('constant', .01), ('exponential', .02), ('mixture', .0325)]:
    waiting = arrival_rate * second_moment / (2 * (1-rho))
    print(name, 'queue seconds:', waiting, 'total seconds:', waiting+mean_service)
# Analytical M/G/1 values, not a real inference benchmark.

Codice, dati e istruzioni · JSON. Calcoli didattici eseguiti con Python 3.14.0; figure con Matplotlib 3.11.2. Analisi con assistenza AI, senza dichiarare peer review o revisione umana. Copertina originale ImageGen, illustrativa: non documenta persone, sedi o installazioni EL-AI. Fonti consultate il 29 settembre 2026.