Panoramica delle best practice per l'inferenza su GKE

Questo documento fornisce una panoramica generale delle best practice per l'esecuzione dei carichi di lavoro di inferenza su GKE.

Questo documento è destinato ad amministratori, operatori e sviluppatori di dati che vogliono adottare le best practice per i carichi di lavoro di inferenza utilizzando acceleratori, come GPU e TPU, con Kubernetes e GKE. Per scoprire di più sui ruoli comuni, consulta Ruoli utente e attività comuni di GKE.

Preparati per la pubblicazione dell'inferenza su GKE

Questa sezione descrive le best practice di base da seguire quando ti prepari a eseguire il deployment di un workload di inferenza. Queste pratiche includono l'analisi del caso d'uso, la scelta dei modelli e la selezione degli acceleratori.

Analizza le caratteristiche del tuo caso d'uso di inferenza

Prima di eseguire il deployment di un carico di lavoro di inferenza, analizza i suoi requisiti specifici. Questa analisi ti aiuta a prendere decisioni architetturali che bilanciano prestazioni, costi e affidabilità. Comprendere il tuo caso d'uso ti aiuta a selezionare i modelli, gli acceleratori e le configurazioni appropriati per soddisfare gli obiettivi del livello di servizio (SLO).

Per guidare l'analisi, valuta le seguenti dimensioni chiave del carico di lavoro:

  • Definisci i requisiti di prestazioni e latenza: determina gli SLO della tua applicazione per latenza e throughput. Le metriche chiave da definire includono richieste al secondo (RPS), latenza della risposta, lunghezza dei token di input e output e tasso di successo della cache dei prefissi. Per saperne di più, consulta Metriche sul rendimento dell'inferenza.
  • Valuta i requisiti e la scalabilità del modello: le caratteristiche del modello scelto influenzano direttamente le tue esigenze di infrastruttura. Considera la lunghezza massima del contesto supportata dal modello e confrontala con quella richiesta dal tuo carico di lavoro. Se il tuo caso d'uso non richiede il contesto massimo, la riduzione della lunghezza massima del contesto può liberare la memoria dell'acceleratore per una cache KV più grande, aumentando potenzialmente la velocità effettiva.
  • Stabilisci vincoli di costi e aziendali: il budget e gli obiettivi aziendali sono fattori chiave per progettare un servizio di inferenza sostenibile ed economicamente vantaggioso. Definisci il costo per milione di token target per l'input e l'output e il budget mensile totale per questo carico di lavoro. Identifica il tuo obiettivo di ottimizzazione, ad esempio prezzo/prestazioni, latenza più bassa o throughput più elevato, e se la tua app può tollerare una latenza variabile.

Scegliere i modelli giusti per i tuoi casi d'uso di inferenza

La scelta del modello giusto influisce direttamente su prestazioni, costi e fattibilità dell'applicazione di inferenza. Per selezionare il modello ottimale, valuta i candidati in base ai seguenti criteri:

  • Allineamento di attività e modalità: valuta i modelli in base alle attività designate e alle modalità supportate. Un modello ottimizzato per un'attività specifica quasi sempre supera le prestazioni di un modello più generico.
  • Caratteristiche tecniche: l'architettura e la precisione del tipo di dati di un modello, ad esempio FP16, FP8 e FP4, sono fattori chiave per determinare i requisiti di risorse e il rendimento. Questa valutazione ti aiuta a determinare se devi applicare tecniche di quantizzazione. Controlla la precisione supportata per i pesi del modello, assicurati il supporto del framework e verifica la lunghezza massima del contesto supportata del modello.
  • Rendimento ed efficacia in termini di costi: per prendere una decisione basata sui dati, confronta i modelli selezionati utilizzando benchmark disponibili pubblicamente e i tuoi test interni. Utilizza le classifiche come Chatbot Arena per confrontare i modelli e valuta il costo per milione di token per ogni modello sull'hardware di destinazione.

Applica la quantizzazione al modello

La quantizzazione è una tecnica per ottimizzare i workload di inferenza riducendo l'impronta di memoria del modello. Converte i pesi, le attivazioni e la cache chiave-valore (KV) del modello da formati in virgola mobile ad alta precisione (come FP16, FP32 e FP64) a formati a precisione inferiore (come FP8 e FP4). Questa riduzione della memoria può portare a miglioramenti significativi sia in termini di prestazioni che di efficacia in termini di costi.

La quantizzazione riduce l'impronta di memoria del modello, il che a sua volta riduce l'overhead del trasferimento di dati e libera memoria per una cache KV più grande.

Per applicare in modo efficace la quantizzazione ai tuoi modelli, segui questi consigli:

  • Valuta il compromesso tra accuratezza: a volte la quantizzazione può comportare una perdita di accuratezza del modello. Quando valuti il compromesso tra accuratezza e quantizzazione, tieni presente che la quantizzazione a 8 bit può spesso comportare una perdita minima di accuratezza. Al contrario, la quantizzazione a 4 bit può ridurre fino a quattro volte i requisiti di memoria dell'acceleratore, ma potrebbe anche causare una maggiore perdita di precisione rispetto alla quantizzazione a 8 bit. Valuta le prestazioni del modello quantizzato nel tuo caso d'uso specifico per assicurarti che l'accuratezza rientri ancora in un intervallo accettabile. Per valutare la perdita di accuratezza, puoi utilizzare strumenti come OpenCompass e Language Model Evaluation Harness.
  • Valuta il supporto dell'accelerazione hardware: per ottenere il massimo dalla quantizzazione, utilizza acceleratori che forniscono accelerazione hardware per i formati di dati utilizzati dal modello quantizzato. Ad esempio:
    • Le GPU NVIDIA H100 forniscono l'accelerazione hardware per le operazioni FP8 e FP16.
    • Le GPU NVIDIA B200 forniscono l'accelerazione hardware per le operazioni FP4, FP8 e FP16.
    • Cloud TPU v5p fornisce l'accelerazione hardware per le operazioni FP8.
  • Controlla i modelli pre-quantizzati: prima di quantizzare un modello, controlla i repository di modelli pubblici come Hugging Face. Idealmente, trova un modello addestrato in modo nativo con una precisione inferiore, in quanto ciò può fornire vantaggi in termini di prestazioni senza la potenziale perdita di accuratezza dovuta alla quantizzazione post-addestramento.
  • Utilizza una libreria di quantizzazione: se non è disponibile un modello prequantizzato, utilizza una libreria per eseguire la quantizzazione. I server di inferenza come vLLM supportano l'esecuzione di modelli quantizzati con una serie di tecniche. Puoi utilizzare strumenti come llm-compressor per applicare tecniche di quantizzazione a un modello non quantizzato.
  • Valuta la quantizzazione della cache KV: oltre a quantizzare i pesi del modello, puoi quantizzare anche la cache KV. Questa tecnica riduce ulteriormente la memoria richiesta per la cache KV in fase di runtime, il che può portare a un miglioramento delle prestazioni.

