Introduzione alle TPU in GKE
Ora i clienti di Google Kubernetes Engine (GKE) possono creare pool di nodi Kubernetes contenenti slice TPU v4 e v5e. Per maggiori informazioni sulle TPU, consulta la sezione Architettura del sistema.
Quando utilizzi GKE, devi prima creare un cluster GKE. Poi aggiungi pool di nodi al tuo cluster. I pool di nodi GKE sono raccolte di VM che condividono gli stessi attributi. Per i carichi di lavoro TPU, i pool di nodi sono costituiti da VM TPU.
Tipi di node pool
GKE supporta due tipi di pool di nodi TPU:
Node pool di sezioni TPU multi-host
Un node pool di sezioni TPU multi-host è un pool di nodi contenente due o più VM TPU interconnesse. A ogni VM è collegato un dispositivo TPU. Le TPU in un
scatto multi-host sono collegate tramite un'interconnessione ad alta velocità (ICI). Una volta creato un
pool di nodi di slice multi-host, non puoi aggiungere nodi. Ad esempio,
non puoi creare un pool di nodi v4-32
e poi aggiungere un altro nodo Kubernetes (VM TPU) al pool di nodi. Per aggiungere un altro slice TPU a un
cluster GKE, devi creare un nuovo pool di nodi.
Gli host in un pool di nodi di sezione TPU multi-host vengono trattati come un'unica unità atomica. Se GKE non è in grado di eseguire il deployment di un nodo nella sezione, non verrà eseguito il deployment di nessun nodo nella sezione.
Se un nodo all'interno di una sezione TPU multi-host deve essere riparato, GKE chiuderà tutte le VM TPU nella sezione, costringendo all'espulsione tutti i pod Kubernetes nel workload. Una volta che tutte le VM TPU del segmento sono attive e in esecuzione, i pod Kubernetes possono essere pianificati sulle VM TPU del nuovo segmento.
Il seguente diagramma mostra un esempio di un seme TPU v5litepod-16 (v5e) con più host. Questa sezione ha quattro VM TPU. Ogni VM TPU ha quattro chip TPU v5e collegati con interconnessioni ad alta velocità (ICI) e ogni chip TPU v5e ha un Tensor Core.
Il seguente diagramma mostra un cluster GKE contenente un
sezione TPU v5litepod-16
(v5e) (topologia: 4x4) e un'altra sezione TPU v5litepod-8
(v5e)
(topologia: 2x4):
Per un esempio di esecuzione di un carico di lavoro su una sezione TPU multi-host, consulta Eseguire il carico di lavoro sulle TPU.
Pool di nodi di sezioni TPU a host singolo
Un pool di nodi con sezione a singolo host è un pool di nodi contenente una o più VM TPU indipendenti. A ogni VM è collegato un dispositivo TPU. Sebbene le VM all'interno di un pool di nodi di slice con un solo host possano comunicare tramite la rete del data center (DCN), le TPU collegate alle VM non sono interconnesse.
Il seguente diagramma mostra un esempio di uno slice TPU con un solo host con sette macchine v4-8
:
Per un esempio di esecuzione di un carico di lavoro su uno slice TPU a host singolo, consulta Eseguire il carico di lavoro sulle TPU.
Tipi di macchine TPU per i pool di nodi GKE
Prima di creare i pool di nodi, devi scegliere la versione e le dimensioni della sezione TPU richieste dal tuo carico di lavoro. TPU v4 è supportata in GKE
versione Standard 1.26.1-gke.1500
e successive, v5e in GKE
versione Standard 1.27.2-gke.2100
e successive e v5p in
GKE versione Standard 1.28.3-gke.1024000
e successive.
TPU v4, v5e e v5p sono supportate in GKE Autopilot
versione 1.29.2-gke.1521000
e successive.
Per ulteriori informazioni sulle specifiche hardware delle diverse versioni di TPU, consulta Architettura di sistema. Quando crei un pool di nodi TPU, seleziona una dimensione della sezione TPU (una topologia TPU) in base alle dimensioni del tuo modello e alla quantità di memoria richiesta. Il tipo di macchina specificato quando crei i pool di nodi dipende dalla versione e dalle dimensioni dei tuoi slice.
v5e
Di seguito sono riportati i tipi di macchine e le topologie TPU v5e supportati per i casi d'uso di addestramento e inferenza:
Tipo di macchina | Topologia | Numero di chip TPU | Numero di VM | Caso d'uso consigliato |
---|---|---|---|---|
ct5lp-hightpu-1t |
1x1 | 1 | 1 | Addestramento, inferenza su un singolo host |
ct5lp-hightpu-4t |
2x2 | 4 | 1 | Addestramento, inferenza su un singolo host |
ct5lp-hightpu-8t |
2x4 | 8 | 1 | Addestramento, inferenza su un singolo host |
ct5lp-hightpu-4t |
2x4 | 8 | 2 | Addestramento, inferenza multi-host |
ct5lp-hightpu-4t |
4x4 | 16 | 4 | Addestramento su larga scala, inferenza multi-host |
ct5lp-hightpu-4t |
4x8 | 32 | 8 | Addestramento su larga scala, inferenza multi-host |
ct5lp-hightpu-4t |
8x8 | 64 | 16 | Addestramento su larga scala, inferenza multi-host |
ct5lp-hightpu-4t |
8x16 | 128 | 32 | Addestramento su larga scala, inferenza multi-host |
ct5lp-hightpu-4t |
16x16 | 256 | 64 | Addestramento su larga scala, inferenza multi-host |
Cloud TPU v5e è un prodotto combinato di addestramento e inferenza. I job di addestramento sono ottimizzati per la velocità in transito e la disponibilità, mentre i job di inferenza sono ottimizzati per la latenza. Per ulteriori informazioni, consulta Tipi di acceleratori di addestramento v5e e Tipi di acceleratori di inferenza v5e.
Le macchine TPU v5e sono disponibili in us-west4-a
, us-east5-b
e us-east1-c
.
I cluster GKE Standard devono eseguire il piano di controllo
versione 1.27.2-gke.2100 o successive. GKE Autopilot deve eseguire la versione del piano di controllo 1.29.2-gke.1521000 o successive. Per ulteriori informazioni su v5e, consulta Addestramento per Cloud TPU v5e.
Confronto dei tipi di macchine:
Tipo di macchina | ct5lp-hightpu-1t | ct5lp-hightpu-4t | ct5lp-hightpu-8t |
---|---|---|---|
Numero di chip v5e | 1 | 4 | 8 |
Numero di vCPU | 24 | 112 | 224 |
RAM (GB) | 48 | 192 | 384 |
Numero di nodi NUMA | 1 | 1 | 2 |
Probabilità di prerilascio | Alta | Medie | Bassa |
Per fare spazio alle VM con più chip, lo scheduler GKE può prelevare e riprogrammare le VM con meno chip. Pertanto, le VM con 8 chip hanno maggiori probabilità di prelevare le VM con 1 e 4 chip.
v4 e v5p
Di seguito sono riportati i tipi di macchine TPU v4 e v5p:
Tipo di macchina | Numero di vCPU | Memoria (GB) | Numero di nodi NUMA |
---|---|---|---|
ct4p-hightpu-4t |
240 | 407 | 2 |
ct5p-hightpu-4t |
208 | 448 | 2 |
Quando crei una sezione TPU v4, utilizza il tipo di macchina ct4p-hightpu-4t
che ha un host e contiene 4 chip. Per ulteriori informazioni, consulta le topologie v4 e l'architettura del sistema TPU. I tipi di macchine TPU v4 sono disponibili in us-central2-b
. I
cluster GKE Standard devono eseguire il piano di controllo
nella versione 1.26.1-gke.1500
o successive. I cluster GKE Autopilot devono eseguire la versione del piano di controllo 1.29.2-gke.1521000
o successiva.
Quando crei una sezione TPU v5p, utilizza il tipo di macchina ct5p-hightpu-4t
che ha un host e contiene 4 chip. I tipi di macchine con sezioni TPU v5p sono disponibili in
us-west4-a
e us-east5-a
. I cluster GKE Standard devono eseguire la versione 1.28.3-gke.1024000
o successive del control plane.
GKE Autopilot deve essere eseguito su 1.29.2-gke.1521000
o versioni successive. Per ulteriori informazioni sulla versione 5p, consulta l'introduzione alla formazione sulla versione 5p.
Problemi noti e limitazioni
- Numero massimo di pod Kubernetes: puoi eseguire un massimo di 256 pod Kubernetes in una singola VM TPU.
- Solo prenotazioni SPECIFICHE: quando utilizzi le TPU in GKE,
SPECIFIC
è l'unico valore supportato per il flag--reservation-affinity
del comandogcloud container node-pools create
. - È supportata solo la variante VM spot delle TPU prerilasciabili: le VM spot sono simili alle VM prerilasciabili e sono soggette alle stesse limitazioni di disponibilità, ma non hanno una durata massima di 24 ore.
- Nessun supporto per l'allocazione dei costi: l'allocazione dei costi di GKE e la misurazione dell'utilizzo non includono dati sull'utilizzo o sui costi delle TPU.
- Il gestore della scalabilità automatica potrebbe calcolare la capacità: il gestore della scalabilità automatica del cluster potrebbe calcolare scorrettamente la capacità per i nuovi nodi contenenti VM TPU prima che questi nodi siano disponibili. Il gestore della scalabilità automatica dei cluster potrebbe quindi eseguire un ulteriore scale up e, di conseguenza, creare più nodi del necessario. Il gestore della scalabilità automatica del cluster eseguirà fare lo scale down di altri nodi, se non sono necessari, dopo l'operazione di fare lo scale down regolare.
- Il gestore della scalabilità automatica annulla lo scale up: il gestore della scalabilità automatica del cluster annulla lo scale up dei pool di nodi TPU che rimangono in stato di attesa per più di 10 ore. Il gestore della scalabilità automatica dei cluster riproverà queste operazioni di ridimensionamento in un secondo momento. Questo comportamento potrebbe ridurre la disponibilità delle TPU per i clienti che non utilizzano le prenotazioni.
- L'alterazione potrebbe impedire il ridimensionamento verso il basso: i carichi di lavoro non TPU che hanno una tolleranza per l'alterazione TPU potrebbero impedire fare lo scale down verso il basso del pool di nodi se vengono ricreati durante lo svuotamento del pool di nodi TPU.
Assicurati quote TPU e GKE sufficienti
Potresti dover aumentare determinate quote relative a GKE nelle regioni in cui vengono create le risorse.
Le seguenti quote hanno valori predefiniti che probabilmente dovranno essere aumentati:
- Quota SSD (GB) di Persistent Disk: il disco di avvio di ogni nodo Kubernetes richiede 100 GB per impostazione predefinita. Pertanto, questa quota deve essere impostata su un valore almeno pari a (il numero massimo di nodi GKE che prevedi di creare) * 100 GB.
- Quota indirizzi IP in uso: ogni nodo Kubernetes utilizza un indirizzo IP. Pertanto, questa quota deve essere impostata almeno sul numero massimo di nodi GKE che prevedi di creare.
Per richiedere un aumento della quota, vedi Richiedere una quota superiore. Per saperne di più sui tipi di quote TPU, consulta Quota TPU.
Potrebbero essere necessari alcuni giorni prima che le richieste di aumento della quota vengano approvate. Se hai difficoltà ad approvare le richieste di aumento della quota entro qualche giorno, contatta il team dell'Account Google.
Esegui la migrazione della prenotazione TPU
Se non prevedi di utilizzare una prenotazione TPU esistente con TPU in GKE, salta questa sezione e vai a Creare un cluster Google Kubernetes Engine.
Per utilizzare le TPU riservate con GKE, devi prima eseguire la migrazione della prenotazione TPU a un nuovo sistema di prenotazione basato su Compute Engine.
Esistono diversi aspetti importanti da conoscere in merito a questa migrazione:
- La capacità TPU di cui è stata eseguita la migrazione al nuovo sistema di prenotazione basato su Compute Engine non può essere utilizzata con l'API Resource Queued di Cloud TPU. Se intendi utilizzare le risorse in coda TPU con la tua prenotazione, dovrai eseguire la migrazione di una parte della prenotazione TPU al nuovo sistema di prenotazione basato su Compute Engine.
- Nessun carico di lavoro può essere in esecuzione sulle TPU quando viene eseguita la migrazione al nuovo sistema di prenotazione basato su Compute Engine.
- Seleziona un orario per eseguire la migrazione e collabora con il team dedicato all'account Google Cloud per pianificarla. Il periodo di tempo per la migrazione deve essere scelto durante l'orario lavorativo (dal lunedì al venerdì, dalle 09:00 alle 17:00 PST).
Crea un cluster Google Kubernetes Engine
Consulta la sezione Creare un cluster nella documentazione di Google Kubernetes Engine.
Crea un pool di nodi TPU
Consulta Creare un pool di nodi nella documentazione di Google Kubernetes Engine.
Esecuzione senza modalità con privilegi
Se vuoi ridurre l'ambito delle autorizzazioni nel contenitore, consulta la modalità privilegio TPU.
Esegui i carichi di lavoro nei pool di nodi TPU
Consulta Eseguire i workload GKE su TPU nella documentazione di Google Kubernetes Engine.
Selettori di nodi
Affinché Kubernetes possa pianificare il carico di lavoro sui nodi contenenti VM TPU, devi specificare due selettori per ogni carico di lavoro nel manifest di Google Kubernetes Engine:
- Imposta
cloud.google.com/gke-accelerator-type
sutpu-v5-lite-podslice
,tpu-v5p-slice
otpu-v4-podslice
. - Imposta
cloud.google.com/gke-tpu-topology
sulla topologia TPU del nodo.
Le sezioni Carichi di lavoro di addestramento e Carichi di lavoro di inferenza contengono manifest di esempio che illustrano l'utilizzo di questi selettori di nodi.
Considerazioni sulla pianificazione dei carichi di lavoro
Le TPU hanno caratteristiche uniche che richiedono una pianificazione e una gestione speciale dei carichi di lavoro in Kubernetes. Per saperne di più, consulta la sezione Considerazioni sulla pianificazione dei workload nella documentazione di GKE.
Riparazione dei nodi
Se un nodo in un pool di nodi di sezioni TPU multi-host non è in stato di esecuzione, GKE ricrea l'intero pool di nodi. Per ulteriori informazioni, consulta Riparazione automatica dei nodi nella documentazione di GKE.
Multislice: oltre un singolo livello
Puoi aggregare più slice in un multislice per gestire carichi di lavoro di addestramento più grandi. Per ulteriori informazioni, consulta Cloud TPU Multislice.
Tutorial sui carichi di lavoro di addestramento
Questi tutorial si concentrano sui carichi di lavoro di addestramento su uno slice TPU multi-host (ad esempio quattro macchine v5e). Sono coperti i seguenti modelli:
- Modelli FLAX di Hugging Face: addestramento di Diffusion su Pokémon
- PyTorch/XLA: GPT2 su WikiText
Scaricare le risorse dei tutorial
Scarica gli script Python e le specifiche YAML del tutorial per ogni modello preaddestrato con il seguente comando:
git clone https://github.com/GoogleCloudPlatform/ai-on-gke.git
Creare e connettersi al cluster
Crea un cluster GKE regionale in modo che il piano di controllo Kubernetes venga replicato in tre zone, garantendo una maggiore disponibilità.
Crea il tuo cluster in us-west4
, us-east1
o us-central2
a seconda della versione di TPU in uso. Per saperne di più su TPU e zone, consulta
Regioni e zone di Cloud TPU.
Il comando seguente crea un nuovo cluster GKE regionale abbonato al canale di rilascio rapido con un pool di nodi che contiene inizialmente un nodo per zona. Il comando abilita anche le funzionalità di Workload Identity Federation per GKE e del driver CSI di Cloud Storage FUSE nel cluster perché i workload di inferenza di esempio in questa guida utilizzano i bucket Cloud Storage per archiviare i modelli preaddestrati.
gcloud container clusters create cluster-name \ --region your-region \ --release-channel rapid \ --num-nodes=1 \ --workload-pool=project-id.svc.id.goog \ --addons GcsFuseCsiDriver
Per abilitare le funzionalità di Workload Identity Federation per GKE e del driver CSI di Cloud Storage FUSE per i cluster esistenti, esegui il seguente comando:
gcloud container clusters update cluster-name \ --region your-region \ --update-addons GcsFuseCsiDriver=ENABLED \ --workload-pool=project-id.svc.id.goog
I carichi di lavoro di esempio sono configurati con le seguenti ipotesi:
- il pool di nodi utilizza
tpu-topology=4x4
con quattro nodi - il pool di nodi utilizza
machine-type
ct5lp-hightpu-4t
Esegui il seguente comando per connetterti al cluster appena creato:
gcloud container clusters get-credentials cluster-name \ --location=cluster-region
Modelli FLAX Hugging Face: addestrare la diffusione su Pokémon
Questo esempio addestra il modello di diffusione stabile di HuggingFace utilizzando il set di dati Pokémon.
Il modello di diffusione stabile è un modello di testo a immagine latente che genera immagini fotorealistiche da qualsiasi input di testo. Per ulteriori informazioni su Stable Diffusion, consulta:
Crea immagine Docker
Il Dockerfile si trova nella cartellaai-on-gke/tutorials-and-examples/tpu-examples/training/diffusion/
.
Prima di eseguire il seguente comando, assicurati che il tuo account disponga delle autorizzazioni adeguate per consentire a Docker di eseguire il push nel repository.
Crea ed esegui il push dell'immagine Docker:
cd ai-on-gke/tutorials-and-examples/tpu-examples/training/diffusion/ docker build -t gcr.io/project-id/diffusion:latest . docker push gcr.io/project-id/diffusion:latest
Esegui il deployment del workload
Crea un file con i seguenti contenuti e assegnagli il nome tpu_job_diffusion.yaml
.
Compila il campo dell'immagine con l'immagine appena creata.
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
clusterIP: None
selector:
job-name: tpu-job-diffusion
---
apiVersion: batch/v1
kind: Job
metadata:
name: tpu-job-diffusion
spec:
backoffLimit: 0
# Completions and parallelism should be the number of chips divided by 4.
# (e.g. 4 for a v5litepod-16)
completions: 4
parallelism: 4
completionMode: Indexed
template:
spec:
subdomain: headless-svc
restartPolicy: Never
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
cloud.google.com/gke-tpu-topology: 4x4
containers:
- name: tpu-job-diffusion
image: gcr.io/${project-id}/diffusion:latest
ports:
- containerPort: 8471 # Default port using which TPU VMs communicate
- containerPort: 8431 # Port to export TPU usage metrics, if supported
command:
- bash
- -c
- |
cd examples/text_to_image
python3 train_text_to_image_flax.py --pretrained_model_name_or_path=duongna/stable-diffusion-v1-4-flax --dataset_name=lambdalabs/pokemon-blip-captions --resolution=128 --center_crop --random_flip --train_batch_size=4 --mixed_precision=fp16 --max_train_steps=1500 --learning_rate=1e-05 --max_grad_norm=1 --output_dir=sd-pokemon-model
resources:
requests:
google.com/tpu: 4
limits:
google.com/tpu: 4
Quindi esegui il deployment utilizzando:
kubectl apply -f tpu_job_diffusion.yaml
Pulizia
Al termine dell'esecuzione del job, puoi eliminarlo utilizzando:
kubectl delete -f tpu_job_diffusion.yaml
PyTorch/XLA: GPT2 su WikiText
Questo tutorial mostra come eseguire GPT2 su TPU v5e utilizzando HuggingFace su PyTorch/XLA utilizzando il set di dati wikitext.
Crea immagine Docker
Il Dockerfile si trova nella cartella ai-on-gke/tutorials-and-examples/tpu-examples/training/gpt/
.
Prima di eseguire il seguente comando, assicurati che il tuo account disponga delle autorizzazioni adeguate per consentire a Docker di eseguire il push nel repository.
Crea ed esegui il push dell'immagine Docker:
cd ai-on-gke/tutorials-and-examples/tpu-examples/training/gpt/ docker build -t gcr.io/project-id/gpt:latest . docker push gcr.io/project-id/gpt:latest
Esegui il deployment del workload
Copia il seguente codice YAML e salvalo in un file denominato tpu_job_gpt.yaml
. Compila il campo dell'immagine con l'immagine appena creata.
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
clusterIP: None
selector:
job-name: tpu-job-gpt
---
apiVersion: batch/v1
kind: Job
metadata:
name: tpu-job-gpt
spec:
backoffLimit: 0
# Completions and parallelism should be the number of chips divided by 4.
# (for example, 4 for a v5litepod-16)
completions: 4
parallelism: 4
completionMode: Indexed
template:
spec:
subdomain: headless-svc
restartPolicy: Never
volumes:
# Increase size of tmpfs /dev/shm to avoid OOM.
- name: shm
emptyDir:
medium: Memory
# consider adding `sizeLimit: XGi` depending on needs
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
cloud.google.com/gke-tpu-topology: 4x4
containers:
- name: tpu-job-gpt
image: gcr.io/$(project-id)/gpt:latest
ports:
- containerPort: 8479
- containerPort: 8478
- containerPort: 8477
- containerPort: 8476
- containerPort: 8431 # Port to export TPU usage metrics, if supported.
env:
- name: PJRT_DEVICE
value: 'TPU'
- name: XLA_USE_BF16
value: '1'
command:
- bash
- -c
- |
numactl --cpunodebind=0 python3 -u examples/pytorch/xla_spawn.py --num_cores 4 examples/pytorch/language-modeling/run_clm.py --num_train_epochs 3 --dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 --per_device_train_batch_size 16 --per_device_eval_batch_size 16 --do_train --do_eval --output_dir /tmp/test-clm --overwrite_output_dir --config_name my_config_2.json --cache_dir /tmp --tokenizer_name gpt2 --block_size 1024 --optim adafactor --adafactor true --save_strategy no --logging_strategy no --fsdp "full_shard" --fsdp_config fsdp_config.json
volumeMounts:
- mountPath: /dev/shm
name: shm
resources:
requests:
google.com/tpu: 4
limits:
google.com/tpu: 4
Esegui il deployment del flusso di lavoro utilizzando:
kubectl apply -f tpu_job_gpt.yaml
Pulizia
Al termine dell'esecuzione del job, puoi eliminarlo utilizzando:
kubectl delete -f tpu_job_gpt.yaml
Tutorial: carichi di lavoro di inferenza su un singolo host
Questo tutorial mostra come eseguire un workload di inferenza a host singolo su GKE v5 e TPU per i modelli preaddestrati con JAX, TensorFlow e PyTorch. A livello generale, sono previsti quattro passaggi distinti da eseguire sul cluster GKE:
Crea un bucket Cloud Storage e configura l'accesso al bucket. Utilizzi un bucket Cloud Storage per archiviare il modello preaddestrato.
Scarica e converti un modello preaddestrato in un modello compatibile con TPU. Applica un pod Kubernetes che scarica il modello preaddestrato, utilizza il convertitore Cloud TPU e archivia i modelli convertiti in un bucket Cloud Storage utilizzando il driver CSI di Cloud Storage FUSE. Il convertitore Cloud TPU non richiede hardware specializzato. Questo tutorial mostra come scaricare il modello ed eseguire il convertitore Cloud TPU nel pool di nodi CPU.
Avvia il server per il modello convertito. Applica un deployment che gestisce il modello utilizzando un framework di server basato sul volume archiviato nel volume permanente ReadOnlyMany (ROX). Le repliche del deployment devono essere eseguite in un pool di nodi di slice v5e con un pod Kubernetes per nodo.
Esegui il deployment di un bilanciatore del carico per testare il server del modello. Il server è esposto alle richieste esterne utilizzando il servizio LoadBalancer. È stato fornito uno script Python con una richiesta di esempio per testare il server del modello.
Il seguente diagramma mostra come le richieste vengono indirizzate dal bilanciatore del carico.
Esempi di deployment del server
Questi carichi di lavoro di esempio sono configurati con le seguenti ipotesi:
- Il cluster è in esecuzione con un pool di nodi TPU v5 con 3 nodi
- Il pool di nodi utilizza il tipo di macchina
ct5lp-hightpu-1t
, dove:- la topologia è 1x1
- il numero di chip TPU è 1
Il seguente manifest GKE definisce un singolo deployment del server di hosting.
apiVersion: apps/v1
kind: Deployment
metadata:
name: bert-deployment
spec:
selector:
matchLabels:
app: tf-bert-server
replicas: 3 # number of nodes in node pool
template:
metadata:
annotations:
gke-gcsfuse/volumes: "true"
labels:
app: tf-bert-server
spec:
nodeSelector:
cloud.google.com/gke-tpu-topology: 1x1 # target topology
cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice # target version
containers:
- name: serve-bert
image: us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
env:
- name: MODEL_NAME
value: "bert"
volumeMounts:
- mountPath: "/models/"
name: bert-external-storage
ports:
- containerPort: 8500
- containerPort: 8501
- containerPort: 8431 # Port to export TPU usage metrics, if supported.
resources:
requests:
google.com/tpu: 1 # TPU chip request
limits:
google.com/tpu: 1 # TPU chip request
volumes:
- name: bert-external-storage
persistentVolumeClaim:
claimName: external-storage-pvc
Se utilizzi un numero diverso di nodi nel pool di nodi TPU, modifica il campo replicas
in base al numero di nodi.
Se il cluster standard esegue la versione GKE 1.27 o precedente, aggiungi il seguente campo al manifest:
spec:
securityContext:
privileged: true
Non è necessario eseguire i pod Kubernetes in modalità privilegiata in GKE versione 1.28 o successive. Per maggiori dettagli, vedi Eseguire i contenitori senza modalità privilegiata.
Se utilizzi un tipo di macchina diverso:
- Imposta
cloud.google.com/gke-tpu-topology
sulla topologia per il tipo di macchina in uso. - Imposta entrambi i campi
google.com/tpu
inresources
in modo che corrispondano al numero di chip per il tipo di macchina corrispondente.
Configurazione
Scarica gli script Python e i manifest YAML del tutorial utilizzando il seguente comando:
git clone https://github.com/GoogleCloudPlatform/ai-on-gke.git
Vai alla directory single-host-inference
:
cd ai-on-gke/gke-tpu-examples/single-host-inference/
Configura l'ambiente Python
Gli script Python utilizzati in questo tutorial richiedono la versione 3.9 o successive di Python.
Ricordati di installare il requirements.txt
per ogni tutorial prima di eseguire gli script di test di Python.
Se non hai configurato Python correttamente nel tuo ambiente locale, puoi utilizzare Cloud Shell per scaricare ed eseguire gli script Python in questo tutorial.
Configura il cluster
Crea un cluster utilizzando il tipo di macchina
e2-standard-4
.gcloud container clusters create cluster-name \ --region your-region \ --release-channel rapid \ --num-nodes=1 \ --machine-type=e2-standard-4 \ --workload-pool=project-id.svc.id.goog \ --addons GcsFuseCsiDriver
I carichi di lavoro di esempio presuppongono quanto segue:
- Il cluster è in esecuzione con un pool di nodi TPU v5e con 3 nodi.
- Il pool di nodi TPU utilizza il tipo di macchina
ct5lp-hightpu-1t
.
Se utilizzi una configurazione del cluster diversa da quella descritta in precedenza, dovrai modificare il manifesto di deployment del server.
Per la demo di JAX Stable Diffusion, è necessario un pool di nodi CPU con un tipo di macchina con oltre 16 Gi di memoria disponibile (ad esempio e2-standard-4
).
Questo viene configurato nel comando gcloud container clusters create
o aggiungendo un altro pool di nodi al cluster esistente con il seguente
comando:
gcloud beta container node-pools create your-pool-name \ --zone=your-cluster-zone \ --cluster=your-cluster-name \ --machine-type=e2-standard-4 \ --num-nodes=1
Sostituisci quanto segue:
your-pool-name
: il nome del pool di nodi da creare.your-cluster-zone
: la zona in cui è stato creato il cluster.your-cluster-name
: il nome del cluster in cui aggiungere il pool di nodi.your-machine-type
: il tipo di macchina dei nodi da creare nel pool di nodi.
Configurare lo spazio di archiviazione del modello
Esistono diversi modi per archiviare il modello per la pubblicazione. In questo tutorial, utilizzeremo il seguente approccio:
- Per convertire il modello preaddestrato in modo che funzioni sulle TPU, utilizzeremo un Virtual Private Cloud basato su Persistent Disk con accesso
ReadWriteMany
(RWX). - Per pubblicare il modello su più TPU mono-host, utilizzeremo la stessa VPC supportata dal bucket Cloud Storage.
Esegui il seguente comando per creare un bucket Cloud Storage.
gcloud storage buckets create gs://your-bucket-name \ --project=your-bucket-project-id \ --location=your-bucket-location
Sostituisci quanto segue:
your-bucket-name
: il nome del bucket Cloud Storage.your-bucket-project-id
: l'ID del progetto in cui hai creato il bucket Cloud Storage.your-bucket-location
: la posizione del tuo bucket Cloud Storage. Per migliorare le prestazioni, specifica la località in cui è in esecuzione il tuo cluster GKE.
Per concedere al tuo cluster GKE l'accesso al bucket: Per semplificare la configurazione, i seguenti esempi utilizzano lo spazio dei nomi predefinito e l'account di servizio Kubernetes predefinito. Per maggiori dettagli, consulta Configurare l'accesso ai bucket Cloud Storage utilizzando la federazione delle identità per i carichi di lavoro di GKE.
Crea un account di servizio IAM per la tua applicazione o utilizza un account di servizio IAM esistente. Puoi utilizzare qualsiasi account di servizio IAM nel progetto del bucket Cloud Storage.
gcloud iam service-accounts create your-iam-service-acct \ --project=your-bucket-project-id
Sostituisci quanto segue:
your-iam-service-acct
: il nome del nuovo account di servizio IAM.your-bucket-project-id
: l'ID del progetto in cui hai creato il tuo account di servizio IAM. L'account di servizio IAM deve trovarsi nello stesso progetto del bucket Cloud Storage.
Assicurati che l'account di servizio IAM abbia i ruoli di archiviazione di cui hai bisogno.
gcloud storage buckets add-iam-policy-binding gs://your-bucket-name \ --member "serviceAccount:your-iam-service-acct@your-bucket-project-id.iam.gserviceaccount.com" \ --role "roles/storage.objectAdmin"
Sostituisci quanto segue:
your-bucket-name
: il nome del bucket Cloud Storage.your-iam-service-acct
: il nome del nuovo account di servizio IAM.your-bucket-project-id
: l'ID del progetto in cui hai creato il tuo account di servizio IAM.
Consenti all'account di servizio Kubernetes di rubare l'identità dell'account di servizio IAM aggiungendo un'associazione dei criteri IAM tra i due account di servizio. Questa associazione consente all'account di servizio Kubernetes di agire come account di servizio IAM.
gcloud iam service-accounts add-iam-policy-binding your-iam-service-acct@your-bucket-project-id.iam.gserviceaccount.com \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:your-project-id.svc.id.goog[default/default]"
Sostituisci quanto segue:
your-iam-service-acct
: il nome del nuovo account di servizio IAM.your-bucket-project-id
: l'ID del progetto in cui hai creato il tuo account di servizio IAM.your-project-id
: l'ID del progetto in cui hai creato il cluster GKE. I bucket Cloud Storage e il cluster GKE possono trovarsi nello stesso progetto o in progetti diversi.
Aggiungi un'annotazione all'account di servizio Kubernetes con l'indirizzo email dell'account di servizio IAM.
kubectl annotate serviceaccount default \ --namespace default \ iam.gke.io/gcp-service-account=your-iam-service-acct@your-bucket-project-id.iam.gserviceaccount.com
Sostituisci quanto segue:
your-iam-service-acct
: il nome del nuovo account di servizio IAM.your-bucket-project-id
: l'ID del progetto in cui hai creato il tuo account di servizio IAM.
Esegui il comando seguente per inserire il nome del bucket nei file YAML di questa demo:
find . -type f -name "*.yaml" | xargs sed -i "s/BUCKET_NAME/your-bucket-name/g"
Sostituisci
your-bucket-name
con il nome del tuo bucket Cloud Storage.Crea il volume permanente e la richiesta di volume permanente con il seguente comando:
kubectl apply -f pvc-pv.yaml
Inferenza e pubblicazione del modello JAX
Installa le dipendenze Python per eseguire gli script Python del tutorial che inviano richieste al servizio di modelli JAX.
pip install -r jax/requirements.txt
Esegui la demo di JAX BERT E2E:
Questa demo utilizza un modello BERT preaddestrato di Hugging Face.
Il pod Kubernetes esegue i seguenti passaggi:
- Scarica e utilizza lo script Python
export_bert_model.py
dalle risorse di esempio per scaricare il modello BERT preaddestrato in una directory temporanea. - Utilizza l'immagine di Cloud TPU Converter per convertire il modello preaddestrato da CPU a TPU e memorizza il modello nel bucket Cloud Storage che hai creato durante la configurazione.
Questo pod Kubernetes è configurato per l'esecuzione sulla CPU del pool di nodi predefinito. Esegui il pod con il seguente comando:
kubectl apply -f jax/bert/install-bert.yaml
Verifica che il modello sia stato installato correttamente con quanto segue:
kubectl get pods install-bert
Potrebbero essere necessari alcuni minuti prima che STATUS
legga Completed
.
Avvia il server di modelli TF per il modello
I carichi di lavoro di esempio in questo tutorial presuppongono quanto segue:
- Il cluster è in esecuzione con un pool di nodi TPU v5 con tre nodi
- Il pool di nodi utilizza il tipo di macchina
ct5lp-hightpu-1t
che contiene un chip TPU.
Se utilizzi una configurazione del cluster diversa da quella descritta in precedenza, dovrai modificare il manifesto di deployment del server.
Applica il deployment
kubectl apply -f jax/bert/serve-bert.yaml
Verifica che il server sia in esecuzione con quanto segue:
kubectl get deployment bert-deployment
La lettura di AVAILABLE
da parte di 3
può richiedere un minuto.
Applica il servizio di bilanciatore del carico
kubectl apply -f jax/bert/loadbalancer.yaml
Verifica che il bilanciatore del carico sia pronto per il traffico esterno con quanto segue:
kubectl get svc tf-bert-service
Potrebbero essere necessari alcuni minuti prima che un indirizzo IP venga elencato per EXTERNAL_IP
.
Invia la richiesta al server del modello
Ottieni l'IP esterno dal servizio del bilanciatore del carico:
EXTERNAL_IP=$(kubectl get services tf-bert-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Esegui uno script per inviare una richiesta al server:
python3 jax/bert/bert_request.py $EXTERNAL_IP
Risultato previsto:
For input "The capital of France is [MASK].", the result is ". the capital of france is paris.."
For input "Hello my name [MASK] Jhon, how can I [MASK] you?", the result is ". hello my name is jhon, how can i help you?."
Pulizia
Per ripulire le risorse, esegui kubectl delete
in ordine inverso.
kubectl delete -f jax/bert/loadbalancer.yaml kubectl delete -f jax/bert/serve-bert.yaml kubectl delete -f jax/bert/install-bert.yaml
Esegui la demo di pubblicazione E2E di JAX Stable Diffusion
Questa demo utilizza il modello di diffusione stabile preaddestrato di Hugging Face.
Esportare un modello salvato TF2 compatibile con TPU dal modello di diffusione stabile di Flax
L'esportazione dei modelli di diffusione stabili richiede che il cluster abbia un pool di nodi CPU con un tipo di macchina con almeno 16 GB di memoria disponibile, come descritto in Configurare il cluster.
Il pod Kubernetes esegue i seguenti passaggi:
- Scarica e utilizza lo script Python
export_stable_diffusion_model.py
dalle risorse di esempio per scaricare il modello di diffusione stabile preaddestrato in una directory temporanea. - Utilizza l'immagine di Cloud TPU Converter per convertire il modello preaddestrato da CPU a TPU e memorizza il modello nel bucket Cloud Storage che hai creato durante la configurazione dello spazio di archiviazione.
Questo pod Kubernetes è configurato per l'esecuzione nel pool di nodi CPU predefinito. Esegui il pod con il seguente comando:
kubectl apply -f jax/stable-diffusion/install-stable-diffusion.yaml
Verifica che il modello sia stato installato correttamente con quanto segue:
kubectl get pods install-stable-diffusion
Potrebbero essere necessari alcuni minuti prima che STATUS
legga Completed
.
Avvia il container del server di modelli TF per il modello
I carichi di lavoro di esempio sono stati configurati con le seguenti ipotesi:
- il cluster è in esecuzione con un pool di nodi TPU v5 con tre nodi
- il pool di nodi utilizza il tipo di macchina
ct5lp-hightpu-1t
, dove:- la topologia è 1x1
- il numero di chip TPU è 1
Se utilizzi una configurazione del cluster diversa da quella descritta in precedenza, dovrai modificare il manifesto di deployment del server.
Applica il deployment:
kubectl apply -f jax/stable-diffusion/serve-stable-diffusion.yaml
Verifica che il server funzioni come previsto:
kubectl get deployment stable-diffusion-deployment
La lettura di AVAILABLE
da parte di 3
può richiedere un minuto.
Applica il servizio di bilanciatore del carico:
kubectl apply -f jax/stable-diffusion/loadbalancer.yaml
Verifica che il bilanciatore del carico sia pronto per il traffico esterno con quanto segue:
kubectl get svc tf-stable-diffusion-service
Potrebbero essere necessari alcuni minuti prima che un indirizzo IP venga elencato per EXTERNAL_IP
.
Invia la richiesta al server del modello
Ottieni un IP esterno dal bilanciatore del carico:
EXTERNAL_IP=$(kubectl get services tf-stable-diffusion-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Esegui lo script per l'invio di una richiesta al server
python3 jax/stable-diffusion/stable_diffusion_request.py $EXTERNAL_IP
Risultato previsto:
Il prompt è Painting of a squirrel skating in New York
e l'immagine di output verrà salvata come stable_diffusion_images.jpg
nella directory corrente.
Pulizia
Per ripulire le risorse, esegui kubectl delete
in ordine inverso.
kubectl delete -f jax/stable-diffusion/loadbalancer.yaml kubectl delete -f jax/stable-diffusion/serve-stable-diffusion.yaml kubectl delete -f jax/stable-diffusion/install-stable-diffusion.yaml
Esegui la demo di pubblicazione E2E di TensorFlow ResNet-50:
Installa le dipendenze Python per eseguire gli script Python del tutorial che inviano richieste al servizio di modelli TF.
pip install -r tf/resnet50/requirements.txt
Passaggio 1: converti il modello
Applica la conversione del modello:
kubectl apply -f tf/resnet50/model-conversion.yml
Verifica che il modello sia stato installato correttamente con quanto segue:
kubectl get pods resnet-model-conversion
Potrebbero essere necessari alcuni minuti prima che STATUS
legga Completed
.
Passaggio 2: pubblica il modello con la pubblicazione di TensorFlow
Applica il deployment della pubblicazione del modello:
kubectl apply -f tf/resnet50/deployment.yml
Verifica che il server funzioni come previsto con il seguente comando:
kubectl get deployment resnet-deployment
La lettura di AVAILABLE
da parte di 3
può richiedere un minuto.
Applica il servizio di bilanciatore del carico:
kubectl apply -f tf/resnet50/loadbalancer.yml
Verifica che il bilanciatore del carico sia pronto per il traffico esterno con quanto segue:
kubectl get svc resnet-service
Potrebbero essere necessari alcuni minuti prima che un indirizzo IP venga elencato per EXTERNAL_IP
.
Passaggio 3: invia la richiesta di test al server del modello
Ottieni l'IP esterno dal bilanciatore del carico:
EXTERNAL_IP=$(kubectl get services resnet-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Esegui lo script di richiesta di test (HTTP) per inviare la richiesta al server del modello.
python3 tf/resnet50/request.py --host $EXTERNAL_IP
La risposta dovrebbe essere simile alla seguente:
Predict result: ['ImageNet ID: n07753592, Label: banana, Confidence: 0.94921875', 'ImageNet ID: n03532672, Label: hook, Confidence: 0.0223388672', 'ImageNet ID: n07749582, Label: lemon, Confidence: 0.00512695312
Passaggio 4: pulizia
Per ripulire le risorse, esegui i seguenti comandi kubectl delete
:
kubectl delete -f tf/resnet50/loadbalancer.yml kubectl delete -f tf/resnet50/deployment.yml kubectl delete -f tf/resnet50/model-conversion.yml
Assicurati di eliminare il pool di nodi e il cluster GKE quando non ti servono più.
Inferenza e pubblicazione del modello PyTorch
Installa le dipendenze Python per eseguire gli script Python del tutorial che inviano richieste al servizio di modelli PyTorch:
pip install -r pt/densenet161/requirements.txt
Esegui la demo di pubblicazione E2E di TorchServe Densenet161:
Genera l'archivio del modello.
- Applica l'archivio del modello:
kubectl apply -f pt/densenet161/model-archive.yml
- Verifica che il modello sia stato installato correttamente con quanto segue:
kubectl get pods densenet161-model-archive
Potrebbero essere necessari alcuni minuti prima che
STATUS
leggaCompleted
.Pubblica il modello con TorchServe:
Applica il deployment della pubblicazione del modello:
kubectl apply -f pt/densenet161/deployment.yml
Verifica che il server funzioni come previsto con il seguente comando:
kubectl get deployment densenet161-deployment
La lettura di
AVAILABLE
da parte di3
può richiedere un minuto.Applica il servizio di bilanciatore del carico:
kubectl apply -f pt/densenet161/loadbalancer.yml
Verifica che il bilanciatore del carico sia pronto per il traffico esterno con il seguente comando:
kubectl get svc densenet161-service
Potrebbero essere necessari alcuni minuti prima che un indirizzo IP venga elencato per
EXTERNAL_IP
.
Invia la richiesta di test al server del modello:
Ottieni l'IP esterno dal bilanciatore del carico:
EXTERNAL_IP=$(kubectl get services densenet161-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Esegui lo script di richiesta di test per inviare la richiesta (HTTP) al server del modello.
python3 pt/densenet161/request.py --host $EXTERNAL_IP
Dovresti visualizzare una risposta simile alla seguente:
Request successful. Response: {'tabby': 0.47878125309944153, 'lynx': 0.20393909513950348, 'tiger_cat': 0.16572578251361847, 'tiger': 0.061157409101724625, 'Egyptian_cat': 0.04997897148132324
Ripulisci le risorse eseguendo i seguenti comandi
kubectl delete
:kubectl delete -f pt/densenet161/loadbalancer.yml kubectl delete -f pt/densenet161/deployment.yml kubectl delete -f pt/densenet161/model-archive.yml
Assicurati di eliminare il node pool e il cluster GKE quando non ti servono più.
Risoluzione dei problemi più comuni
Puoi trovare informazioni sulla risoluzione dei problemi di GKE in Risolvere i problemi di TPU in GKE.
Inizializzazione della TPU non riuscita
Se riscontri il seguente errore, assicurati di eseguire il contenitore TPU in modalità privilegiata o di aver aumentato il valore ulimit
all'interno del contenitore. Per ulteriori informazioni, vedi Eseguire senza modalità con privilegi.
TPU platform initialization failed: FAILED_PRECONDITION: Couldn't mmap: Resource
temporarily unavailable.; Unable to create Node RegisterInterface for node 0,
config: device_path: "/dev/accel0" mode: KERNEL debug_data_directory: ""
dump_anomalies_only: true crash_in_debug_dump: false allow_core_dump: true;
could not create driver instance
Blocco della pianificazione
Supponiamo di avere due job (Job A e Job B) e che entrambi debbano essere pianificati su sezioni TPU con una determinata topologia TPU (ad esempio v4-32
). Supponiamo inoltre di avere due sezioni TPU v4-32
all'interno del cluster GKE, che chiameremo sezione X e sezione Y. Poiché il tuo cluster ha una capacità sufficiente per pianificare entrambi i job, in teoria entrambi i job dovrebbero essere pianificati rapidamente, uno su ciascun slice v4-32
TPU.
Tuttavia, senza un'attenta pianificazione, è possibile imbattersi in un blocco della programmazione. Supponiamo che lo scheduler Kubernetes pianifichi un pod Kubernetes dal job A sul seme X e poi un pod Kubernetes dal job B sul seme X. In questo caso, date le regole di affinità dei pod Kubernetes per il job A, lo scheduler tenterà di pianificare tutti i pod Kubernetes rimanenti per il job A nel segmento X. Lo stesso vale per il compito B. Di conseguenza, né il job A né il job B potranno essere pianificati completamente in un singolo slice. Il risultato sarà un deadlock di pianificazione.
Per evitare il rischio di un deadlock di pianificazione, puoi utilizzare l'anti-affinità dei pod Kubernetes con cloud.google.com/gke-nodepool
come topologyKey
come mostrato nell'esempio seguente:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 2
template:
metadata:
labels:
job: pi
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: job
operator: In
values:
- pi
topologyKey: cloud.google.com/gke-nodepool
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: job
operator: NotIn
values:
- pi
topologyKey: cloud.google.com/gke-nodepool
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values:
- kube-system
containers:
- name: pi
image: perl:5.34.0
command: ["sleep", "60"]
restartPolicy: Never
backoffLimit: 4
Creazione di risorse di pool di nodi TPU con Terraform
Puoi anche utilizzare Terraform per gestire le risorse del cluster e del pool di nodi.
Crea un pool di nodi di sezioni TPU multi-host in un cluster GKE esistente
Se hai già un cluster in cui vuoi creare un pool di nodi TPU multi-host, puoi utilizzare il seguente snippet Terraform:
resource "google_container_cluster" "cluster_multi_host" {
…
release_channel {
channel = "RAPID"
}
workload_identity_config {
workload_pool = "my-gke-project.svc.id.goog"
}
addons_config {
gcs_fuse_csi_driver_config {
enabled = true
}
}
}
resource "google_container_node_pool" "multi_host_tpu" {
provider = google-beta
project = "${project-id}"
name = "${node-pool-name}"
location = "${location}"
node_locations = ["${node-locations}"]
cluster = google_container_cluster.cluster_multi_host.name
initial_node_count = 2
node_config {
machine_type = "ct4p-hightpu-4t"
reservation_affinity {
consume_reservation_type = "SPECIFIC_RESERVATION"
key = "compute.googleapis.com/reservation-name"
values = ["${reservation-name}"]
}
workload_metadata_config {
mode = "GKE_METADATA"
}
}
placement_policy {
type = "COMPACT"
tpu_topology = "2x2x2"
}
}
Sostituisci i seguenti valori:
your-project
: il tuo progetto Google Cloud in cui esegui il tuo carico di lavoro.your-node-pool
: il nome del pool di nodi che stai creando.us-central2
: la regione in cui stai eseguendo il carico di lavoro.us-central2-b
: la zona in cui stai eseguendo il carico di lavoro.your-reservation-name
: il nome della prenotazione.
Creare un pool di nodi di sezione TPU a un solo host in un cluster GKE esistente
Utilizza lo snippet Terraform seguente:
resource "google_container_cluster" "cluster_single_host" {
…
cluster_autoscaling {
autoscaling_profile = "OPTIMIZE_UTILIZATION"
}
release_channel {
channel = "RAPID"
}
workload_identity_config {
workload_pool = "${project-id}.svc.id.goog"
}
addons_config {
gcs_fuse_csi_driver_config {
enabled = true
}
}
}
resource "google_container_node_pool" "single_host_tpu" {
provider = google-beta
project = "${project-id}"
name = "${node-pool-name}"
location = "${location}"
node_locations = ["${node-locations}"]
cluster = google_container_cluster.cluster_single_host.name
initial_node_count = 0
autoscaling {
total_min_node_count = 2
total_max_node_count = 22
location_policy = "ANY"
}
node_config {
machine_type = "ct4p-hightpu-4t"
workload_metadata_config {
mode = "GKE_METADATA"
}
}
}
Sostituisci i seguenti valori:
your-project
: il tuo progetto Google Cloud in cui esegui il tuo carico di lavoro.your-node-pool
: il nome del pool di nodi che stai creando.us-central2
: la regione in cui stai eseguendo il carico di lavoro.us-central2-b
: la zona in cui esegui il carico di lavoro.