Questo tutorial mostra come orchestrare un ambiente di addestramento distribuito per l'apprendimento per rinforzo (RL) su Google Kubernetes Engine (GKE). Utilizzi Ray e il framework NVIDIA NeMo RL per configurare un ambiente di addestramento distribuito per ottimizzare un modello.
Questo tutorial si concentra sulla pipeline di addestramento dell'ottimizzazione relativa dei criteri di gruppo (GRPO) su GKE con Ray e NeMo RL. GRPO è un algoritmo di apprendimento per rinforzo progettato per migliorare la capacità di ragionamento di un modello. Questo algoritmo efficiente in termini di memoria semplifica il processo di RL eliminando il Critic, o modello di valore, e utilizzando invece un calcolo relativo basato sul gruppo.
Prima di eseguire questo tutorial, ti consigliamo di completare il tutorial Perfezionare e scalare l'apprendimento per rinforzo con verl su GKE. Il seguente tutorial utilizza la stessa configurazione e lo stesso setup del cluster del tutorial sull'ottimizzazione e lo scaling del RL con verl.
Sfondo
Le sezioni seguenti forniscono una breve panoramica dei concetti utilizzati in questo tutorial.
Apprendimento per rinforzo (RL)
L'RL insegna ai modelli attraverso l'esperienza, l'esplorazione e il feedback, anziché l'imitazione statica. Sebbene il pre-addestramento insegni a un modello cosa dire, l'apprendimento per rinforzo con feedback umano (RLHF) gli insegna a essere utile, sicuro e logico. L'RL funge da ponte tra un modello di base e un modello ottimizzato per un caso d'uso specializzato.
Per saperne di più, consulta Che cos'è l'apprendimento per rinforzo?
Ottimizzazione delle policy relative al gruppo (GRPO)
GRPO, un algoritmo reso popolare da DeepSeek, offre un'alternativa efficiente in termini di memoria all'ottimizzazione delle policy prossimali (PPO) per l'allineamento LLM rimuovendo il modello Critic. Invece di una rete Critic, GRPO genera un gruppo di risposte per lo stesso prompt e utilizza la ricompensa media di quel gruppo come baseline.
Per saperne di più, consulta GRPO.
NVIDIA NeMo RL
NeMo RL è la libreria open source di NVIDIA per il post-training progettata per l'RL scalabile. Parte dell'ecosistema più ampio del framework NeMo, NeMo RL consente sia esperimenti su piccola scala su una singola GPU sia deployment multinodo su migliaia di GPU.
Per ulteriori informazioni, consulta NVIDIA NeMo RL.
Set di dati GSM8k
In questo tutorial utilizzi il set di dati GSM8k, che contiene 8500 problemi matematici di alta qualità, linguisticamente diversi per la scuola elementare.
Utilizzando GSM8k e GRPO, il modello genera un gruppo di n risposte diverse per lo stesso problema. GRPO confronta queste risposte con la media del gruppo. Il modello viene premiato maggiormente per i percorsi che sono costantemente corretti e logicamente validi rispetto al resto del gruppo. Nel tempo, il modello impara che articolare chiaramente i suoi passaggi è il modo più affidabile per massimizzare la ricompensa, riducendo di fatto la ricompensa per le risposte con un rendimento scarso.
Per saperne di più, consulta GSM8k.
Obiettivi
Questo tutorial mostra come configurare RL su GKE con NeMo RL completando i seguenti passaggi:
- Prepara l'ambiente.
- Configura un cluster GKE con GPU B200 o H200.
- Configura KubeRay per gestire un cluster Ray distribuito.
- Utilizza Managed Lustre per l'archiviazione ad alte prestazioni.
- Esegui un job di addestramento GRPO che utilizza NeMo RL.
Prima di iniziare
- Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei carichi di lavoro.
-
Installa Google Cloud CLI.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
gcloud init -
Crea o seleziona un Google Cloud progetto.
Ruoli richiesti per selezionare o creare un progetto
- Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
-
Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto
(
roles/resourcemanager.projectCreator), che contiene l'autorizzazioneresourcemanager.projects.create. Scopri come concedere i ruoli.
-
Creare un progetto Google Cloud :
gcloud projects create PROJECT_ID
Sostituisci
PROJECT_IDcon un nome per il progetto Google Cloud che stai creando. -
Seleziona il progetto Google Cloud che hai creato:
gcloud config set project PROJECT_ID
Sostituisci
PROJECT_IDcon il nome del progetto Google Cloud .
-
Verifica che la fatturazione sia attivata per il tuo progetto Google Cloud .
Abilita le API richieste:
Ruoli richiesti per abilitare le API
Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (
roles/serviceusage.serviceUsageAdmin), che include l'autorizzazioneserviceusage.services.enable. Scopri come concedere i ruoli.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Installa Google Cloud CLI.
-
Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.
-
Per inizializzare gcloud CLI, esegui questo comando:
gcloud init -
Crea o seleziona un Google Cloud progetto.
Ruoli richiesti per selezionare o creare un progetto
- Seleziona un progetto: la selezione di un progetto non richiede un ruolo IAM specifico. Puoi selezionare qualsiasi progetto per il quale ti è stato concesso un ruolo.
-
Crea un progetto: per creare un progetto, devi disporre del ruolo Autore progetto
(
roles/resourcemanager.projectCreator), che contiene l'autorizzazioneresourcemanager.projects.create. Scopri come concedere i ruoli.
-
Creare un progetto Google Cloud :
gcloud projects create PROJECT_ID
Sostituisci
PROJECT_IDcon un nome per il progetto Google Cloud che stai creando. -
Seleziona il progetto Google Cloud che hai creato:
gcloud config set project PROJECT_ID
Sostituisci
PROJECT_IDcon il nome del progetto Google Cloud .
-
Verifica che la fatturazione sia attivata per il tuo progetto Google Cloud .
Abilita le API richieste:
Ruoli richiesti per abilitare le API
Per abilitare le API, devi disporre del ruolo IAM Amministratore utilizzo dei servizi (
roles/serviceusage.serviceUsageAdmin), che include l'autorizzazioneserviceusage.services.enable. Scopri come concedere i ruoli.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Concedi ruoli al tuo account utente. Esegui il seguente comando una volta per ciascuno dei seguenti ruoli IAM:
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Sostituisci quanto segue:
PROJECT_ID: il tuo ID progetto.USER_IDENTIFIER: l'identificatore del tuo account utente . Ad esempio:myemail@example.com.ROLE: il ruolo IAM che concedi al tuo account utente.
- Crea un account Hugging Face, se non ne hai già uno.
- Assicurati di avere un token Hugging Face.
- Assicurati che il tuo progetto disponga di una quota sufficiente per le GPU B200 e H200. Per saperne di più, consulta Pianificare la quota di GPU e Quota di GPU.
prepara l'ambiente
In questo tutorial utilizzi Cloud Shell.
Vai alla consoleGoogle Cloud .
Nella parte superiore della finestra della console Google Cloud , fai clic sul pulsante Attiva Cloud Shell.
Imposta le seguenti variabili di ambiente:
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_REGION=CONTROL_PLANE_REGION export NODE_ZONE=NODE_ZONE export CLUSTER_NAME=CLUSTER_NAME export GPU_TYPE=GPU_TYPE export MACHINE_TYPE=MACHINE_TYPE export KSA_NAME=generic-ksa export NAMESPACE=default export RESERVATION=RESERVATION export LUSTRE_NAME=LUSTRE_NAME export HF_TOKEN=YOUR_HF_TOKEN export WANDB_API_KEY=YOUR_WANDB_API_KEYSostituisci i seguenti valori:
CLUSTER_NAME: il nome del cluster GKE.CONTROL_PLANE_REGION: la regione Compute Engine per il control plane del cluster GKE.NODE_ZONE: la zona per i tuoi nodi. Seleziona una zona in cui sono disponibili le GPU NVIDIA B200 o H200.GPU_TYPE: l'acceleratore che hai prenotato nella prenotazione di capacità di Compute Engine. Deve essere uno dei seguenti valori:nvidia-b200: NVIDIA B200 (180 GB)nvidia-h200-141gb: NVIDIA H200 (141 GB)
MACHINE_TYPE: il tipo di macchina da utilizzare:- Per le GPU NVIDIA B200 (180 GB), utilizza
a4-highgpu-8go versioni successive. - Per le GPU NVIDIA H200 (141 GB), utilizza
a3-ultragpu-8go versioni successive.
- Per le GPU NVIDIA B200 (180 GB), utilizza
RESERVATION: il nome della prenotazione GPU.LUSTRE_NAME: il nome dell'istanza Lustre.YOUR_HF_TOKEN: il tuo token Hugging Face.YOUR_WANDB_API_KEY: la tua chiave API Wandb.
Crea le seguenti variabili di ambiente per la rete:
export NETWORK="NETWORK-NAME" export GVNIC_NETWORK_PREFIX="GVNIC-NAME" export RDMA_NETWORK_PREFIX="RDMA-NAME"Sostituisci i seguenti valori:
NETWORK-NAME: il nome della rete per GKE.GVNIC-NAME: il prefisso per il nome della rete gVNIC. Puoi utilizzare qualsiasi prefisso.RDMA-NAME: il prefisso per la rete di accesso diretto alla memoria (RDMA) remota. Puoi utilizzare qualsiasi prefisso.
Configurazione dell'infrastruttura
In questa sezione crei reti VPC e un cluster GKE.
Crea una rete VPC
Crea una rete VPC per l'interfaccia gVNIC:
gcloud compute networks create ${NETWORK} --subnet-mode=auto gcloud compute networks create ${GVNIC_NETWORK_PREFIX}-net \ --subnet-mode=custom gcloud compute networks subnets create ${GVNIC_NETWORK_PREFIX}-sub \ --network=${GVNIC_NETWORK_PREFIX}-net \ --region=${CONTROL_PLANE_REGION} \ --range=192.168.0.0/24 gcloud compute firewall-rules create ${GVNIC_NETWORK_PREFIX}-internal \ --network=${GVNIC_NETWORK_PREFIX}-net \ --action=ALLOW \ --rules=tcp:0-65535,udp:0-65535,icmp \ --source-ranges=192.168.0.0/16Crea una rete VPC e subnet per RDMA che includa otto subnet per otto GPU:
gcloud compute networks create ${RDMA_NETWORK_PREFIX}-net \ --network-profile=${NODE_ZONE}-vpc-roce \ --subnet-mode=custom for N in $(seq 0 7); do gcloud compute networks subnets create ${RDMA_NETWORK_PREFIX}-sub-$N \ --network=${RDMA_NETWORK_PREFIX}-net \ --region=${CONTROL_PLANE_REGION} \ --range=192.168.$((N+1)).0/24 & done wait
Crea il cluster GKE
Puoi impostare NeMo RL in un cluster GKE Standard.
Crea un cluster standard:
gcloud container clusters create ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --enable-dataplane-v2 \ --enable-ip-alias \ --enable-multi-networking \ --addons=RayOperator,LustreCsiDriver \ --enable-legacy-lustre-port \ --machine-type=n2-highmem-80 \ --num-nodes=1 \ --min-nodes=1 \ --max-nodes=5 \ --enable-autoscaling \ --network=${NETWORK}Recupera le credenziali per il tuo cluster:
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION}Crea il pool di nodi GPU:
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --location=${CONTROL_PLANE_REGION} \ --node-locations=${NODE_ZONE} \ --machine-type=${MACHINE_TYPE} \ --accelerator=type=${GPU_TYPE},count=8,gpu-driver-version=DEFAULT \ --reservation-affinity=specific \ --reservation=${RESERVATION} \ --enable-autoscaling \ --num-nodes=0 \ --total-max-nodes=2 \ --additional-node-network=network=${GVNIC_NETWORK_PREFIX}-net,subnetwork=${GVNIC_NETWORK_PREFIX}-sub \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-0 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-1 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-2 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-3 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-4 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-5 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-6 \ --additional-node-network=network=${RDMA_NETWORK_PREFIX}-net,subnetwork=${RDMA_NETWORK_PREFIX}-sub-7Installa il programma di installazione NCCL RDMA:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
Configurare i mapping di rete
Salva il seguente manifest come
network-mapping.yaml:Applica il manifest:
envsubst < network-mapping.yaml > network-mapping-updated.yaml kubectl apply -f network-mapping-updated.yaml
Preparare lo spazio di archiviazione
In questa sezione creerai un'istanza Managed Lustre, che esegue il provisioning dello spazio di archiviazione ad alte prestazioni necessario per il tuo carico di lavoro RL.
Alloca un intervallo di indirizzi IP per l'accesso ai servizi privati:
gcloud compute addresses create ${LUSTRE_NAME}-range \ --global --purpose=VPC_PEERING \ --prefix-length=20 --network=${NETWORK}Connetti il peering:
gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=${LUSTRE_NAME}-range \ --network=${NETWORK}Crea un'istanza Managed Lustre:
gcloud lustre instances create ${LUSTRE_NAME} \ --per-unit-storage-throughput=500 \ --capacity-gib=18000 \ --filesystem=lustrefs \ --location=${NODE_ZONE} \ --network=projects/${PROJECT_ID}/global/networks/${NETWORK} \ --gke-support-enabledAccedi a un'istanza Managed Lustre esistente utilizzando il driver CSI Managed Lustre
Estrai l'indirizzo IP dell'istanza Managed Lustre.
export LUSTRE_IP=$(gcloud lustre instances describe ${LUSTRE_NAME} \ --location=$NODE_ZONE --format="value(mountPoint)" | awk -F'@' '{print $1}')Esamina il manifest di
lustre-pv.yaml.Applica il manifest:
envsubst < lustre-pv.yaml > lustre-pv-updated.yaml kubectl apply -f lustre-pv-updated.yamlEsamina il manifest di
lustre-pvc.yaml.Applica il manifest:
kubectl apply -f lustre-pvc.yaml
Esegui il deployment di RayCluster
In questa sezione, clona il repository di esempio, prepara i manifest e deploy Ray cluster:
Clona il repository di esempio:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samplesVai alla directory di lavoro:
cd ai-ml/nemo-rl-on-gke/nemoRLIspeziona il manifest
values.yaml:Sostituisci
NCCL_TUNER_CONFIG_PATHcon uno dei seguenti valori, in base all'acceleratore che utilizzi in questo tutorial:- NVIDIA B200 (180 GB):
/usr/local/gib/configs/tuner_config_a4.txtpb - NVIDIA H200 (141 GB):
/usr/local/gib/configs/tuner_config_a3u.txtpb
In questo manifest, il nodo head gestisce il job e ospita la dashboard Ray. I nodi worker eseguono i job di addestramento.
- NVIDIA B200 (180 GB):
Esegui il deployment del cluster Ray:
export REPLICA_COUNT=2 helm install ray-cluster . \ --set additionalWorkerGroups.worker-grp-0.replicas=$REPLICA_COUNTPer questo tutorial, utilizzi due nodi di lavoro. Se vuoi modificare il numero di nodi worker, modifica il valore di
REPLICA_COUNT.Verifica che i nodi worker e head siano in esecuzione:
kubectl get podsL'output è simile al seguente:
NAME READY STATUS RESTARTS AGE ray-cluster-kuberay-head-sw7dp 3/3 Running 0 33h ray-cluster-kuberay-worker-grp-0-worker-gkbxw 3/3 Running 0 33h ray-cluster-kuberay-worker-grp-0-worker-kdg62 3/3 Running 0 33hVerifica che il cluster Ray sia in esecuzione:
kubectl ray get clusterL'output è simile al seguente:
NAME NAMESPACE DESIRED WORKERS AVAILABLE WORKERS CPUS GPUS TPUS MEMORY CONDITION STATUS AGE ray-cluster-kuberay default 2 2 618 17 0 1573741824k RayClusterProvisioned ready 33h
Avvia il job GRPO
Quando il cluster Ray è pronto, puoi inviare un job Ray al cluster Ray in esecuzione su GKE. NeMo RL scarica automaticamente il modello durante l'esecuzione del job di addestramento RL.
Per inviare un job Ray, avvia una sessione interattiva per eseguire il job.
Per stabilire una connessione locale al cluster Ray, esegui questo comando:
kubectl ray session ray-cluster-kuberayQuesto comando avvia l'inoltro delle porte tra la tua macchina locale e il nodo head Ray nel tuo cluster GKE. Tieni presente che il terminale sarà occupato mentre questa sessione è attiva; per procedere, apri un'istanza del terminale separata.
Modifica il file
gemma3-27b-gsm8k.sh:Sostituisci i seguenti valori nel file
gemma3-27b-gsm8k.sh:YOUR_WANDB_API_KEY: la tua chiave API WandB.YOUR_HF_TOKEN: il tuo token Hugging Face.
In questo file puoi vedere la configurazione per eseguire un job con il modello gemma3-27b-it sul set di dati GSM8k. Per completare la pipeline di addestramento GRPO, questo script definisce i seguenti parametri:
num_prompts_per_step: 16enum_generations_per_prompt: 32: il modello Gemma3-27b-it genera un ampio gruppo di risposte per ogni prompt. In questa configurazione, il modello produce 512 risposte totali (16 × 32 = 512).policy.generation.colocated.enabled=False: questo parametro disattiva la funzionalità di generazione in collocazione, il che significa che il modello non genera risposte nello stesso nodo del processo di addestramento. Nell'RL standard, le stesse GPU gestiscono sia l'addestramento che la generazione. In questa configurazione di NeMo RL, dedichi nodi specifici (gestiti con il parametropolicy.generation.colocated.resources) esclusivamente all'inferenza vLLM, mentre il resto del cluster si concentra sui calcoli di addestramento più pesanti. Separando questi carichi di lavoro, eviti la contesa delle risorse tra i buffer di addestramento a uso intensivo di memoria e i carichi di lavoro di inferenza a uso intensivo di calcolo.
Per inviare il Job, esegui questo comando:
bash gemma3-27b-it/gemma3-27b-gsm8k.shQuando il job è in esecuzione, l'output mostra i risultati dell'addestramento, la tempistica e le metriche di rendimento.
Monitorare lo stato del job GRPO
Al termine del job, NeMo RL archivia i checkpoint nel percorso configurato.
Per controllare l'output del job GRPO, crea una sessione SSH nel container
ray-head:kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -c ray-head -- bashInstalla l'utilità apt tree nel terminale del container
ray-head:apt update && apt install -y treeL'output è simile al seguente:
root@ray-cluster-kuberay-worker-grp-0-worker-gkbxw:/opt/nemo-rl# tree /data/nemo_rl_gemma3_27b_3_17/ /data/nemo_rl_gemma3_27b_3_17/ `-- step_10 |-- config.yaml |-- policy | |-- optimizer | | |-- __0_0.distcp | | |-- __10_0.distcp | | |-- __11_0.distcp | | |-- __12_0.distcp | | |-- __13_0.distcp | | |-- __14_0.distcp | | |-- __15_0.distcp | | |-- __1_0.distcp | | |-- __2_0.distcp | | |-- __3_0.distcp | | |-- __4_0.distcp | | |-- __5_0.distcp | | |-- __6_0.distcp | | |-- __7_0.distcp | | |-- __8_0.distcp | | `-- __9_0.distcp | |-- tokenizer | | |-- chat_template.jinja | | |-- special_tokens_map.json | | |-- tokenizer.json | | `-- tokenizer_config.json | `-- weights | |-- __0_0.distcp | |-- __10_0.distcp | |-- __11_0.distcp | |-- __12_0.distcp | |-- __13_0.distcp | |-- __14_0.distcp | |-- __15_0.distcp | |-- __1_0.distcp | |-- __2_0.distcp | |-- __3_0.distcp | |-- __4_0.distcp | |-- __5_0.distcp | |-- __6_0.distcp | |-- __7_0.distcp | |-- __8_0.distcp | `-- __9_0.distcp |-- train_dataloader.pt `-- training_info.json 6 directories, 39 files ```
Esegui la pulizia
Per evitare che ti vengano addebitati dei costi, elimina le risorse:
helm delete ray-cluster
gcloud container clusters delete ${CLUSTER_NAME} \
--location=${CONTROL_PLANE_REGION} \
--quiet
gcloud lustre instances delete ${LUSTRE_NAME} --location=${NODE_ZONE} --quiet
gcloud services vpc-peerings delete \
--service=servicenetworking.googleapis.com \
--network=${NETWORK}
gcloud compute addresses delete ${LUSTRE_NAME}-range --global --quiet
gcloud compute firewall-rules delete ${GVNIC_NETWORK_PREFIX}-internal --quiet
gcloud compute networks subnets delete ${GVNIC_NETWORK_PREFIX}-sub \
--region=${CONTROL_PLANE_REGION} --quiet
gcloud compute networks delete ${GVNIC_NETWORK_PREFIX}-net --quiet
for N in $(seq 0 7); do
gcloud compute networks subnets delete ${RDMA_NETWORK_PREFIX}-sub-$N \
--region=${CONTROL_PLANE_REGION} --quiet &
done
wait
gcloud compute networks delete ${RDMA_NETWORK_PREFIX}-net --quiet
gcloud compute networks delete ${NETWORK} --quiet