Ce tutoriel explique comment orchestrer un environnement d'entraînement distribué pour l'apprentissage par renforcement (RL) sur Google Kubernetes Engine (GKE). Vous utilisez Ray et le framework NVIDIA NeMo RL pour configurer un environnement d'entraînement distribué afin d'affiner un modèle.
Ce tutoriel se concentre sur le pipeline d'entraînement Group Relative Policy Optimization (GRPO) sur GKE avec Ray et NeMo RL. GRPO est un algorithme d'apprentissage par renforcement conçu pour améliorer la capacité de raisonnement d'un modèle. Cet algorithme économe en mémoire simplifie le processus de RL en éliminant le Critic, ou modèle de valeur, et en utilisant à la place un calcul relatif basé sur les groupes.
Avant de suivre ce tutoriel, nous vous recommandons de suivre le tutoriel Ajuster et mettre à l'échelle l'apprentissage par renforcement avec Verl sur GKE. Le tutoriel suivant utilise la même configuration de cluster que le tutoriel sur le scaling et le fine-tuning du RL avec Verl.
Arrière-plan
Les sections suivantes présentent brièvement les concepts utilisés dans ce tutoriel.
Apprentissage par renforcement
L'apprentissage par renforcement enseigne aux modèles par l'expérience, l'exploration et le retour d'informations plutôt que par l'imitation statique. Bien que le pré-entraînement apprenne à un modèle quoi dire, l'apprentissage par renforcement qui utilise le feedback humain (RLHF) lui apprend à être utile, sûr et logique. L'apprentissage par renforcement sert de pont entre un modèle de base et un modèle affiné pour un cas d'utilisation spécialisé.
Pour en savoir plus, consultez Qu'est-ce que l'apprentissage par renforcement ?
Optimisation des stratégies relatives aux groupes (GRPO)
GRPO, un algorithme popularisé par DeepSeek, offre une alternative économe en mémoire à l'optimisation de la politique proximale (PPO) pour l'alignement des LLM en supprimant le modèle Critic. Au lieu d'un réseau Critic, GRPO génère un groupe de réponses pour la même requête et utilise la récompense moyenne de ce groupe comme référence.
Pour en savoir plus, consultez GRPO.
NVIDIA NeMo RL
NeMo RL est la bibliothèque Open Source de post-entraînement de NVIDIA conçue pour le RL évolutif. Faisant partie de l'écosystème plus vaste du framework NeMo, NeMo RL permet à la fois des expériences à petite échelle sur un seul GPU et des déploiements multinœuds sur des milliers de GPU.
Pour en savoir plus, consultez NVIDIA NeMo RL.
Ensemble de données GSM8k
Dans ce tutoriel, vous allez utiliser l'ensemble de données GSM8k, qui contient 8 500 problèmes de mathématiques de haute qualité, linguistiquement diversifiés et adaptés au niveau de l'école primaire.
En utilisant GSM8k et GRPO, le modèle génère un groupe de n réponses différentes pour le même problème. GRPO compare ces réponses à la moyenne du groupe. Le modèle est davantage récompensé pour les chemins qui sont constamment corrects et logiques par rapport au reste du groupe. Au fil du temps, le modèle apprend que la meilleure façon de maximiser la récompense est d'articuler clairement ses étapes, ce qui réduit efficacement la récompense pour les réponses peu performantes.
Pour en savoir plus, consultez GSM8k.
Objectifs
Ce tutoriel vous explique comment configurer le RL sur GKE avec NeMo RL en suivant les étapes suivantes :
- Préparez votre environnement.
- Configurez un cluster GKE avec des GPU B200 ou H200.
- Configurez KubeRay pour gérer un cluster Ray distribué.
- Utilisez Managed Lustre pour un stockage hautes performances.
- Exécutez une tâche d'entraînement GRPO qui utilise NeMo RL.
Avant de commencer
- Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $de crédits sans frais pour exécuter, tester et déployer des charges de travail.
-
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez les API requises :
Rôles requis pour activer les API
Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (
roles/serviceusage.serviceUsageAdmin), qui contient l'autorisationserviceusage.services.enable. Découvrez comment attribuer des rôles.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Installez la Google Cloud CLI.
-
Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.
-
Pour initialiser la gcloud CLI, exécutez la commande suivante :
gcloud init -
Créez ou sélectionnez un projet Google Cloud .
Rôles requis pour sélectionner ou créer un projet
- Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
-
Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (
roles/resourcemanager.projectCreator), qui contient l'autorisationresourcemanager.projects.create. Découvrez comment attribuer des rôles.
-
Créez un projet Google Cloud :
gcloud projects create PROJECT_ID
Remplacez
PROJECT_IDpar le nom du projet Google Cloud que vous créez. -
Sélectionnez le projet Google Cloud que vous avez créé :
gcloud config set project PROJECT_ID
Remplacez
PROJECT_IDpar le nom de votre projet Google Cloud .
-
Vérifiez que la facturation est activée pour votre projet Google Cloud .
Activez les API requises :
Rôles requis pour activer les API
Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (
roles/serviceusage.serviceUsageAdmin), qui contient l'autorisationserviceusage.services.enable. Découvrez comment attribuer des rôles.gcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
Attribuez des rôles à votre compte utilisateur. Exécutez la commande suivante une fois pour chacun des rôles IAM suivants :
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Remplacez les éléments suivants :
PROJECT_ID: ID de votre projetUSER_IDENTIFIER: identifiant de votre compte d'utilisateur. Par exemple,myemail@example.com.ROLE: rôle IAM que vous accordez à votre compte utilisateur.
- Créez un compte Hugging Face si vous n'en possédez pas.
- Assurez-vous de disposer d'un jeton Hugging Face.
- Assurez-vous que votre projet dispose d'un quota suffisant pour les GPU B200 et H200. Pour en savoir plus, consultez Planifier le quota de GPU et Quota de GPU.
Préparer votre environnement
Dans ce tutoriel, vous utilisez Cloud Shell.
Accédez à la consoleGoogle Cloud .
En haut de la fenêtre de la console Google Cloud , cliquez sur le bouton Activer Cloud Shell.
Définissez les variables d'environnement suivantes :
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATION export NODE_LOCATION=NODE_LOCATION export CLUSTER_NAME=CLUSTER_NAME export GPU_TYPE=GPU_TYPE export MACHINE_TYPE=MACHINE_TYPE export GKE_VERSION=GKE_VERSION export KSA_NAME=generic-ksa export NAMESPACE=default export GS_BUCKET=BUCKET_NAME-${PROJECT_ID} export HF_TOKEN=YOUR_HUGGING_FACE_TOKENRemplacez les valeurs suivantes :
CLUSTER_NAME: nom de votre cluster GKE.CONTROL_PLANE_LOCATION: région Compute Engine du plan de contrôle du cluster GKE.NODE_LOCATION: emplacement de vos nœuds. Sélectionnez une zone où les GPU NVIDIA B200 ou H200 sont disponibles.GPU_TYPE: accélérateur que vous avez réservé dans la réservation de capacité Compute Engine. Il doit s'agir de l'une des options suivantes :nvidia-b200: NVIDIA B200 (180 Go)nvidia-h200-141gb: NVIDIA H200 (141 Go)
MACHINE_TYPE: type de machine à utiliser :- Pour les GPU NVIDIA B200 (180 Go), utilisez la version
a4-highgpu-8gou ultérieure. - Pour les GPU NVIDIA H200 (141 Go), utilisez
a3-ultragpu-8gou version ultérieure.
- Pour les GPU NVIDIA B200 (180 Go), utilisez la version
GKE_VERSION: version de GKE à utiliser :- Pour les GPU NVIDIA B200 (180 Go), utilisez la version
1.32.2-gke.1422000ou ultérieure. - Pour les GPU NVIDIA H200 (141 Go), utilisez
1.31.4-gke.1183000ou version ultérieure.
- Pour les GPU NVIDIA B200 (180 Go), utilisez la version
BUCKET_NAME: nom de base de votre bucket Cloud Storage.YOUR_HUGGING_FACE_TOKEN: votre jeton Hugging Face.
Créez les variables d'environnement suivantes pour le réseau :
export GVNIC_NETWORK_PREFIX="GVNIC-NAME" export RDMA_NETWORK_PREFIX="RDMA-NAME"Remplacez les valeurs suivantes :
GVNIC-NAME: préfixe du nom du réseau gVNIC. Vous pouvez utiliser le préfixe de votre choix.RDMA-NAME: préfixe du réseau d'accès direct à la mémoire à distance (RDMA). Vous pouvez utiliser le préfixe de votre choix.
Configurer l'infrastructure
Dans cette section, vous allez créer des réseaux VPC et un cluster GKE.
Créer un réseau VPC
Créez un réseau VPC pour l'interface gVNIC :
gcloud compute networks create ${GVNIC_NETWORK_PREFIX}-net \ --project=${PROJECT_ID} \ --subnet-mode=custom gcloud compute networks subnets create ${GVNIC_NETWORK_PREFIX}-sub \ --network=${GVNIC_NETWORK_PREFIX}-net \ --location=${CONTROL_PLANE_LOCATION} \ --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/16Créez un réseau et des sous-réseaux VPC pour RDMA, y compris huit sous-réseaux pour huit GPU :
gcloud compute networks create ${RDMA_NETWORK_PREFIX}-net \ --network-profile=${CONTROL_PLANE_LOCATION}-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 \ --location=${CONTROL_PLANE_LOCATION} \ --range=192.168.$((N+1)).0/24 & done wait
Créer le cluster GKE
Vous pouvez définir NeMo RL dans un cluster GKE Autopilot ou GKE Standard. Nous vous recommandons d'utiliser un cluster GKE Autopilot pour une expérience Kubernetes entièrement gérée. Pour choisir le mode de fonctionnement GKE le mieux adapté à vos charges de travail, consultez À propos des modes de fonctionnement GKE.
Autopilot
Créez un cluster Autopilot :
gcloud container clusters create-auto ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-multi-networking \ --enable-ray-operatorObtenez les identifiants de votre cluster :
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION}Installez le programme d'installation NCCL RDMA pour Autopilot :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer-autopilot.yaml
Standard
Créez un cluster standard :
gcloud container clusters create ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-dataplane-v2 \ --enable-ip-alias \ --enable-multi-networking \ --addons=RayOperator \ --num-nodes=1Obtenez les identifiants de votre cluster :
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${CONTROL_PLANE_LOCATION}Créez le pool de nœuds GPU :
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER_NAME} \ --node-locations=${NODE_LOCATION} \ --machine-type=${MACHINE_TYPE} \ --accelerator=type=${GPU_TYPE},count=8 \ --spot \ --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-7Installez le programme d'installation NCCL RDMA :
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/refs/heads/master/gpudirect-rdma/nccl-rdma-installer.yaml
Configurer les mappages réseau
Enregistrez le manifeste suivant sous le nom
network-mapping.yaml:Appliquez le fichier manifeste :
kubectl apply -f network-mapping.yaml
Préparer l'espace de stockage
Dans cette section, vous allez créer des buckets Cloud Storage et une instance Lustre gérée, qui provisionne le stockage hautes performances requis pour votre charge de travail RL.
Créez un bucket Cloud Storage :
gcloud storage buckets create gs://${GS_BUCKET} \ --location=${CONTROL_PLANE_LOCATION} \ --enable-hierarchical-namespace \ --uniform-bucket-level-accessCréez un compte de service Kubernetes (KSA) et associez-le au bucket :
kubectl create serviceaccount ${KSA_NAME} --namespace ${NAMESPACE} gcloud storage buckets add-iam-policy-binding gs://${GS_BUCKET} \ --member "principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KSA_NAME}" \ --role "roles/storage.objectUser"Pour configurer Managed Lustre, procédez comme suit :
- Créez une instance Managed Lustre en suivant la procédure décrite dans Créer une instance Managed Lustre. Assurez-vous que l'instance utilise le même réseau que votre cluster GKE.
- Accédez à l'instance Managed Lustre en suivant la procédure décrite dans Accéder à une instance Managed Lustre existante.
Déployer un RayCluster
Dans cette section, vous allez cloner l'exemple de dépôt, préparer les fichiers manifestes et exécuter un script launcher.sh :
Clonez l'exemple de dépôt :
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samplesAccédez au répertoire de travail :
cd ai-ml/nemo-rl-on-gke/nemoRLInspectez le fichier manifeste
values.yaml:Remplacez
NCCL_TUNER_CONFIG_PATHpar l'une des valeurs suivantes, en fonction de l'accélérateur que vous utilisez dans ce tutoriel :- NVIDIA B200 (180 Go) :
/usr/local/gib/configs/tuner_config_a4.txtpb - NVIDIA H200 (141 Go) :
/usr/local/gib/configs/tuner_config_a3u.txtpb
Dans ce fichier manifeste, le nœud principal gère le job et héberge le tableau de bord Ray. Les nœuds de calcul exécutent les tâches d'entraînement.
- NVIDIA B200 (180 Go) :
Installez le cluster Ray :
export REPLICA_COUNT=2 helm install ray-cluster . \ --set values.additionalWorkerGroups.worker-grp-0.replicas=$REPLICA_COUNTPour ce tutoriel, vous utilisez deux nœuds de calcul. Si vous souhaitez modifier le nombre de nœuds de calcul, modifiez la valeur
REPLICA_COUNT.Pour déployer le cluster Ray, exécutez le script
launcher.sh:bash launcher.shVérifiez que les nœuds de calcul et principaux sont en cours d'exécution :
kubectl get podsLe résultat ressemble à ce qui suit :
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 33hVérifiez que le cluster Ray est en cours d'exécution :
kubectl ray get clustersLe résultat ressemble à ce qui suit :
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
Lancer le job GRPO
Une fois votre cluster Ray prêt, vous pouvez envoyer un job Ray à votre cluster Ray en cours d'exécution sur GKE. NeMo RL télécharge automatiquement le modèle lors de l'exécution du job d'entraînement RL.
Pour envoyer un job Ray, démarrez une session interactive pour l'exécuter.
Pour établir une connexion locale à votre cluster Ray, exécutez cette commande :
kubectl ray session ray-cluster-kuberayCette commande lance le transfert de port entre votre machine locale et le nœud principal Ray de votre cluster GKE. Notez que votre terminal sera occupé pendant que cette session est active. Pour continuer, ouvrez une autre instance de terminal.
Modifiez le fichier
gemma3-27b-gsm8k.shcomme suit :Remplacez les valeurs suivantes dans le fichier
gemma3-27b-gsm8k.sh:YOUR_WANDB_API_KEY: votre clé API WandB.YOUR_HF_TOKEN: votre jeton Hugging Face.
Dans ce fichier, vous pouvez voir la configuration permettant d'exécuter un job avec le modèle gemma3-27b-it sur l'ensemble de données GSM8k. Pour exécuter le pipeline d'entraînement GRPO, ce script définit les paramètres suivants :
num_prompts_per_step: 16etnum_generations_per_prompt: 64: le modèle Gemma3-27b-it génère un grand nombre de réponses pour chaque requête. Dans cette configuration, le modèle produit 1 024 réponses au total (16 x 64 = 1 024).policy.generation.colocated.enabled=False: ce paramètre désactive la fonctionnalité de génération colocalisée, ce qui signifie que le modèle ne génère pas de réponses dans le même nœud que le processus d'entraînement. Dans l'apprentissage par renforcement standard, les mêmes GPU gèrent l'entraînement et la génération. Dans cette configuration NeMo RL, vous dédiez des nœuds spécifiques (gérés avec le paramètrepolicy.generation.colocated.resources) uniquement à l'inférence vLLM, tandis que le reste du cluster se concentre sur les calculs d'entraînement intensifs. En séparant ces charges de travail, vous évitez les conflits de ressources entre les tampons d'entraînement gourmands en mémoire et les charges de travail d'inférence gourmandes en ressources de calcul.
Pour envoyer le job, exécutez la commande suivante :
bash gemma3-27b-it/gemma3-27b-gsm8k.shLorsque le job est en cours d'exécution, la sortie affiche les résultats de l'entraînement, le timing et les métriques de performances.
Surveiller l'état du job GRPO
Une fois le job terminé, NeMo RL stocke les points de contrôle dans le chemin configuré.
Installez l'utilitaire apt-tree :
apt install treePour surveiller l'état du job GRPO, vérifiez les journaux du nœud principal Ray :
kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -c ray-head -- bashLe résultat ressemble à ce qui suit :
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
Effectuer un nettoyage
Pour éviter que des frais ne vous soient facturés, supprimez les ressources :
helm delete ray-cluster
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_LOCATION}
gcloud storage rm -r gs://${GS_BUCKET}