Questo tutorial mostra come eseguire workload PyTorch distribuiti e ottimizzare un modello Gemma 4 su sezioni Cloud TPU multi-host in Google Kubernetes Engine (GKE) utilizzando Ray Core, Ray Train, PyTorch Fully Sharded Data Parallel (FSDP2) e TorchTPU.
Questo tutorial è rivolto a ML engineer, amministratori e operatori di piattaforme e specialisti di dati e AI che vogliono orchestrare workload di addestramento PyTorch distribuito su sezioni TPU multi-host in Kubernetes. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui si fa riferimento nei contenuti di Google Cloud , consulta Ruoli e attività comuni degli utenti GKE.
Prima di iniziare questo tutorial, assicurati di avere familiarità con quanto segue:
- Informazioni sulle modalità operative di GKE
- Informazioni sulle TPU in GKE
- Node pool di sezioni TPU multi-host
- Informazioni su Ray su GKE
Sfondo
Questa sezione descrive le tecnologie chiave utilizzate in questo tutorial.
TPU
Le Tensor Processing Unit (TPU) sono acceleratori progettati da Google per i workload di machine learning. Questo tutorial supporta sia TPU Trillium (v6e) sia Ironwood (TPU7x). In una sezione TPU multi-host, più host TPU comunicano direttamente su una rete Inter-Chip Interconnect (ICI) ad alta velocità, fornendo la memoria ad alta larghezza di banda (HBM) aggregata e la comunicazione collettiva a bassa latenza necessarie per addestrare modelli che superano la capacità di memoria di un singolo chip o host TPU.
TorchTPU
TorchTPU è un backend PyTorch open source per Cloud TPU, sviluppato in collaborazione tra Google e Meta. Con TorchTPU, puoi eseguire i modelli PyTorch esistenti su hardware TPU con modifiche minime al codice e scalare i workload di addestramento e inferenza da un singolo chip a pod di TPU multislice tramite il compilatore Accelerated Linear Algebra (XLA). TorchTPU utilizza un modello di esecuzione con un processo per dispositivo sulla rete TPU ICI e supporta le API PyTorch standard, tra cui l'esecuzione eager, torch.compile, torch.distributed, DeviceMesh, DTensor e Fully Sharded Data Parallel (FSDP2).
KubeRay e Ray su TPU
KubeRay è un operatore Kubernetes per il deployment e la gestione delle applicazioni Ray. L'abilitazione del componente aggiuntivo Ray su GKE esegue il deployment dell'operatore KubeRay gestito e del webhook TPU KubeRay. Quando KubeRay crea pod worker che richiedono risorse google.com/tpu, il webhook configura automaticamente i nomi host dei pod, il servizio headless e le variabili di ambiente TPU necessarie per il coordinamento multi-host.
Ray rileva la topologia TPU su ogni nodo all'avvio e pianifica i workload distribuiti tra le sezioni TPU. Puoi orchestrare i workload TorchTPU distribuiti a due livelli:
- Ray Core fornisce gruppi di posizionamento sensibili alla topologia e pianificazione degli attori per loop di esecuzione distribuiti personalizzati, come il calcolo parallelo dei tensori o le pipeline di apprendimento per rinforzo (RL).
- Ray Train fornisce un addestramento gestito con parallelismo dei dati e dei modelli distribuito, tra cui PyTorch Distributed Data Parallel (DDP), PyTorch FSDP2 e JAX single program, multiple data (SPMD), con checkpoint integrato e recupero automatico degli errori.
Obiettivi
Questo tutorial mostra gli aspetti seguenti:
- Crea un cluster GKE in modalità Autopilot o Standard su TPU Trillium (v6e) o Ironwood (TPU7x).
- Crea un'immagine container che sovrappone le librerie di addestramento Ray e Hugging Face all'immagine di base TorchTPU.
- Esegui il deployment di una risorsa personalizzata RayCluster per eseguire il provisioning dei nodi head e worker TPU.
- Esegui il calcolo distribuito con parallelismo dei tensori con PyTorch
DeviceMesheDTensorin una sezione TPU utilizzando Ray Core. - Esegui l'ottimizzazione di un modello Gemma 4 con PyTorch FSDP2 su una sezione TPU multi-host utilizzando Ray Train.
Costi
In questo tutorial utilizzerai i seguenti componenti fatturabili di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi.
Al termine delle attività descritte in questo tutorial, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, consulta Esegui la pulizia.
Prima di iniziare
Prima di iniziare, assicurati di aver eseguito le seguenti attività:
- Abilita l'API Artifact Registry, l'API Cloud Storage e l'API Google Kubernetes Engine. Abilita le API
- Per utilizzare Google Cloud CLI per questa attività,
installala e poi
inizializza
gcloud CLI. Se hai già installato gcloud CLI, scarica l'ultima
versione eseguendo il comando
gcloud components update. Le versioni precedenti di gcloud CLI potrebbero non supportare l'esecuzione dei comandi in questo documento.
- Verifica che il tuo progetto disponga di una quota sufficiente per la capacità TPU Trillium (v6e) o Ironwood (TPU7x) nella zona selezionata. Per maggiori informazioni, consulta Quote di Cloud TPU.
- Assicurati che il tuo account disponga dei seguenti ruoli IAM:
- Kubernetes Engine Admin (
roles/container.admin) - Artifact Registry Administrator (
roles/artifactregistry.admin) - Storage Admin (
roles/storage.admin)
- Kubernetes Engine Admin (
prepara l'ambiente
In questo tutorial utilizzerai Cloud Shell per gestire le risorse ospitate su Google Cloud. In Cloud Shell è preinstallato il software necessario per questo tutorial, tra cui kubectl, docker, python3 e l'interfaccia a riga di comando gcloud.
Per configurare l'ambiente con Cloud Shell, segui questi passaggi:
Nella console Google Cloud , avvia una sessione di Cloud Shell facendo clic su
Attiva Cloud Shell nella consoleGoogle Cloud . Questa azione avvia una sessione nel riquadro inferiore della console Google Cloud .
Clona il repository
kubernetes-engine-samplese passa alla directory di esempio per questo tutorial:git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samples/ai-ml/gke-ray/raytrain/torchtpuCrea e attiva un ambiente virtuale Python locale con l'interfaccia a riga di comando Ray installata:
python3 -m venv ~/ray-env source ~/ray-env/bin/activate pip install "ray[default]==2.58.0"Per scaricare i pesi del modello Gemma 4, accetta il contratto di licenza di Google su Hugging Face:
- Vai alla pagina del modello Gemma 4 su Hugging Face.
- Accedi e accetta i termini di licenza facendo clic su Accetta e accedi al repository.
- Nelle impostazioni del tuo account Hugging Face, genera un token di accesso utente con autorizzazioni
Read.
Imposta le variabili di ambiente per il tuo progetto Google Cloud , il cluster, il bucket Cloud Storage e il token Hugging Face:
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=CLUSTER_NAME export REGION=REGION export ZONE=ZONE export ARTIFACT_REGISTRY=ARTIFACT_REGISTRY export BUCKET_NAME=BUCKET_NAME export HF_TOKEN=HF_TOKEN export IMAGE_URI=${REGION}-docker.pkg.dev/${PROJECT_ID}/${ARTIFACT_REGISTRY}/ray-torchtpu:latest gcloud config set project ${PROJECT_ID}Sostituisci quanto segue:
PROJECT_ID: il tuo ID progetto Google Cloud .CLUSTER_NAME: il nome del tuo cluster GKE, ad esempioray-torchtpu-cluster.REGION: la regione in cui si trovano il repository Artifact Registry, il bucket Cloud Storage e la capacità della TPU.ZONE: la zona in cui è disponibile la capacità della TPU. Per le regioni e le zone disponibili in base alla versione della TPU, consulta Regioni e zone TPU.ARTIFACT_REGISTRY: il nome del tuo repository Docker Artifact Registry, ad esempioray-torchtpu.BUCKET_NAME: il nome del bucket Cloud Storage per l'archiviazione dei checkpoint di Ray Train, ad esempioPROJECT_ID-ray-torchtpu.HF_TOKEN: il tuo token di accesso a Hugging Face.
Crea un cluster GKE
Puoi eseguire workload di addestramento TorchTPU distribuito in un cluster GKE Autopilot o Standard con il componente aggiuntivo operatore Ray gestito abilitato.
Crea il cluster GKE e configura le credenziali per lo strumento a riga di comando
kubectl:Autopilot
Crea un cluster GKE Autopilot regionale con il componente aggiuntivo Operatore Ray abilitato:
gcloud container clusters create-auto ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --region=${REGION} \ --cluster-version=1.36 \ --enable-ray-operatorQuando esegui il deployment della risorsa personalizzata RayCluster in un passaggio successivo, GKE Autopilot esegue automaticamente il provisioning del nodo head della CPU e della sezione TPU multi-host che corrispondono alle richieste di risorse dei pod e ai selettori dei nodi.
Configura lo strumento a riga di comando
kubectlper comunicare con il tuo cluster:gcloud container clusters get-credentials ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --region=${REGION}
Standard
Crea un cluster GKE Standard di zona con un pool di nodi CPU per ospitare il pod head Ray, Image streaming, GKE Dataplane V2 e la federazione delle identità per i carichi di lavoro per GKE abilitati:
gcloud container clusters create ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --zone=${ZONE} \ --cluster-version=1.36 \ --machine-type=n2-standard-8 \ --num-nodes=1 \ --addons=RayOperator \ --enable-image-streaming \ --enable-dataplane-v2 \ --workload-pool=${PROJECT_ID}.svc.id.googRayOperatorConfigura lo strumento a riga di comando
kubectlper comunicare con il tuo cluster:gcloud container clusters get-credentials ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --zone=${ZONE}Crea un pool di nodi di sezioni TPU multi-host con 16 dispositivi con una topologia
4x4su quattro host su TPU Trillium (v6e) o una topologia2x2x2su due host su Ironwood (TPU7x):Trillium (v6e)
gcloud container node-pools create tpu-multi-host-pool \ --project=${PROJECT_ID} \ --cluster=${CLUSTER_NAME} \ --zone=${ZONE} \ --machine-type=ct6e-standard-4t \ --tpu-topology=4x4 \ --num-nodes=4Ironwood (TPU7x)
gcloud container node-pools create tpu-multi-host-pool \ --project=${PROJECT_ID} \ --cluster=${CLUSTER_NAME} \ --zone=${ZONE} \ --machine-type=tpu7x-standard-4t \ --tpu-topology=2x2x2 \ --num-nodes=2
Crea un bucket Cloud Storage per archiviare i checkpoint Ray Train condivisi tra i nodi TPU multi-host e concedi alla risorsa ServiceAccount Kubernetes
defaultl'accesso al bucket:gcloud storage buckets create gs://${BUCKET_NAME} --location=${REGION} PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \ --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/default/sa/default" \ --role="roles/storage.objectAdmin"Crea un secret Kubernetes con il tuo token di accesso Hugging Face in modo che i pod Ray possano scaricare i pesi di Gemma 4 con accesso limitato:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN}
Crea l'immagine container
Crea un'immagine container che installi Ray e le librerie di addestramento Hugging Face sull'immagine di base TorchTPU predefinita, che include TorchTPU e la libreria libtpu.
Crea un repository Docker di Artifact Registry e configura l'autenticazione Docker:
gcloud artifacts repositories create ${ARTIFACT_REGISTRY} \ --repository-format=docker \ --location=${REGION} gcloud auth configure-docker ${REGION}-docker.pkg.dev,us-docker.pkg.devEsamina il file
Dockerfilenella directory di esempio:L'addestramento a sezione singola con la classe Ray
TorchTrainere la pianificazione per chiplet su Ironwood (TPU7x) richiedono Ray versione 2.58.0 o successive, mentre l'ottimizzazione di Gemma 4 richiede la libreriatransformersversione 5.5.0 o successive.Crea l'immagine ed eseguine il push in Artifact Registry:
docker build -t ${IMAGE_URI} . docker push ${IMAGE_URI}
Esegui il deployment della risorsa personalizzata RayCluster
Esegui il deployment di una risorsa personalizzata RayCluster che esegue il provisioning di un pod head della CPU, di un volume /dev/shm in memoria per l'archivio di oggetti della memoria condivisa di Ray e di un gruppo di worker TPU multi-host.
Esamina il manifest RayCluster per la tua versione di TPU nel repository di esempio:
Trillium (v6e)
Ironwood (TPU7x)
Su Ironwood (TPU7x), ogni chip fisico contiene due chiplet, fornendo otto core TPU logici per host a quattro chip. Il manifest imposta il valore del campo
TPUsu"8"nella sezioneresourcese imposta la variabile di ambienteRAY_TPU_RESOURCE_PER_CHIPsu"2"per annunciare e pianificare otto risorseTPUlogiche per host.Applica il manifest per creare la risorsa personalizzata RayCluster:
Trillium (v6e)
envsubst < ray-cluster.tpu-v6e-multihost.yaml | kubectl apply -f -Ironwood (TPU7x)
envsubst < ray-cluster.tpu-v7x-multihost.yaml | kubectl apply -f -Attendi finché il pod head di RayCluster e tutti i pod worker TPU non raggiungono lo stato
Running:kubectl get pods -l ray.io/cluster=ray-torchtpu-clusterL'output è simile al seguente:
Trillium (v6e)
NAME READY STATUS RESTARTS AGE ray-torchtpu-cluster-head-pdpk6 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-brwpc 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-dx4w7 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-h4d4w 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-t2g24 1/1 Running 0 2m30sIronwood (TPU7x)
NAME READY STATUS RESTARTS AGE ray-torchtpu-cluster-head-k9x2m 1/1 Running 0 2m30s ray-torchtpu-cluster-tpu7x-16-worker-7cwpq 1/1 Running 0 2m30s ray-torchtpu-cluster-tpu7x-16-worker-m98r9 1/1 Running 0 2m30sIspeziona le variabili di ambiente su uno dei pod worker per verificare che il webhook TPU KubeRay abbia inserito le variabili di coordinamento TPU multi-host e di topologia TorchTPU:
kubectl get pods -l ray.io/node-type=worker \ -o=jsonpath='{range .items[0].spec.containers[0].env[*]}{.name}={.value}{"\n"}{end}' \ | grep -E "TPU_WORKER_ID|TPU_WORKER_HOSTNAMES|TPU_NAME|TORCH_TPU_TOPOLOGY|TORCH_TPU_SLICEBUILDER_ADDRESSES"L'output è simile al seguente:
Trillium (v6e)
TPU_WORKER_HOSTNAMES=v6e-16-0-0.ray-torchtpu-cluster-headless,v6e-16-0-1.ray-torchtpu-cluster-headless,v6e-16-0-2.ray-torchtpu-cluster-headless,v6e-16-0-3.ray-torchtpu-cluster-headless TORCH_TPU_TOPOLOGY=4,4,1 TORCH_TPU_SLICEBUILDER_ADDRESSES=v6e-16-0-0.ray-torchtpu-cluster-headless:8471,v6e-16-0-0.ray-torchtpu-cluster-headless:8472,v6e-16-0-0.ray-torchtpu-cluster-headless:8473,v6e-16-0-0.ray-torchtpu-cluster-headless:8474,v6e-16-0-1.ray-torchtpu-cluster-headless:8471,v6e-16-0-1.ray-torchtpu-cluster-headless:8472,v6e-16-0-1.ray-torchtpu-cluster-headless:8473,v6e-16-0-1.ray-torchtpu-cluster-headless:8474,v6e-16-0-2.ray-torchtpu-cluster-headless:8471,v6e-16-0-2.ray-torchtpu-cluster-headless:8472,v6e-16-0-2.ray-torchtpu-cluster-headless:8473,v6e-16-0-2.ray-torchtpu-cluster-headless:8474,v6e-16-0-3.ray-torchtpu-cluster-headless:8471,v6e-16-0-3.ray-torchtpu-cluster-headless:8472,v6e-16-0-3.ray-torchtpu-cluster-headless:8473,v6e-16-0-3.ray-torchtpu-cluster-headless:8474 TPU_WORKER_ID=3 TPU_NAME=v6e-16-0Ironwood (TPU7x)
TPU_WORKER_HOSTNAMES=tpu7x-16-0-0.ray-torchtpu-cluster-headless,tpu7x-16-0-1.ray-torchtpu-cluster-headless TORCH_TPU_TOPOLOGY=2,2,2,2 TORCH_TPU_SLICEBUILDER_ADDRESSES=tpu7x-16-0-0.ray-torchtpu-cluster-headless:8471,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8472,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8473,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8474,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8475,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8476,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8477,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8478,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8471,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8472,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8473,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8474,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8475,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8476,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8477,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8478 TPU_WORKER_ID=1 TPU_NAME=tpu7x-16-0Stabilisci una sessione di port forwarding al servizio head Ray:
kubectl port-forward svc/ray-torchtpu-cluster-head-svc 8265:8265 >/dev/null 2>&1 &Puoi ispezionare i nodi worker TPU e le relative etichette
ray.io/tpu-*rilevate automaticamente nella scheda Cluster della dashboard Ray.
Esegui il parallelismo dei tensori distribuito con Ray Core
Ray Core fornisce la funzione slice_placement_group nel modulo ray.util.tpu per prenotare una sezione TPU multi-host intatta e la classe PlacementGroupSchedulingStrategy per pianificare un attore Ray per dispositivo TPU logico nella sezione.
Esamina lo script
ray_core_collectives.pynel repository di esempio:Lo script esegue il parallelismo dei tensori distribuito nella sezione TPU in tre passaggi:
- La funzione
slice_placement_groupprenota una sezione TPU di 16 dispositivi e pianifica un attoreTorchTPUSliceWorkersu ogni dispositivo TPU. - Ogni attore calcola il proprio ranking globale dall'indice dell'host e dall'ID dispositivo locale, quindi inizializza il gruppo di processi
tpu_dist. - Le funzioni
init_device_mesheparallelize_modulesuddividono in shard i livelli feed-forward su tutti i 16 dispositivi TPU, verificano l'output rispetto a un riferimento CPU su un singolo dispositivo ed eseguono un'operazione collettivaall_reducesu ICI.
- La funzione
Invia il job Ray Core per la tua versione di TPU:
Trillium (v6e)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_core_collectives.py --topology=4x4 --accelerator-type=TPU-V6EIronwood (TPU7x)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_core_collectives.py --topology=2x2x2 --accelerator-type=TPU-V7XL'output è simile al seguente:
Trillium (v6e)
Rank 0 (worker_id=0, local_rank=0, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 1 (worker_id=0, local_rank=1, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 2 (worker_id=0, local_rank=2, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 3 (worker_id=0, local_rank=3, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 4 (worker_id=1, local_rank=0, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 5 (worker_id=1, local_rank=1, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 6 (worker_id=1, local_rank=2, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 7 (worker_id=1, local_rank=3, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 8 (worker_id=2, local_rank=0, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 9 (worker_id=2, local_rank=1, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 10 (worker_id=2, local_rank=2, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 11 (worker_id=2, local_rank=3, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 12 (worker_id=3, local_rank=0, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 13 (worker_id=3, local_rank=1, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 14 (worker_id=3, local_rank=2, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 15 (worker_id=3, local_rank=3, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] All 16 TorchTPU ranks verified DTensor TP parity (max_abs_diff=0.002470) and all_reduce sum = 136.0 ------------------------------------------ Job 'raysubmit_HFTkKrjSnfza3ZFD' succeeded ------------------------------------------Ironwood (TPU7x)
Rank 0 (worker_id=0, local_rank=0, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 1 (worker_id=0, local_rank=1, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 2 (worker_id=0, local_rank=2, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 3 (worker_id=0, local_rank=3, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 4 (worker_id=0, local_rank=4, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 5 (worker_id=0, local_rank=5, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 6 (worker_id=0, local_rank=6, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 7 (worker_id=0, local_rank=7, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 8 (worker_id=1, local_rank=0, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 9 (worker_id=1, local_rank=1, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 10 (worker_id=1, local_rank=2, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 11 (worker_id=1, local_rank=3, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 12 (worker_id=1, local_rank=4, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 13 (worker_id=1, local_rank=5, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 14 (worker_id=1, local_rank=6, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 15 (worker_id=1, local_rank=7, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] All 16 TorchTPU ranks verified DTensor TP parity (max_abs_diff=0.002470) and all_reduce sum = 136.0 ------------------------------------------ Job 'raysubmit_MrJbAe3hvARBcBN2' succeeded ------------------------------------------
Ottimizza un modello Gemma 4 con Ray Train e PyTorch FSDP2
La classe Ray Train TorchTrainer automatizza la prenotazione delle sezioni TPU, il posizionamento dei worker e l'inizializzazione di torch.distributed in una sezione TPU multi-host.
Esamina lo script
ray_train_llm_finetune.pynel repository di esempio, che ottimizza il modellogoogle/gemma-4-E2B-itsul set di dati di istruzionidatabricks/databricks-dolly-15k:Lo script configura la classe
TorchTrainercon i seguenti componenti:- La classe
ScalingConfigconfigura la topologia dei worker distribuiti per il job di addestramento. L'impostazione dei parametriuse_tpu=True,num_workers=16,topologyeaccelerator_typeprenota una sezione TPU di 16 dispositivi e pianifica un worker per core TPU. - La classe
TorchConfigconfigura il gruppo di processitorch.distributedtra i worker. L'impostazione del parametrobackend="tpu_dist"connette tutti i 16 worker sulla rete TPU ICI prima dell'esecuzione della funzionetrain_func. - La funzione
create_dataloaderscarica e tokenizza il set di dati di istruzioni, raggruppa le sequenze di token con un oggetto PyTorchDataLoadere chiama la funzioneray.train.torch.prepare_data_loaderin modo che ogni worker riceva uno shard disgiunto di ogni batch globale sul dispositivo TPU assegnato. - La funzione
train_funccarica il modello con precisionebfloat16e chiama la funzione PyTorch FSDP2fully_shardsu ogni blocco feed-forward e sul modello root per eseguire lo sharding di parametri, gradienti e stati dell'ottimizzatore su tutti i 16 core TPU. - La classe
Checkpointe la funzioneray.train.reportraccolgono il dizionario completo dello stato del modello nel rank 0 alla fine di ogni epoca e caricano il checkpoint nel bucket Cloud Storage.
- La classe
Invia il job di ottimizzazione
TorchTrainerFSDP2 per la tua versione di TPU:Trillium (v6e)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_train_llm_finetune.py \ --topology=4x4 \ --accelerator-type=TPU-V6E \ --storage-path=gs://${BUCKET_NAME}/ray_train_torchtpuIronwood (TPU7x)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_train_llm_finetune.py \ --topology=2x2x2 \ --accelerator-type=TPU-V7X \ --storage-path=gs://${BUCKET_NAME}/ray_train_torchtpuL'output è simile al seguente:
Trillium (v6e)
Starting Ray Train FSDP2 SFT job: model=google/gemma-4-E2B-it, topology=4x4, accelerator_type=TPU-V6E, num_workers=16 (TrainController pid=5407) Attempting to start training worker group of size 16 with the following resources: [{'TPU': 1, 'accelerator_type:TPU-V6E': 0.001}] * 16 (RayTrainWorker pid=19733, ip=10.72.3.20) Setting up process group for: env:// [rank=0, world_size=16] (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 1/3 | loss=3.1402 | epoch_time=28.17s | tokens/s=18613.5 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-08-10.762175) (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 2/3 | loss=2.3318 | epoch_time=26.07s | tokens/s=20112.8 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-10-02.548088) (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 3/3 | loss=2.2050 | epoch_time=25.52s | tokens/s=20545.2 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-11-48.701853) Training completed! Final metrics: {'epoch': 3, 'loss': 2.205, 'epoch_time_s': 25.52, 'tokens_per_s': 20545.2} Saved checkpoint: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-11-48.701853) ------------------------------------------ Job 'raysubmit_zbm4pnFZitA1YECA' succeeded ------------------------------------------Ironwood (TPU7x)
Starting Ray Train FSDP2 SFT job: model=google/gemma-4-E2B-it, topology=2x2x2, accelerator_type=TPU-V7X, num_workers=16 (TrainController pid=1162) Attempting to start training worker group of size 16 with the following resources: [{'TPU': 1, 'accelerator_type:TPU-V7X': 0.001}] * 16 (RayTrainWorker pid=257, ip=172.16.26.6) Setting up process group for: env:// [rank=0, world_size=16] (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 1/3 | loss=3.1407 | epoch_time=26.28s | tokens/s=19953.3 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-52-00.026930) (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 2/3 | loss=2.3235 | epoch_time=16.68s | tokens/s=31429.9 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-53-33.533341) (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 3/3 | loss=2.1964 | epoch_time=16.98s | tokens/s=30884.6 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-55-01.508219) Training completed! Final metrics: {'epoch': 3, 'loss': 2.1964, 'epoch_time_s': 16.98, 'tokens_per_s': 30884.6} Saved checkpoint: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-55-01.508219) ------------------------------------------ Job 'raysubmit_zSNnCXhHkwKiSmJh' succeeded ------------------------------------------L'output dell'addestramento mostra quanto segue:
- L'epoca 1 include la compilazione iniziale del grafico XLA. Le epoche 2 e 3 riutilizzano gli eseguibili memorizzati nella cache di
/dev/shm/torch_tpu_cache, raggiungendo oltre 20.000 token al secondo su TPU Trillium (v6e) e 31.000 token al secondo su Ironwood (TPU7x). - La perdita di entropia incrociata globale sincronizzata tra tutti i 16 rank dei worker FSDP2 diminuisce da 3,14 nell'epoca 1 a 2,20 nell'epoca 3 nelle tre epoche di ottimizzazione sul set di dati di istruzioni
databricks/databricks-dolly-15k. - Alla fine di ogni epoca, il rank 0 raccoglie il dizionario completo dello stato del modello e carica il checkpoint nel bucket Cloud Storage, conservando il checkpoint con la perdita più bassa, come configurato nell'oggetto
CheckpointConfig(num_to_keep=1, checkpoint_score_attribute="loss", checkpoint_score_order="min").
- L'epoca 1 include la compilazione iniziale del grafico XLA. Le epoche 2 e 3 riutilizzano gli eseguibili memorizzati nella cache di
Osserva le prestazioni del workload
Per monitorare l'utilizzo di TensorCore della TPU, l'utilizzo di HBM e le metriche del cluster Ray in Cloud Monitoring, consulta Raccogli e visualizza log e metriche per i cluster Ray su GKE e Visualizza le metriche della TPU nella dashboard di Ray.
Accedi alla dashboard Ray
Per esaminare lo stato degli attori, dei gruppi di posizionamento e dei job di addestramento Ray nella dashboard Ray integrata, segui questi passaggi:
Se il port forwarding al servizio head di Ray non è già in esecuzione, avvialo in background:
kubectl port-forward svc/ray-torchtpu-cluster-head-svc 8265:8265 >/dev/null 2>&1 &In Cloud Shell, fai clic su
Anteprima web e seleziona Anteprima sulla porta 8265 oppure apri
http://localhost:8265nel browser locale.Fai clic sulle schede Job, Cluster e Metriche per esaminare i log dei worker, lo stato del gruppo di posizionamento, le etichette dei nodi TPU e il grafico Utilizzo TPU per nodo.
Esegui la pulizia
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina la risorsa personalizzata RayCluster, il cluster GKE, il bucket Cloud Storage e il repository Artifact Registry:
Interrompi il processo di port forwarding in background ed elimina la risorsa personalizzata RayCluster e il secret Kubernetes:
pkill -f "kubectl port-forward" || true kubectl delete raycluster ray-torchtpu-cluster kubectl delete secret hf-secret --ignore-not-foundElimina il cluster GKE:
Autopilot
gcloud container clusters delete ${CLUSTER_NAME} \ --region=${REGION}Standard
gcloud container clusters delete ${CLUSTER_NAME} \ --zone=${ZONE}Elimina il bucket Cloud Storage e i relativi contenuti dei checkpoint:
gcloud storage rm --recursive gs://${BUCKET_NAME}Elimina il repository Artifact Registry:
gcloud artifacts repositories delete ${ARTIFACT_REGISTRY} \ --location=${REGION}
Passaggi successivi
- Scopri di più su PyTorch su Cloud TPU.
- Consulta la documentazione di TorchTPU.
- Scopri come gestire gli LLM su TPU multi-host con Ray e TorchTPU.
- Scopri come ottimizzare l'addestramento dell'AI su TPU con DWS e Kueue.
- Leggi Informazioni sulle TPU in GKE.
- Consulta la documentazione di Ray Train.