Per saperne di più, consulta Ottimizzare i carichi di lavoro di inferenza LLM sulle GPU.

Scegliere gli acceleratori giusti

La scelta dell'acceleratore giusto influisce direttamente su prestazioni, costi ed esperienza utente del servizio di inferenza. La scelta ottimale dipende da un'analisi dei requisiti di memoria del modello, degli obiettivi di rendimento e del budget.

Per scegliere l'acceleratore giusto per il tuo caso d'uso specifico, segui questi passaggi:

  1. Calcola i requisiti di memoria: innanzitutto, calcola la memoria minima dell'acceleratore necessaria per caricare ed eseguire il modello. La memoria totale è la somma della memoria richiesta per i pesi del modello, l'overhead del motore di inferenza, le attivazioni intermedie e la cache KV.

    Per stimare la memoria necessaria, utilizza la seguente equazione:

    \[ \begin{aligned} \text{Required accelerator memory} = {} & (\text{Model weights} + \text{Overhead} + \text{Activations}) \\ & + (\text{KV cache per batch} \times \text{Batch size}) \end{aligned} \]

    I termini dell'equazione sono i seguenti:

    • Pesi del modello: la dimensione dei parametri del modello.
    • Overhead: un buffer per il server di inferenza e altri overhead di sistema, in genere 1-2 GB.
    • Attivazione: la memoria richiesta per le attivazioni intermedie durante l'esecuzione di un modello.
    • Cache KV per batch: la memoria richiesta per la cache KV per una singola sequenza, che viene scalata in base alla lunghezza del contesto e alla configurazione del modello.
    • Dimensioni batch: il numero di sequenze (max_num_sequences) che verranno elaborate contemporaneamente dal motore di inferenza.

    Esempio: calcola i requisiti di memoria dell'acceleratore per Gemma 3

    Per calcolare la memoria dell'acceleratore necessaria per eseguire il deployment di un modello Gemma 3 con 27 miliardi di parametri con una precisione BF16 per un caso d'uso di generazione di testo, puoi utilizzare i seguenti valori.

    Per una procedura dettagliata interattiva di questo calcolo, consulta la sezione Quanta VRAM serve al mio modello? Notebook Colab.

    • Input:
      • Ponderazioni modello: 54 GB
      • Dimensione batch (max_num_sequences): 1
      • Lunghezza media dell'input: 1500 token
      • Lunghezza media dell'output: 200 token
      • Overhead del motore di inferenza: 1 GB (stimato)
      • Dimensioni del tipo di dati della cache KV: 2 (per BF16)
      • Vettori KV: 2 (uno per la chiave, uno per il valore)
    • Configurazione del modello per un modello Gemma 3 27B ottimizzato per le istruzioni:
      • hidden_size: 5376
      • intermediate_size: 21504
      • num_attention_heads: 32
      • num_hidden_layers: 62
      • num_key_value_heads: 16
    • Calcolo della memoria:
      • sequence_length = avg_input_length + avg_output_length = 1500 + 200 = 1700 token
      • pytorch_activation_peak_memory = (max_num_sequences * sequence_length * (18 * hidden_size + 4 * intermediate_size)) / (1000^3) = ~0,31 GB (stimato).
      • head_dims = hidden_size / num_attention_heads = 5376 / 32 = 168
      • kv_cache_memory_per_batch = (kv_vectors * max_num_sequences * sequence_length * num_key_value_heads * head_dims * num_hidden_layers * kv_data_type_size) / (1000^3) = (2 * 1 * 1700 * 16 * 168 * 62 * 2) / (1000^3) = ~1,13 GB
      • Memoria dell'acceleratore richiesta = Model weights + Overhead + Activations + KV cache per batch = 54 + 1 + 0,31 + 1,13 = ~56,44 GB

    La memoria dell'acceleratore totale stimata necessaria per il deployment del modello è di circa 57 GB.

  2. Valuta le opzioni di acceleratore: una volta stimati i requisiti di memoria, valuta le opzioni GPU e TPU disponibili su GKE.

    Oltre alla quantità di memoria dell'acceleratore, considera i seguenti requisiti del modello per la valutazione:

    • Per i modelli che richiedono più di un acceleratore, verifica il supporto della connettività ad alta velocità, come NVLINK e GPUDirect, per ridurre la latenza di comunicazione.
    • Per i modelli quantizzati, utilizza acceleratori con accelerazione hardware nativa per tipi di dati a precisione inferiore, come FP8 e FP4, per ottenere i maggiori vantaggi in termini di prestazioni.

    La tua scelta comporta un compromesso tra queste funzionalità, prestazioni, costi e disponibilità.

    Suggerimento: per i suggerimenti più recenti sugli acceleratori in base ai benchmark delle prestazioni di pubblicazione e all'analisi dei costi, puoi anche utilizzare lo strumento GKE Inference Quickstart. Per maggiori dettagli, consulta la documentazione Guida rapida di GKE Inference.

    Per aiutarti a scegliere gli acceleratori giusti per il tuo workload, la seguente tabella riassume le opzioni più adatte per i casi d'uso di inferenza comuni. Questi casi d'uso sono definiti come segue:

    • Inferenza di modelli di piccole dimensioni: per modelli con pochi miliardi di parametri, in cui il carico di calcolo è limitato a un singolo host.
    • Inferenza di modelli di grandi dimensioni su un singolo host: per modelli con decine o centinaia di miliardi di parametri, in cui il carico di calcolo è condiviso tra più acceleratori su una singola macchina host.
    • Inferenza di modelli di grandi dimensioni multi-host: per modelli con centinaia di miliardi o trilioni di parametri, in cui il carico di calcolo è condiviso tra più acceleratori su più macchine host.
    Caso d'uso Acceleratori consigliati Serie di macchine Caratteristiche principali
    Inferenza di modelli di piccole dimensioni NVIDIA L4 G2 Opzione conveniente per modelli di piccole dimensioni (24 GB di memoria per GPU).
    NVIDIA RTX Pro 6000 G4 Conveniente per modelli con meno di 30 miliardi di parametri e generazione di immagini (96 GB di memoria per GPU). Supporta la comunicazione peer-to-peer diretta della GPU, il che lo rende adatto per l'inferenza multi-GPU su un singolo host.
    TPU v5e - Ottimizzato per l'efficienza dei costi.
    TPU v6e - Offre il valore più alto per i modelli Transformer e da testo a immagine.
    Inferenza di modelli di grandi dimensioni su un singolo host NVIDIA A100 A2 Adatto alla maggior parte dei modelli che rientrano in un singolo nodo (fino a 640 GB di memoria totale).
    NVIDIA H100 A3 Ideale per i carichi di lavoro di inferenza che rientrano in un singolo nodo (fino a 640 GB di memoria totale).
    NVIDIA B200 A4 Opzione a prova di futuro per modelli impegnativi che rientrano in un singolo nodo (fino a 1440 GB di memoria totale).
    TPU v4 - Offre un buon equilibrio tra costi e prestazioni.
    TPU v5p - Un'opzione ad alte prestazioni per workload impegnativi.
    Inferenza di modelli di grandi dimensioni multi-host NVIDIA H200 A3 Ultra Adatto a modelli di grandi dimensioni che richiedono molta memoria (fino a 1128 GB di memoria totale).
    NVIDIA B200 / GB200 A4 / A4X Per i workload più esigenti, ad alta intensità di calcolo e vincolati alla rete. Le macchine A4X utilizzano CPU basate su Arm, che potrebbero richiedere il refactoring del carico di lavoro (modifiche al codice oltre a una semplice ricompilazione del container) se il carico di lavoro utilizza funzionalità o ottimizzazioni specifiche per x86.
    TPU v5e - Ottimizzato per efficienza dei costi e prestazioni per il servizio di LLM di dimensioni medie e grandi.
    TPU v5p - Un'opzione ad alte prestazioni per l'inferenza multihost che richiede la parallelizzazione su larga scala.
    TPU v6e - Ottimizzato per il servizio di trasformatori, da testo a immagine e CNN.

    Esempio: scegli un acceleratore per un modello da 260 GB

    Supponiamo di dover eseguire il deployment di un modello che richiede 260 GB di memoria dell'acceleratore totale (200 GB per il modello, 50 GB per la cache KV e 10 GB per l'overhead).

    In base ai soli requisiti di memoria, puoi escludere le GPU NVIDIA L4, in quanto la macchina G2 più grande offre un massimo di 192 GB di memoria dell'acceleratore. Inoltre, poiché le GPU L4 non supportano la connettività a bassa latenza e ad alta velocità tra gli acceleratori, la distribuzione del workload su più nodi non è un'opzione praticabile per ottenere le prestazioni desiderate.

    Se vuoi evitare il refactoring dei tuoi workload x86-64 (ovvero dover modificare il codice in modo che possa essere eseguito su un tipo diverso di processore), escludi anche gli acceleratori NVIDIA GB200 e GB300, che utilizzano CPU basate su Arm.

    Ti rimangono le seguenti opzioni:

    • NVIDIA A100
    • NVIDIA RTX Pro 6000
    • NVIDIA H100
    • NVIDIA H200
    • NVIDIA B200

    Tutti questi acceleratori hanno memoria sufficiente. Il passaggio successivo consiste nel valutarne la disponibilità nelle regioni di destinazione. Supponiamo che tu scopra che solo le GPU NVIDIA A100 e NVIDIA H100 sono disponibili in una determinata regione. Dopo aver confrontato il rapporto prezzo/prestazioni di queste due opzioni, potresti scegliere NVIDIA H100 per il tuo workload.

    GPU multi-istanza

    Per aumentare l'utilizzo della GPU e ottimizzare i costi della GPU, puoi utilizzare configurazioni GPU multi-istanza. Con questa configurazione, partizioni una GPU supportata per condividere una singola GPU tra più container su GKE. Quando esegui il provisioning di una GPU multi-istanza, colleghi solo GPU intere ai nodi GKE e sei soggetto ai prezzi delle GPU corrispondenti. Ti consigliamo di utilizzare GPU multi-istanza solo con workload attendibili.

    Ad esempio, puoi collegare una NVIDIA RTX PRO 6000 ed eseguire le seguenti operazioni:

    • Partizionala in quattro istanze (ciascuna istanza fornisce 24 GB di memoria dell'acceleratore) ed esegui modelli di diffusione o piccoli carichi di lavoro di inferenza del modello, come modelli con circa 8 miliardi di parametri e che utilizzano la precisione del formato dei dati FP16 per i pesi del modello. Questa partizione potrebbe avere un rapporto prezzo/prestazioni migliore rispetto a una NVIDIA L4.
    • Partizionala in due istanze (ciascuna istanza fornisce 48 GB di memoria dell'acceleratore) ed esegui piccoli carichi di lavoro di inferenza del modello, ad esempio modelli con circa 15 miliardi di parametri e che utilizzano la precisione del formato dei dati FP16 per i pesi del modello. Questa partizione potrebbe essere un'alternativa all'esecuzione di carichi di lavoro di inferenza su una GPU NVIDIA A100 da 40 GB.

    Per saperne di più, consulta Esecuzione di GPU multi-istanza.

    Per saperne di più, consulta Tipi di macchine GPU e Famiglia di macchine ottimizzate per l'acceleratore nella documentazione di Compute Engine.

  3. Seleziona una strategia di distribuzione dell'inferenza: se il modello è troppo grande per un singolo acceleratore, seleziona una strategia di distribuzione in base ai requisiti del tuo workload.

    Per prima cosa, scegli una strategia di distribuzione in base alla topologia dell'hardware:

    • Singolo acceleratore: se il tuo modello rientra in un singolo acceleratore, questo è l'approccio più semplice e consigliato.
    • Multi-acceleratore a nodo singolo: se il modello rientra in un singolo nodo con più acceleratori, puoi utilizzare il parallelismo dei tensori per distribuire il modello tra gli acceleratori su quel nodo.
    • Multi-nodo, multi-acceleratore: se il modello è troppo grande per un singolo nodo, puoi utilizzare una combinazione di parallelismo tensoriale e pipeline per distribuirlo su più nodi.

    Per implementare queste strategie, puoi utilizzare le seguenti tecniche di parallelismo:

    • Parallelismo dei tensori: questa tecnica suddivide i livelli di un modello in più acceleratori. È molto efficace all'interno di un singolo nodo con interconnessioni ad alta velocità come NVLINK o PCIe peer-to-peer diretto, ma richiede una comunicazione significativa tra gli acceleratori.

      Esempio: parallelismo tensoriale

      Ad esempio, supponiamo che tu debba eseguire il deployment di un modello con 109 miliardi di parametri. Con la precisione BF16 (16 bit) predefinita, il caricamento dei pesi del modello nella memoria dell'acceleratore richiede circa 113 GB. Una singola GPU NVIDIA H100 fornisce 80 GB di memoria. Pertanto, anche senza tenere conto di altri requisiti di memoria come la cache KV, hai bisogno di almeno due GPU NVIDIA H100 per caricare il modello, utilizzando una dimensione di parallelismo dei tensori pari a due.

    • Parallelismo della pipeline: questa tecnica partiziona i livelli di un modello in sequenza su più nodi. È ideale per distribuire un modello su più nodi in un deployment multihost e richiede meno comunicazione tra i ranghi del modello rispetto al parallelismo dei tensori.

      Esempio: parallelismo ibrido (tensore e pipeline)

      Per un modello molto grande con oltre 600 miliardi di parametri, il requisito di memoria può superare 1,1 TB. In uno scenario con due nodi a3-megagpu-8g (ciascuno con otto GPU NVIDIA H100), il cluster totale ha 1,28 TB di memoria dell'acceleratore. Per eseguire il modello, implementeresti una strategia ibrida: parallelismo dei tensori a 8 vie all'interno di ogni nodo e parallelismo della pipeline a 2 vie tra i due nodi. Il modello verrebbe suddiviso in due fasi, con la prima metà dei livelli sul primo nodo e la seconda metà sul secondo nodo. Quando arriva una richiesta, il primo nodo la elabora e invia i dati intermedi sulla rete al secondo nodo, che completa il calcolo.

    Per ulteriori linee guida sulla scelta di una strategia di inferenza distribuita per una replica di un singolo modello, consulta Parallelismo e scalabilità nella documentazione di vLLM.

  4. Seleziona un tipo di macchina ottimizzato per l'acceleratore: in base alla tua scelta di acceleratore e al numero che ti serve, seleziona un tipo di macchina che fornisca queste risorse. Ogni tipo di macchina offre una combinazione specifica di vCPU, memoria di sistema e larghezza di banda di rete, che può influire anche sulle prestazioni del tuo workload. Ad esempio, se hai bisogno di 16 GPU NVIDIA H100, seleziona il tipo di macchina a3-megagpu-16g.

  5. Esegui i tuoi benchmark: il rendimento del carico di lavoro di inferenza dipende in larga misura dal tuo caso d'uso specifico. Esegui i tuoi benchmark per convalidare le tue scelte e perfezionare la configurazione.

Ottimizza la configurazione del server di inferenza

Per ottenere prestazioni ottimali quando esegui il deployment del carico di lavoro di inferenza, ti consigliamo un ciclo di benchmarking e ottimizzazione:

  1. Inizia con la guida rapida all'inferenza GKE per ottenere una configurazione di base ottimizzata di Kubernetes per il tuo caso d'uso.
  2. Esegui benchmark per acquisire le metriche di throughput e latenza di base.
  3. Ottimizza la configurazione del server di inferenza.
  4. Esegui di nuovo i benchmark e confronta i risultati per convalidare le modifiche.

I seguenti consigli si basano sul server di inferenza vLLM, ma i principi si applicano anche ad altri server. Per indicazioni dettagliate su tutte le impostazioni disponibili, consulta la documentazione Ottimizzazione e messa a punto di vLLM:

  • Configura il parallelismo:
    • Parallelismo tensoriale (tensor_parallel_size): imposta questo valore sul numero di acceleratori su un singolo nodo per partizionare il workload. Ad esempio, l'impostazione tensor_parallel_size=4 distribuirà il carico di lavoro su quattro acceleratori. Tieni presente che l'aumento di questo valore può comportare un sovraccarico di sincronizzazione eccessivo.
    • Parallelismo della pipeline (pipeline_parallel_size): imposta questo valore sul numero di nodi su cui distribuire il modello. Ad esempio, se esegui il deployment su due nodi con otto acceleratori ciascuno, devi impostare tensor_parallel_size=8 e pipeline_parallel_size=2. L'aumento di questo valore può comportare penalità di latenza.
  • Ottimizza la cache KV (gpu_memory_utilization): questo parametro controlla la percentuale di memoria GPU riservata ai pesi del modello, alle attivazioni e alla cache KV. Un valore più alto aumenta le dimensioni della cache KV e può migliorare il throughput. Ti consigliamo di impostare un valore compreso tra 0.9 e 0.95. Se si verificano errori di memoria insufficiente (OOM), riduci questo valore.
  • Configura la lunghezza massima del contesto (max_model_len): per ridurre le dimensioni della cache KV e i requisiti di memoria, puoi impostare una lunghezza massima del contesto inferiore a quella predefinita del modello. In questo modo, puoi utilizzare GPU più piccole ed economiche. Ad esempio, se il tuo caso d'uso richiede solo un contesto di 40.000 token, ma il valore predefinito del modello è 256.000, l'impostazione di max_model_len su 40.000 libererà memoria per una cache KV più grande, il che potrebbe portare a una velocità effettiva maggiore.
  • Configura il numero di richieste simultanee (max_num_batched_tokens, max_num_seqs): ottimizza il numero massimo di richieste elaborate simultaneamente da vLLM per evitare il prerilascio quando la cache KV ha poco spazio. Valori inferiori per max_num_batched_tokens e max_num_seqs riducono i requisiti di memoria, mentre valori più elevati possono migliorare il throughput a rischio di errori di esaurimento della memoria. Per trovare i valori ottimali, ti consigliamo di eseguire esperimenti sul rendimento e osservare il numero di richieste di preemption nelle metriche Prometheus esportate da vLLM.

Per maggiori informazioni, consulta le seguenti risorse:

Ottimizza per latenza e disponibilità

Per garantire che il servizio di inferenza sia reattivo e affidabile, devi ottimizzare per una bassa latenza di avvio e un'elevata disponibilità di risorse.

Ottimizzare la latenza di avvio a freddo del carico di lavoro di inferenza

Ridurre al minimo il tempo necessario per l'avvio dei carichi di lavoro di inferenza è fondamentale sia per l'efficienza dei costi sia per l'esperienza utente. Una bassa latenza di avvio a freddo consente al cluster di scalare rapidamente per soddisfare la domanda, garantendo un servizio reattivo e riducendo al minimo la necessità di un provisioning eccessivo costoso.

Ottimizzare il tempo di avvio del pod

Il tempo necessario affinché un pod sia pronto è determinato in gran parte dal tempo necessario per estrarre l'immagine container e scaricare i pesi del modello. Per ottimizzare entrambi, prendi in considerazione le seguenti strategie:

  • Accelerare il caricamento del modello con un caricatore di dati ottimizzato: il metodo utilizzato per archiviare e caricare i pesi del modello ha un impatto significativo sul tempo di avvio. Per le versioni 0.10.2 e successive di vLLM, l'approccio consigliato è utilizzare Run:ai Model Streamer per caricare i modelli trasmettendoli in streaming direttamente da un bucket Cloud Storage.

    Se lo streamer non è disponibile per il tuo caso d'uso, puoi montare un bucket Cloud Storage utilizzando Cloud Storage FUSE e ottimizzarne le prestazioni attivando gli spazi dei nomi gerarchici e utilizzando tecniche come i download paralleli e il recupero anticipato. Per scoprire di più su queste tecniche, consulta Ottimizzare il driver CSI di Cloud Storage FUSE per il rendimento di GKE. In entrambi i casi, ti consigliamo di utilizzare Anywhere Cache per creare cache di lettura zonali ad alte prestazioni per i tuoi bucket e di attivare l'accesso uniforme a livello di bucket per controllare in modo uniforme l'accesso ai tuoi bucket.

    Se utilizzi già Managed Lustre per l'archiviazione di file ad alte prestazioni per i tuoi carichi di lavoro di addestramento, puoi utilizzarlo anche per caricare i pesi del modello per l'inferenza. Questo approccio offre un accesso a bassa latenza quando la località dei dati e la compatibilità POSIX sono fondamentali.

  • Abilita flusso immagine: per ridurre il tempo necessario per eseguire il pull delle immagini dei container, abilita flusso immagine sul tuo cluster GKE. Il flusso dell'immagine consente l'avvio dei container prima del download dell'intera immagine, il che può ridurre drasticamente il tempo di avvio del pod.

Abilita i nodi ad avvio rapido

Per i carichi di lavoro che richiedono uno scalabilità rapida, puoi sfruttare i nodi a avvio rapido in GKE. I nodi ad avvio rapido sono risorse hardware preinizializzate che hanno un tempo di avvio significativamente più breve rispetto ai nodi standard. Se il cluster soddisfa i requisiti, GKE attiva automaticamente i nodi a avvio rapido.

Pianificare la capacità e massimizzare l'ottenimento degli acceleratori

Gli acceleratori ad alta richiesta come GPU e TPU possono avere una disponibilità limitata, quindi una strategia di pianificazione della capacità proattiva è essenziale.

Pianificare e prenotare la capacità

Gli acceleratori ad alta richiesta potrebbero avere una disponibilità limitata, pertanto è essenziale una strategia di pianificazione proattiva della capacità. Per garantire l'accesso alle risorse di cui hai bisogno, segui questi consigli:

  • Determina la capacità di base e la gestione dei picchi: pianifica la capacità di base dell'acceleratore che devi prenotare. L'importo da riservare dipende dal tuo caso d'uso. Ad esempio, potresti prenotare il 100% della capacità richiesta per i carichi di lavoro critici senza tolleranza per i ritardi oppure potresti prenotare un determinato percentile (ad esempio il 90° o il 95°) e acquisire il resto on demand per gestire i picchi.

  • Prenota la capacità di base: per ottenere risorse con un elevato livello di garanzia, crea prenotazioni. Puoi scegliere un tipo di prenotazione in base alle tue esigenze. Ad esempio, per prenotare risorse ad alta richiesta come gli acceleratori per un periodo di tempo futuro specifico, puoi creare prenotazioni future in modalità calendario.

  • Orchestra la capacità per i picchi: per la domanda che supera le prenotazioni di base, puoi implementare una strategia di fallback utilizzando altri tipi di capacità, come on demand, VM spot o Dynamic Workload Scheduler (DWS). Puoi automatizzare questa strategia di fallback utilizzando le classi di calcolo personalizzate per definire un ordine di priorità per il provisioning di diversi tipi di capacità.

  • Accedi a prezzi scontati: per la capacità di base, acquista sconti per impegno di utilizzo (CUD) per ottenere prezzi molto scontati in cambio di un impegno di uno o tre anni.

Utilizza Dynamic Workload Scheduler con la modalità di provisioning con avvio flessibile se i tuoi workload tollerano ritardi nell'acquisizione della capacità

Per i carichi di lavoro che possono tollerare un certo ritardo nell'acquisizione della capacità, Dynamic Workload Scheduler (DWS) con modalità di provisioning con avvio flessibile è un'opzione per ottenere acceleratori a un prezzo scontato. DWS ti consente di mettere in coda le richieste di capacità per un massimo di sette giorni.

Quando utilizzi DWS con la modalità di provisioning con avvio flessibile, ti consigliamo quanto segue:

  • Incorporalo in una classe di computing personalizzata: utilizza una classe di computing personalizzata per definire DWS come parte di una strategia di fallback con priorità per l'acquisizione di capacità.
  • Imposta una durata massima di esecuzione: il parametro maxRunDurationSeconds imposta la durata massima di esecuzione per i nodi richiesti tramite DWS. Se imposti questo valore su un valore inferiore a quello predefinito di sette giorni, puoi aumentare le probabilità di ottenere i nodi richiesti.
  • Abilita il riciclo dei nodi: per evitare tempi di inattività per i tuoi carichi di lavoro, abilita il riciclo dei nodi. Questa funzionalità inizia il provisioning di un nuovo nodo prima della scadenza di quello precedente, garantendo una transizione più fluida.
  • Riduci al minimo le interruzioni: per ridurre al minimo le interruzioni dovute all'espulsione e agli upgrade dei nodi, configura periodi di manutenzione ed esclusioni, disattiva la riparazione automatica dei nodi e sfrutta la strategia di upgrade di breve durata.

Utilizzare le classi di computing personalizzate

Le classi di calcolo personalizzate (CCC) sono una funzionalità di GKE che ti consente di definire un elenco prioritario di configurazioni dell'infrastruttura per i tuoi workload. I CCC forniscono funzionalità chiave progettate per migliorare l'ottenimento degli acceleratori:

  • Priorità di calcolo di riserva: puoi definire un elenco prioritario di configurazioni. Se l'opzione preferita non è disponibile durante un evento di scale up, il gestore della scalabilità automatica esegue automaticamente il failover all'opzione successiva nell'elenco, aumentando significativamente la probabilità di acquisire capacità.
  • Migrazione attiva a nodi con priorità più alta: quando configuri questa funzionalità, GKE sostituisce automaticamente i nodi in esecuzione su configurazioni con priorità inferiore con nodi di configurazioni con priorità più alta non appena diventano disponibili. In questo modo, i tuoi pod vengono eseguiti sui nodi che preferisci di più (e spesso più convenienti).

Con le classi di calcolo personalizzate (CCC), puoi creare una strategia di fallback per l'acquisizione dei nodi. Questa strategia utilizza un elenco prioritario di diversi tipi di capacità, come VM on demand, VM spot o prenotazioni. Ciascuno di questi tipi di capacità ha un livello di disponibilità diverso:

  • Prenotazioni: offrono il massimo livello di garanzia per l'ottenimento della capacità. Quando utilizzi le prenotazioni con i CCC, tieni presente le relative limitazioni. Ad esempio, alcuni tipi di prenotazione limitano i tipi di macchina che puoi prenotare o il numero massimo di macchine che puoi richiedere.
  • On demand: il modello di provisioning standard, che offre flessibilità, ma potrebbe essere soggetto a vincoli di capacità regionali per le risorse ad alta domanda.
  • VM spot: utilizza la capacità di riserva a un prezzo inferiore, ma può essere prerilasciata. Quando si verifica un evento di prerilascio, GKE fornisce un periodo di terminazione normale fino a 30 secondi ai pod interessati secondo il criterio del "best effort". Per sfruttare questo vantaggio, rendi i tuoi workload tolleranti agli eventi di preempt implementando checkpoint e meccanismi di ripetizione.
  • Dynamic Workload Scheduler (DWS): consente di mettere in coda le richieste di risorse scarse a prezzi scontati. Questa funzionalità è ideale per i carichi di lavoro che possono tollerare ritardi nell'acquisizione della capacità.

L'ordine dell'elenco delle priorità deve cambiare a seconda che l'obiettivo principale sia ridurre al minimo la latenza o ottimizzare i costi. Ad esempio, puoi configurare i seguenti elenchi di priorità per diversi requisiti dei workload:

Priorità Workload a bassa latenza Workload ottimizzati per i costi (tolleranti alla latenza)
1 Prenotazioni (specifiche, poi qualsiasi) Prenotazioni (specifiche, poi qualsiasi)
2 On demand VM spot
3 VM spot Dynamic Workload Scheduler
4 Dynamic Workload Scheduler On demand

Per i casi d'uso a bassa latenza, la capacità on demand viene assegnata in ordine di priorità dopo le prenotazioni perché segnala rapidamente le carenze di capacità, consentendo al CCC di passare rapidamente all'opzione successiva.

Per i casi d'uso ottimizzati per i costi, le VM spot e DWS con avvio flessibile vengono assegnate la priorità dopo le prenotazioni per sfruttare i costi inferiori. La capacità on demand viene utilizzata come ultimo fallback.

Configura il criterio di località dei cluster GKE e dei pool di nodi

La policy di località del gestore della scalabilità automatica del cluster controlla il modo in cui GKE distribuisce i nodi tra le zone durante un evento di scale up. Questa impostazione è particolarmente importante quando utilizzi le classi di computing personalizzate, perché determina le zone che il gestore della scalabilità automatica del cluster prenderà in considerazione prima di applicare l'elenco di priorità della classe di computing personalizzata.

Per aumentare le probabilità di ottenere acceleratori, configura la policy di località in base ai requisiti del tuo workload:

  • location-policy=ANY: dà la priorità all'ottenimento della capacità rispetto al bilanciamento uniforme dei nodi tra le zone. Questa impostazione è particolarmente pertinente quando il tuo CCC include VM spot o tipi di macchine con disponibilità variabile, in quanto ANY consente a Cluster Autoscaler di scegliere la zona con la migliore probabilità di soddisfare i tipi di nodi con priorità del CCC. Utilizza questa impostazione anche per dare la priorità all'utilizzo delle prenotazioni inutilizzate. Quando utilizzi questo criterio, ti consigliamo di iniziare con num-nodes=0 per offrire a Cluster Autoscaler la massima flessibilità nella ricerca della capacità.

  • location-policy=BALANCED: tenta di distribuire i nodi in modo uniforme in tutte le zone disponibili. Utilizza questa norma quando i tuoi workload utilizzano risorse facilmente ottenibili e vuoi mantenere la ridondanza di zona per garantire un'alta disponibilità.

Puoi configurare questa impostazione quando crei o aggiorni un node pool.

Ottimizza per efficienza e costi

Monitorando attentamente gli acceleratori e scalando in modo intelligente i carichi di lavoro, puoi ridurre significativamente gli sprechi e abbassare i costi operativi.

Osserva gli acceleratori e i server di inferenza

Una strategia di osservabilità completa è essenziale per comprendere le prestazioni e l'utilizzo dei tuoi carichi di lavoro di inferenza. GKE fornisce una suite di strumenti per aiutarti a monitorare gli acceleratori e i server di inferenza:

  • Monitora le metriche DCGM per le GPU NVIDIA: per monitorare lo stato e le prestazioni delle GPU NVIDIA, configura GKE in modo che invii le metriche NVIDIA Data Center GPU Manager (DCGM) a Cloud Monitoring.
  • Abilita il monitoraggio automatico delle applicazioni: per semplificare il processo di monitoraggio dei server di inferenza, abilita il monitoraggio automatico delle applicazioni in GKE.
  • Instrumenta i tuoi carichi di lavoro con OpenTelemetry: per i carichi di lavoro non supportati dal monitoraggio automatico delle applicazioni, utilizza OpenTelemetry per raccogliere metriche e tracce personalizzate.

Scala automaticamente i pod

Per garantire che i tuoi workload di inferenza possano adattarsi dinamicamente alle variazioni della domanda, utilizza un Horizontal Pod Autoscaler (HPA) per scalare automaticamente il numero di pod. Per i carichi di lavoro di inferenza, è essenziale basare le decisioni di scalabilità su metriche che riflettono direttamente il carico sul server di inferenza, anziché su metriche standard di CPU o memoria.

Per configurare la scalabilità automatica per i carichi di lavoro di inferenza, ti consigliamo di:

  • Configura HPA in base a metriche sensibili all'inferenza: per prestazioni ottimali, configura HPA in modo che venga scalato in base alle metriche del server di inferenza. La metrica migliore dipende dal fatto che tu stia ottimizzando per una bassa latenza o un throughput elevato.

    • Per i carichi di lavoro sensibili alla latenza, hai due opzioni principali:

      • Utilizzo della cache KV (ad esempio, vllm:gpu_cache_usage_perc): questa metrica è spesso il miglior indicatore di picchi di latenza imminenti. Un utilizzo elevato della cache KV indica che il motore di inferenza si sta avvicinando alla capacità. L'HPA può utilizzare questo segnale per aggiungere in modo preventivo repliche e mantenere un'esperienza utente stabile.
      • Numero di richieste in esecuzione (dimensione batch) (ad esempio,vllm:num_requests_running): questa metrica è direttamente correlata alla latenza, in quanto batch di dimensioni inferiori in genere comportano una latenza inferiore. Tuttavia, utilizzarlo per la scalabilità automatica può essere difficile perché massimizzare la velocità effettiva dipende dalle dimensioni delle richieste in entrata. Potresti dover scegliere un valore inferiore alla dimensione batch massima possibile per assicurarti che HPA venga scalato correttamente.
    • Per i carichi di lavoro sensibili alla velocità effettiva, esegui lo scale in base alle dimensioni della coda (ad esempio, vllm:num_requests_waiting). Questa metrica misura direttamente il backlog di lavoro ed è un modo semplice per abbinare la capacità di elaborazione alla domanda in entrata. Poiché questa metrica considera solo le richieste in attesa e non quelle attualmente in elaborazione, potrebbe non raggiungere la latenza più bassa possibile rispetto allo scaling in base alle dimensioni del batch.

  • Imposta un numero minimo di repliche: per garantire una disponibilità coerente e un'esperienza utente di base, imposta sempre un numero minimo di repliche per il deployment di inferenza.

  • Abilita il profilo HPA per il rendimento: nelle versioni di GKE 1.33 o successive, il profilo HPA per il rendimento è abilitato per impostazione predefinita sui cluster idonei per migliorare il tempo di reazione di HPA.

Per saperne di più, consulta Configurare HPA per i workload LLM sulle GPU e Scalare automaticamente i workload di inferenza LLM sulle TPU.

Avvicinare i dati ai workload

Il tempo necessario ai tuoi workload per caricare i dati, come i pesi del modello, può essere una fonte significativa di latenza. Se sposti i dati più vicino alle risorse di calcolo, puoi ridurre i tempi di trasferimento dei dati e migliorare le prestazioni complessive.

  • Crea cache di lettura zonali con Anywhere Cache: se utilizzi Cloud Storage per archiviare i dati per i tuoi workload AI/ML, attiva Anywhere Cache. Anywhere Cache crea cache di lettura zonali ad alte prestazioni per i tuoi bucket Cloud Storage.
  • Memorizza nella cache i dati a cui si accede di frequente sugli SSD locali: per i workload che richiedono un accesso a latenza estremamente bassa ai dati temporanei, utilizza gli SSD locali come cache ad alte prestazioni. L'utilizzo di SSD locali come spazio di archiviazione temporaneo a bassa latenza per contenere i dati utilizzati di frequente consente di ridurre il tempo di inattività di risorse costose come gli acceleratori, riducendo drasticamente il tempo di attesa degli acceleratori per il completamento delle operazioni I/O. Tieni presente che non tutte le serie di macchine supportano le SSD locali, il che può influire sulla tua scelta di acceleratori.
  • Gestisci le cache con GKE Data Cache: per i carichi di lavoro che leggono spesso dati dai dischi permanenti, attiva GKE Data Cache. GKE Data Cache utilizza gli SSD locali per creare una cache gestita ad alte prestazioni per i tuoi dischi permanenti. Per la maggior parte dei carichi di lavoro di produzione, consigliamo di utilizzare la modalità Writethrough per evitare la perdita di dati scrivendo i dati in modo sincrono sia nella cache sia nel disco permanente sottostante.

Ottimizzare per architetture di scalabilità avanzate

Per soddisfare le esigenze di applicazioni su larga scala o distribuite a livello globale, puoi adottare architetture di scalabilità avanzate per migliorare le prestazioni, l'affidabilità e la gestione del traffico.

Bilancia il carico del traffico con GKE Inference Gateway

Per i carichi di lavoro di inferenza in un singolo cluster, ti consigliamo di utilizzare GKE Inference Gateway. Inference Gateway è un bilanciatore del carico basato sull'AI che monitora le metriche di inferenza per instradare le richieste all'endpoint più ottimale. Questa funzionalità migliora le prestazioni e l'utilizzo dell'acceleratore.

Quando utilizzi GKE Inference Gateway, ti consigliamo di seguire queste best practice:

  • Raggruppa i pod di pubblicazione in un InferencePool: definisci un InferencePool per ogni gruppo di pod che gestiscono i carichi di lavoro di inferenza. Per saperne di più, consulta Personalizzare la configurazione di GKE Inference Gateway.
  • Multiplex latency-critical workloads: definisci InferenceObjectives per specificare le proprietà di pubblicazione del modello, ad esempio nome e priorità. GKE Inference Gateway dà la precedenza ai carichi di lavoro con una priorità più elevata, consentendoti di multiplexare i carichi di lavoro sensibili alla latenza e tolleranti alla latenza e di implementare le policy di riduzione del carico durante il traffico intenso.
  • Utilizza il routing basato sul modello: per instradare le richieste in base al nome del modello nel corpo della richiesta, utilizza il routing basato sul corpo. Quando utilizzi il routing basato sul corpo, assicurati che i backend siano ad alta disponibilità. Il gateway restituirà un errore se l'estensione non è disponibile, impedendo l'instradamento errato delle richieste.
  • Consenti al gateway di distribuire automaticamente il traffico: GKE Inference Gateway instrada in modo intelligente il traffico monitorando le metriche chiave dei server di inferenza in InferencePool, come l'utilizzo della cache KV, la lunghezza della coda e gli indici della cache dei prefissi. Questo bilanciamento del carico in tempo reale ottimizza l'utilizzo dell'acceleratore, riduce la latenza finale e aumenta la velocità effettiva complessiva rispetto ai metodi tradizionali.
  • Integrazione con Apigee e Model Armor: per una maggiore sicurezza e gestione, esegui l'integrazione con Apigee per la gestione delle API e con Model Armor per i controlli di sicurezza.

Esegui il deployment dei carichi di lavoro di inferenza su più nodi

Per i modelli molto grandi che non possono essere contenuti in un singolo nodo, devi distribuire il workload di inferenza su più nodi. Ciò richiede un'architettura che riduca al minimo la latenza di comunicazione tra i nodi e garantisca che tutti i componenti del workload distribuito vengano gestiti come un'unica unità.

Tieni presente le seguenti best practice:

  • Massimizza la larghezza di banda e la velocità effettiva della rete dell'acceleratore: quando un carico di lavoro viene distribuito su più nodi, la rete diventa un fattore di prestazioni critico. Per ridurre al minimo la latenza di comunicazione tra i nodi, utilizza tecnologie di rete ad alte prestazioni come NVIDIA GPUDirect. A seconda delle dimensioni del cluster e dell'intensità della comunicazione richiesta dal carico di lavoro, puoi scegliere tra queste opzioni:

    • GPUDirect-TCPX: efficace per una serie di carichi di lavoro di inferenza multi-nodo in esecuzione su A3 High.
    • GPUDirect-TCPXO: offre prestazioni migliorate con maggiore offload e larghezza di banda più elevata, il che è vantaggioso per i cluster più grandi rispetto a TCPX standard e viene eseguito sulle macchine A3 Mega.
    • GPUDirect RDMA: fornisce la larghezza di banda tra nodi più elevata e la latenza più bassa consentendo l'accesso diretto alla memoria tra le GPU su nodi diversi, bypassando la CPU. È ideale per gli scenari di inferenza su larga scala più esigenti su macchine A3 Ultra e A4.

    Per saperne di più, vedi:

    Per verificare che la configurazione di rete multi-nodo funzioni come previsto, ti consigliamo di eseguire test con strumenti come la NVIDIA Collective Communications Library (NCCL).

  • Utilizza LeaderWorkerSet per gestire i workload distribuiti: quando esegui il deployment di un workload distribuito stateful, ad esempio un servizio di inferenza multi-nodo, è essenziale gestire tutti i suoi componenti come un'unica unità. Per farlo, utilizza LeaderWorkerSet, un'API nativa di Kubernetes che ti consente di gestire un gruppo di pod correlati come una singola entità. Un LeaderWorkerSet garantisce che tutti i pod del set vengano creati ed eliminati insieme, il che è fondamentale per mantenere l'integrità di un carico di lavoro distribuito.

  • Posiziona i nodi in prossimità fisica utilizzando il posizionamento compatto: la distanza fisica tra i nodi nel carico di lavoro distribuito può avere un impatto significativo sulla latenza di rete tra i nodi. Per ridurre al minimo questa latenza, utilizza una policy di posizionamento compatto per i tuoi pool di nodi GKE. Una policy di posizionamento compatto indica a GKE di posizionare i nodi in un pool di nodi il più vicino possibile tra loro all'interno di una zona.

Esegui il deployment dei workload di inferenza in più regioni

Per le applicazioni distribuite a livello globale che richiedono alta disponibilità e bassa latenza, il deployment dei carichi di lavoro di inferenza in più regioni è una best practice fondamentale. Un'architettura multiregionale può aiutarti ad aumentare l'affidabilità, migliorare l'ottenibilità degli acceleratori, ridurre la latenza percepita dagli utenti e soddisfare i requisiti normativi specifici per la località.

Per eseguire il deployment e gestire in modo efficace un servizio di inferenza multiregionale, segui questi suggerimenti:

  • Esegui il provisioning dei cluster GKE in più regioni in cui hai capacità riservata o prevedi di averne bisogno per gestire i picchi di carico.
  • Scegli la strategia di archiviazione giusta per i pesi del modello. Per ottimizzare l'efficienza operativa, crea un bucket Cloud Storage multiregionale. Per ottimizzare i costi, crea un bucket regionale in ogni regione e replica i pesi del modello.
  • Utilizza Anywhere Cache per creare cache di lettura zonali per i bucket Cloud Storage per ridurre sia la latenza di rete sia i costi di traffico in uscita dei dati.

Riepilogo delle best practice

La tabella seguente riepiloga le best practice consigliate in questo documento:

Argomento Attività
Deployment e configurazione
  • Analizza le caratteristiche del tuo caso d'uso di inferenza
  • Scegliere i modelli giusti per i tuoi casi d'uso di inferenza
  • Applica la quantizzazione al modello
  • Scegliere gli acceleratori giusti
  • Scegli la strategia di distribuzione delle inferenze
  • Ottimizza la configurazione del server di inferenza
Latenza di avvio a freddo
  • Ottimizzare il tempo di avvio del pod
  • Abilita nodi ad avvio rapido
Pianificazione della capacità e ottenimento dell'acceleratore
  • Pianificare e prenotare la capacità
  • Utilizzare Dynamic Workload Scheduler
  • Utilizzare le classi di computing personalizzate
  • Configura il criterio di località dei cluster GKE e dei pool di nodi
Efficienza delle risorse e degli acceleratori
  • Osserva gli acceleratori e i server di inferenza
  • Scala automaticamente i pod
  • Avvicinare i dati ai workload
Bilanciamento del carico
  • Utilizza GKE Inference Gateway per i deployment in un singolo cluster
Deployment multi-nodo
  • Massimizzare la larghezza di banda e la velocità effettiva della rete dell'acceleratore
  • Utilizzare LeaderWorkerSet per raggruppare i pod
  • Posiziona i nodi in prossimità fisica utilizzando il posizionamento compatto
Deployment multiregionali
  • Esegui il provisioning dei cluster GKE in più regioni
  • Bilancia il traffico tra le regioni
  • Archivia i pesi del modello nei bucket Cloud Storage
  • Memorizzazione nella cache dei dati con Anywhere Cache

Passaggi successivi