Best practice: inferenza AI sui servizi Cloud Run con GPU

Questa pagina fornisce le best practice per ottimizzare le prestazioni quando utilizzi un servizio Cloud Run con GPU per l'inferenza AI, concentrandosi sui modelli linguistici di grandi dimensioni (LLM). Per creare ed eseguire il deployment di un servizio Cloud Run in grado di rispondere in tempo reale agli eventi di scalabilità, devi:
  • Utilizza modelli che vengono caricati rapidamente e richiedono una trasformazione minima in strutture pronte per la GPU e ottimizza il modo in cui vengono caricati.
  • Utilizza configurazioni che consentano l'esecuzione simultanea massima ed efficiente per ridurre il numero di GPU necessarie per gestire una richiesta target al secondo, mantenendo i costi contenuti.

Modi consigliati per caricare modelli di ML di grandi dimensioni su Cloud Run

Google consiglia di archiviare i modelli ML all'interno delle immagini container o di ottimizzare il caricamento da Cloud Storage.

Compromessi tra archiviazione e caricamento dei modelli ML

Ecco un confronto delle opzioni:

Posizione modello Ora di pubblicazione Esperienza di sviluppo Tempo di avvio del container Costo di archiviazione
Immagine container Lenta. L'importazione in Cloud Run di un'immagine contenente un modello di grandi dimensioni richiede più tempo. Le modifiche all'immagine container richiedono un nuovo deployment, che potrebbe essere lento per le immagini di grandi dimensioni. Dipende dalle dimensioni del modello. Per modelli molto grandi, utilizza Cloud Storage per prestazioni più prevedibili ma più lente. Potenzialmente più copie in Artifact Registry.
Cloud Storage, caricato utilizzando il montaggio del volume Cloud Storage FUSE Veloce. Modello scaricato durante l'avvio del container. Non è difficile da configurare e non richiede modifiche all'immagine Docker. Veloce quando utilizzi le ottimizzazioni di rete. Non parallelizza il download. Una copia in Cloud Storage.
Cloud Storage, scaricati contemporaneamente utilizzando il comando Google Cloud CLI gcloud storage cp o l'API Cloud Storage, come mostrato nell'esempio di codice per il download simultaneo di Transfer Manager. Veloce. Modello scaricato durante l'avvio del container. Leggermente più difficile da configurare, perché dovrai installare Google Cloud CLI sull'immagine o aggiornare il codice per utilizzare l'API Cloud Storage. Veloce quando utilizzi le ottimizzazioni di rete. Google Cloud CLI scarica il file del modello in parallelo, rendendolo più veloce del montaggio FUSE. Una copia in Cloud Storage.
Internet Veloce. Modello scaricato durante l'avvio del container. In genere più semplice (molti framework scaricano i modelli da repository centrali). In genere scarsa e imprevedibile:
  • I framework possono applicare trasformazioni del modello durante l'inizializzazione. (Devi farlo in fase di compilazione).
  • L'host del modello e le librerie per il download del modello potrebbero non essere efficienti.
  • Il download da internet comporta un rischio di affidabilità. Il servizio potrebbe non avviarsi se la destinazione di download non è disponibile e il modello sottostante scaricato potrebbe cambiare, il che riduce la qualità. Ti consigliamo l'hosting nel tuo bucket Cloud Storage.
Dipende dal provider host del modello.

Archiviare i modelli nelle immagini container

Se memorizzi il modello ML nell'immagine container, il caricamento del modello trarrà vantaggio dall'infrastruttura di streaming dei container ottimizzata di Cloud Run. Tuttavia, la creazione di immagini container che includono modelli ML è un processo che richiede molte risorse, soprattutto quando si lavora con modelli di grandi dimensioni. In particolare, il processo di compilazione può diventare un collo di bottiglia per la velocità effettiva di rete. Quando utilizzi Cloud Build, ti consigliamo di utilizzare una macchina di build più potente con prestazioni di calcolo e networking migliorate. Per farlo, crea un'immagine utilizzando un file di configurazione della build con i seguenti passaggi:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'IMAGE', '.']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'IMAGE']
images:
- IMAGE
options:
 machineType: 'E2_HIGHCPU_32'
 diskSizeGb: '500'
 

Puoi creare una copia del modello per immagine se il livello contenente il modello è distinto tra le immagini (hash diverso). Potrebbe esserci un costo aggiuntivo di Artifact Registry perché potrebbe esserci una copia del modello per immagine se il livello del modello è univoco per ogni immagine.

Archivia i modelli in Cloud Storage

Per ottimizzare il caricamento dei modelli ML quando li carichi da Cloud Storage, utilizzando i volumi di montaggio di Cloud Storage o direttamente l'API o la riga di comando di Cloud Storage, devi utilizzare Direct VPC con il valore dell'impostazione di uscita impostato su all-traffic, insieme all'accesso privato Google.

Caricare modelli da internet

Per ottimizzare il caricamento dei modelli ML da internet, instrada tutto il traffico tramite la rete VPC con il valore dell'impostazione di uscita impostato su all-traffic e configura Cloud NAT per raggiungere la rete internet pubblica con una larghezza di banda elevata.

Considerazioni su build, deployment, runtime e progettazione del sistema

Le sezioni seguenti descrivono le considerazioni relative a build, deployment, runtime e progettazione del sistema.

Al momento della build

Il seguente elenco mostra gli aspetti da tenere in considerazione quando pianifichi la build:

  • Scegli una buona immagine di base. Devi iniziare con un'immagine di Deep Learning Containers o del registro di container NVIDIA per il framework ML che stai utilizzando. Queste immagini hanno installato i pacchetti più recenti relativi alle prestazioni. Non è consigliabile creare un'immagine personalizzata.
  • Scegli modelli quantizzati a 4 bit per massimizzare la concorrenza, a meno che tu non possa dimostrare che influiscono sulla qualità dei risultati. La quantizzazione produce modelli più piccoli e più veloci, riducendo la quantità di memoria GPU necessaria per gestire il modello e può aumentare il parallelismo in fase di runtime. Idealmente, i modelli devono essere addestrati alla profondità di bit di destinazione anziché essere quantizzati.
  • Scegli un formato del modello con tempi di caricamento rapidi per ridurre al minimo il tempo di avvio del container, ad esempio GGUF. Questi formati riflettono in modo più accurato il tipo di quantizzazione target e richiedono meno trasformazioni quando vengono caricati sulla GPU. Per motivi di sicurezza, non utilizzare checkpoint in formato pickle.
  • Crea e preriscalda le cache LLM al momento della build. Avvia l'LLM sulla macchina di build durante la creazione dell'immagine Docker. Attiva la memorizzazione nella cache dei prompt e fornisci prompt comuni o di esempio per preparare la cache all'uso reale. Salva gli output generati per caricarli in fase di runtime.
  • Salva il tuo modello di inferenza generato durante la compilazione. Ciò consente di risparmiare tempo significativo rispetto al caricamento di modelli archiviati in modo meno efficiente e all'applicazione di trasformazioni come la quantizzazione all'avvio del container.

Al momento del deployment

Il seguente elenco mostra le considerazioni da tenere presenti quando pianifichi l'implementazione:

  1. Assicurati di impostare la concorrenza del servizio in modo accurato in Cloud Run.
  2. Modifica i probe di avvio in base alla configurazione.

I probe di avvio determinano se il container è stato avviato ed è pronto ad accettare il traffico. Quando configuri i probe di avvio, tieni presente questi punti chiave:

  • Tempo di avvio adeguato: concedi un tempo sufficiente per l'inizializzazione e il caricamento completi del container, inclusi i modelli.
  • Verifica dell'idoneità del modello: configura il probe in modo che venga superato solo quando l'applicazione è pronta a gestire le richieste. La maggior parte dei motori di pubblicazione lo fa automaticamente quando il modello viene caricato nella memoria GPU, impedendo richieste premature.

Tieni presente che Ollama può aprire una porta TCP prima che venga caricato un modello. Per risolvere questo problema:

  • Modelli di precaricamento: consulta la documentazione di Ollama per indicazioni sul precaricamento del modello all'avvio.

In fase di esecuzione

  • Gestisci attivamente la lunghezza del contesto supportata. Più piccola è la finestra contestuale che supporti, più query puoi supportare in esecuzione in parallelo. I dettagli su come farlo dipendono dal framework.
  • Utilizza le cache LLM generate al momento della compilazione. Fornisci gli stessi flag che hai utilizzato durante la compilazione quando hai generato la cache di prompt e prefisso.
  • Carica dal modello salvato che hai appena scritto. Consulta Compromessi tra archiviazione e caricamento dei modelli per un confronto su come caricare il modello.
  • Se il framework lo supporta, valuta la possibilità di utilizzare una cache di coppie chiave-valore quantizzate. Ciò può ridurre i requisiti di memoria per query e consente di configurare un parallelismo maggiore. Tuttavia, può influire anche sulla qualità.
  • Regola la quantità di memoria GPU da riservare a pesi, attivazioni e cache chiave-valore del modello. Impostalo sul valore più alto possibile senza che si verifichi un errore di esaurimento della memoria.
  • Verifica se il tuo framework offre opzioni per migliorare le prestazioni di avvio del container (ad esempio, utilizzando la parallelizzazione del caricamento del modello).
  • Configura correttamente la concorrenza all'interno del codice del servizio. Assicurati che il codice del servizio sia configurato per funzionare con le impostazioni di concorrenza del servizio Cloud Run.

A livello di progettazione del sistema

  • Aggiungi cache semantiche, se opportuno. In alcuni casi, la memorizzazione nella cache di intere query e risposte può essere un ottimo modo per limitare il costo delle query comuni.
  • Controlla la varianza nei preamboli. Le cache dei prompt sono utili solo quando contengono i prompt in sequenza. Le cache vengono memorizzate nella cache in base al prefisso. Inserimenti o modifiche nella sequenza indicano che non sono memorizzati nella cache o sono presenti solo parzialmente.

Scalabilità automatica e GPU

Se utilizzi la scalabilità automatica predefinita di Cloud Run, Cloud Run scala automaticamente il numero di istanze di ogni revisione in base a fattori quali l'utilizzo della CPU e la concorrenza delle richieste. Tuttavia, Cloud Run non scala automaticamente il numero di istanze in base all'utilizzo della GPU.

Per una revisione con una GPU, se la revisione non ha un utilizzo significativo della CPU, Cloud Run esegue lo scale out per la concorrenza delle richieste. Per ottenere uno scaling ottimale per la concorrenza delle richieste, devi impostare un numero massimo di richieste in parallelo per istanza ottimale, come descritto nella sezione successiva.

Numero massimo di richieste in parallelo per istanza

L'impostazione Numero massimo di richieste in parallelo per istanza controlla il numero massimo di richieste che Cloud Run invia a una singola istanza contemporaneamente. Devi ottimizzare la concorrenza in modo che corrisponda alla concorrenza massima che il codice all'interno di ogni istanza può gestire con buone prestazioni.

Carichi di lavoro di concorrenza massima e AI

Quando esegui un workload di inferenza AI su una GPU in ogni istanza, la concorrenza massima che il codice può gestire con un buon rendimento dipende da dettagli specifici del framework e dell'implementazione. I seguenti fattori influiscono sull'impostazione del numero massimo ottimale di richieste simultanee:

  • Numero di istanze del modello caricate sulla GPU
  • Numero di query parallele per modello
  • Utilizzo del batching
  • Parametri di configurazione batch specifici
  • Quantità di lavoro non GPU

Se il numero massimo di richieste simultanee è impostato su un valore troppo elevato, le richieste potrebbero finire per attendere all'interno dell'istanza l'accesso alla GPU, il che comporta un aumento della latenza. Se il numero massimo di richieste simultanee è impostato su un valore troppo basso, la GPU potrebbe essere sottoutilizzata e Cloud Run potrebbe fare lo scale out più istanze del necessario.

Una regola generale per configurare il numero massimo di richieste simultanee per i workload AI è:

(Number of model instances * parallel queries per model) + (number of model instances * ideal batch size)

Ad esempio, supponiamo che un'istanza carichi 3 istanze del modello sulla GPU e che ogni istanza del modello possa gestire 4 query parallele. La dimensione ideale del batch è anche 4, perché è il numero di query parallele che ogni istanza del modello può gestire. Utilizzando la regola empirica, imposteresti le richieste simultanee massime 24: (3 * 4) + (3 * 4).

Tieni presente che questa formula è solo una regola empirica. L'impostazione ideale per il numero massimo di richieste simultanee dipende dai dettagli specifici della tua implementazione. Per ottenere il rendimento ottimale effettivo, ti consigliamo di eseguire test di carico del servizio con diverse impostazioni per le richieste simultanee massime per valutare quale opzione offre il rendimento migliore.

Compromessi tra velocità effettiva, latenza e costi

Consulta Compromessi tra velocità effettiva, latenza e costi per l'impatto delle richieste simultanee massime su velocità effettiva, latenza e costi. Tieni presente che tutti i servizi Cloud Run che utilizzano GPU devono avere configurata la fatturazione basata sulle istanze.