במדריך הזה תלמדו איך לתזמן סביבת אימון מבוזרת ללמידת חיזוקים ב-Google Kubernetes Engine (GKE). אתם משתמשים ב-Ray ובמסגרת verl (Volcano Engine Reinforcement Learning) כדי להגדיר סביבת אימון מבוזרת לצורך כוונון עדין של מודל Qwen2.5-32B-Instruct במערך הנתונים GSM8K.
המדריך הזה מתמקד בצינור עיבוד נתונים לאימון של Group Relative Policy Optimization (GRPO) ב-GKE עם Ray ו-verl. GRPO הוא אלגוריתם ללמידה עם חיזוקים שנועד לשפר את יכולת ההסקה של מודל. האלגוריתם הזה חוסך בזיכרון ומפשט את תהליך הלמידה עם חיזוקים (RL) על ידי ביטול ה-Critic, או מודל הערך, ושימוש בחישוב יחסי שמבוסס על קבוצות במקום זאת.
המדריך הזה הוא נקודת התחלה טובה אם אתם צריכים להגדיר סביבת אימון מבוזרת שבה הנתונים, משקלי המודל ומנוע האימון מופרדים כדי לשפר את היעילות.
המדריך הזה תומך בארכיטקטורות ה-GPU הבאות:
- צמתי GPU מבוססי Intel או AMD: הגדרה ושינוי גודל באמצעות NVIDIA B200 או H200 GPUs, באמצעות הקצאת משאבים דינמית (DRA) של GKE לנתיב Autopilot.
- צמתים מבוססי Arm A4X (GB200): הגדרה ושינוי גודל באמצעות NVIDIA GB200 Grace Blackwell Superchips, באמצעות הקצאת משאבים דינמית (DRA) של GKE ו-Multi-Node NVLink (IMEX).
רקע
בקטעים הבאים מופיעה סקירה כללית קצרה של המושגים שבהם נעשה שימוש במדריך הזה.
למידת חיזוקים (RL)
ב-RL, המודלים לומדים מתוך ניסיון, מחקר ומשוב, ולא מתוך חיקוי סטטי. במהלך האימון המוקדם, המודל לומד מה לומר, אבל במהלך למידה ממשוב אנושי (RLHF), הוא לומד איך להיות מועיל, בטוח והגיוני. RL משמש כגשר בין מודל בסיסי לבין מודל מכוונן לשימוש ספציפי.
מידע נוסף זמין במאמר מה זה למידת חיזוק?
אופטימיזציה של מדיניות יחסית לקבוצה (GRPO)
GRPO, אלגוריתם שזכה לפופולריות בזכות DeepSeek, מציע חלופה חסכונית בזיכרון ל-Proximal Policy Optimization (PPO) להתאמת LLM, על ידי הסרת מודל ה-Critic. במקום רשת מבקרת, GRPO יוצרת קבוצת תגובות לאותה הנחיה ומשתמשת בתגמול הממוצע של הקבוצה הזו כנקודת בסיס.
מידע נוסף זמין במאמר בנושא GRPO.
Volcano Engine Reinforcement Learning (verl)
verl הוא פריימוורק עתיר ביצועים שנועד לטפל בדפוסי זיכרון וחישוב מורכבים של RL מבוסס-LLM.
מידע נוסף זמין במאמר בנושא verl.
מטרות
במדריך הזה תלמדו איך להגדיר למידת חיזוק ב-GKE באמצעות verl. לשם כך, תצטרכו לבצע את השלבים הבאים:
- הגדרת אשכול GKE עם A4X (GB200 Superchips), A4 (B200 GPUs) או A3 Ultra (H200 GPUs).
- הגדרת KubeRay לניהול אשכול Ray מבוזר.
- משתמשים ב-Cloud Storage FUSE כדי לטעון קטגוריה של Cloud Storage בכל הצמתים.
- מריצים משימת אימון של GRPO באמצעות verl כדי להתאים את מודל Qwen2.5-32B-Instruct למערך הנתונים GSM8K.
לפני שמתחילים
- נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
-
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:
gcloud init -
יוצרים או בוחרים Google Cloud פרויקט.
תפקידים שנדרשים כדי לבחור או ליצור פרויקט
- Select a project (בחירת פרויקט): כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שהוקצה לכם בו תפקיד.
-
יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (יצירת פרויקטים) (
roles/resourcemanager.projectCreator), שכולל את ההרשאהresourcemanager.projects.create. איך מקצים תפקידים
-
יוצרים Google Cloud פרויקט:
gcloud projects create PROJECT_ID
מחליפים את
PROJECT_IDבשם של פרויקט Google Cloud שיוצרים. -
בוחרים את הפרויקט שיצרתם: Google Cloud
gcloud config set project PROJECT_ID
מחליפים את
PROJECT_IDבשם הפרויקט ב- Google Cloud .
מפעילים את ממשקי ה-API הנדרשים:
תפקידים שנדרשים להפעלת ממשקי API
כדי להפעיל ממשקי API, נדרשת ההרשאה
serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידיםgcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:
gcloud init -
יוצרים או בוחרים Google Cloud פרויקט.
תפקידים שנדרשים כדי לבחור או ליצור פרויקט
- Select a project (בחירת פרויקט): כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שהוקצה לכם בו תפקיד.
-
יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (יצירת פרויקטים) (
roles/resourcemanager.projectCreator), שכולל את ההרשאהresourcemanager.projects.create. איך מקצים תפקידים
-
יוצרים Google Cloud פרויקט:
gcloud projects create PROJECT_ID
מחליפים את
PROJECT_IDבשם של פרויקט Google Cloud שיוצרים. -
בוחרים את הפרויקט שיצרתם: Google Cloud
gcloud config set project PROJECT_ID
מחליפים את
PROJECT_IDבשם הפרויקט ב- Google Cloud .
מפעילים את ממשקי ה-API הנדרשים:
תפקידים שנדרשים להפעלת ממשקי API
כדי להפעיל ממשקי API, נדרשת ההרשאה
serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידיםgcloud services enable container.googleapis.com
storage.googleapis.com compute.googleapis.com -
מעניקים תפקידים לחשבון המשתמש. מריצים את הפקודה הבאה לכל אחד מהתפקידים הבאים ב-IAM:
roles/container.admin, roles/iam.serviceAccountAdmin, roles/storage.admingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT_ID: מזהה הפרויקט. -
USER_IDENTIFIER: המזהה של חשבון המשתמש . לדוגמה,myemail@example.com. -
ROLE: תפקיד ה-IAM שאתם מקצים לחשבון המשתמש.
-
- אם עדיין אין לכם חשבון Hugging Face, אתם צריכים ליצור חשבון.
- מוודאים שיש לכם טוקן של Hugging Face.
- מוודאים שלפרויקט יש מכסת שימוש מספקת ל-A4X (GB200 Superchips), ל-A4 (B200 GPUs) או ל-A3 Ultra (H200 GPUs). מידע נוסף זמין במאמרים תכנון מכסת GPU ומכסת GPU.
- מוודאים שיש לכם הזמנת קיבולת פעילה לסוג המכונה של ה-GPU. מידע נוסף זמין במאמר בנושא שריין קיבולת באמצעות צוות התמיכה בחשבון.
- כדי להגדיר את A4X (GB200), צריך לוודא שHelm מותקן.
הכנת הסביבה
במדריך הזה משתמשים ב-Cloud Shell.
עוברים אל Google Cloud המסוף.
בחלק העליון של Google Cloud חלון המסוף, לוחצים על הלחצן Activate Cloud Shell (הפעלת Cloud Shell).
מגדירים את משתני הסביבה:
A4 ו-A3 Ultra
טייס אוטומטי
רגילה
A4X
export PROJECT_ID=$(gcloud config get project) export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") export CONTROL_PLANE_REGION=YOUR_REGION export NODE_ZONE=YOUR_ZONE export CLUSTER_NAME=YOUR_CLUSTER_NAME export KSA_NAME=YOUR_KSA_NAME export GS_BUCKET=YOUR_GCS_BUCKET-${PROJECT_ID} export NAMESPACE=default export GPU_TYPE=YOUR_GPU_TYPE export MACHINE_TYPE=YOUR_MACINE_TYPE export RESERVATION=YOUR_RESERVATION_NAME export HF_TOKEN=YOUR_HF_TOKEN # A4X (GB200 Superchips) only variables export NUM_GPU_NODES=4 export VERL_IMAGE=verlai/verl:vllm023.aarch64.dev1 export VERL_REF=ddbcdb7מחליפים את הערכים הבאים:
-
YOUR_REGION: האזור ב-Compute Engine של מישור הבקרה של אשכול GKE. -
YOUR_ZONE: האזור שבו הצמתים מוזמנים. מידע נוסף מופיע במאמר בנושא זמינות של GPU. -
YOUR_CLUSTER_NAME: השם של אשכול GKE. -
YOUR_KSA_NAME: השם של חשבון השירות של Kubernetes. -
YOUR_GCS_BUCKET: שם הבסיס של הקטגוריה ב-Cloud Storage. אין צורך לציין את הקידומתgs://. -
YOUR_GPU_TYPE: המאיץ שהזמנתם בהזמנת הקיבולת של Compute Engine. הערך חייב להיות אחד מהערכים הבאים:-
nvidia-gb200: A4X (GB200 Superchips) -
nvidia-b200: A4 (יחידות GPU מסוג B200) -
nvidia-h200-141gb: A3 Ultra (מעבדי GPU מדגם H200)
-
-
YOUR_MACHINE_TYPE: סוג המכונה לשימוש:- ב-A4X (GB200 Superchips), משתמשים ב-
a4x-highgpu-4g. - ל-A4 (יחידות GPU מסוג B200), צריך להשתמש בגרסה
a4-highgpu-8gואילך. - ב-A3 Ultra (יחידות GPU מדגם H200), צריך להשתמש בגרסה
a3-ultragpu-8gואילך.
- ב-A4X (GB200 Superchips), משתמשים ב-
YOUR_RESERVATION_NAME: השם של הזמנת הקיבולת.-
YOUR_HF_TOKEN: האסימון שלכם ב-Hugging Face. - מהדורת Standard של Google Kubernetes Engine (GKE) בלבד:
-
GVNIC_NAME(GKE Standard – A4 או A3 Ultra בלבד): התחילית של שם רשת gVNIC. אפשר להשתמש בכל קידומת שרוצים. -
RDMA_NAME(A4 או A3 Ultra בלבד): הקידומת של רשת הגישה הישירה לזיכרון (RDMA) מרחוק. אפשר להשתמש בכל קידומת שרוצים.
-
-
משכפלים את המאגר לדוגמה:
עוברים לספריית העבודה של מצב ה-GKE שבחרתם:
A4 ו-A3 Ultra
טייס אוטומטי
רגילה
A4X
אין צורך לשנות את הספרייה. אפשר להמשיך ישירות לקטע הבא.
הגדרת התשתית
בקטע הזה, יוצרים רשתות VPC רגילות ואת אשכול GKE.
יצירת רשתות ותת-רשתות של RDMA (GKE Standard – A4 ו-A3 Ultra בלבד)
A4 ו-A3 Ultra
טייס אוטומטי
הקטע הזה נדרש רק עבור מעבדי GKE Standard A4 ו-A3 Ultra GPU.
אם אתם משתמשים ב-Autopilot, דלגו על הקטע הזה ועברו ישירות אל יצירת אשכול GKE. GKE מקצה אוטומטית את רשתות ה-VPC ורשתות המשנה הנדרשות, ומשתמש ב-DRANET מנוהל של GKE כדי להקצות את המשאבים האלה ל-Pods. לא צריך ליצור ידנית תשתית רשת.
רגילה
יוצרים רשת VPC לממשק gVNIC:
יוצרים רשת VPC ל-RDMA:
יוצרים את 8 רשתות המשנה של RDMA עבור 8 יחידות ה-GPU:
A4X
הקטע הזה נדרש רק עבור מעבדי GKE Standard A4 ו-A3 Ultra GPU.
אם אתם משתמשים ביחידות GPU מסוג A4X (GB200), דלגו על הקטע הזה ועברו ישירות אל יצירת אשכול GKE. ב-GPU מסוג A4X (GB200) או ב-Autopilot, GKE יוצר את הרשתות באופן אוטומטי כשמאגר הצמתים משתמש בפרופיל רשת המאיצים auto. התוכנית של Cluster Toolkit מאפשרת את הפרופיל הזה באמצעות הדגל enable_dranet:true.
יצירת אשכול GKE
יוצרים אשכול GKE שתואם לארכיטקטורת ה-GPU:
A4 ו-A3 Ultra
בוחרים את מצב אשכול GKE שרוצים להשתמש בו:
טייס אוטומטי
יצירת אשכול Autopilot:
קבלת פרטי הכניסה לאשכול:
רגילה
יצירת אשכול רגיל:
קבלת פרטי הכניסה לאשכול:
יוצרים את מאגר הצמתים של ה-GPU. מאגרי הצמתים האלה משתמשים בהזמנה שלכם כדי להבטיח זמינות. מתחילים עם שני צמתים:
מתקינים את NCCL RDMA installer שמשמש לאשכולות רגילים:
A4X
יוצרים אשכול GKE ומאגר צמתים באמצעות Cluster Toolkit
gke-a4xblueprint. תוכנית האב-טיפוס מספקת את אשכול GKE, כולל מאגר הצמתים A4X שקשור להזמנה שלכם, רשתות המאיצים (gVNIC נוסף וארבע מסילות RDMA) ומנהל ההתקן המנוהל של DRANET שחושף את כרטיסי ה-NIC של CX-7 כמכשירי DRA.משתמשים בהוראות הפריסה של התוכנית כדי להגדיר את הפרמטרים (כמו
PROJECT_ID,CONTROL_PLANE_REGION,NODE_ZONE, הזמנה ו-NUM_GPU_NODES), ואז פורסים את האשכול. לחלופין, אפשר ליצור אשכול באופן ידני לפי המדריך ליצירת אשכול GKE ב-A4X.- קבלת פרטי הכניסה לאשכול:
gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}מוודאים שהאשכול חושף כרטיסי רשת של RDMA דרך DRA:
kubectl get deviceclassesהפלט חייב לכלול את המחרוזת
mrdma.google.com.מוודאים שצמתי A4X קיימים:
kubectl get nodes -l cloud.google.com/gke-accelerator=nvidia-gb200מתקינים את הפלאגין gIB NCCL (גרסת A4X):
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-rdma/nccl-rdma-installer-a4x.yamlמתקינים את הדרייבר NVIDIA DRA, שמספק ערוצי
ComputeDomain(IMEX) ל-NVLink מרובה צמתים:helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update kubectl create namespace nvidia-dra-driver-gpu kubectl apply -f - <<EOF apiVersion: v1 kind: ResourceQuota metadata: name: nvidia-dra-driver-gpu-quota namespace: nvidia-dra-driver-gpu spec: hard: pods: "$((2 * NUM_GPU_NODES + 1))" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: - system-node-critical - system-cluster-critical EOF helm upgrade --install nvidia-dra-driver-gpu nvidia/nvidia-dra-driver-gpu \ --version=25.3.1 --namespace nvidia-dra-driver-gpu \ --set nvidiaDriverRoot=/home/kubernetes/bin/nvidia \ --set resources.gpus.enabled=false \ --set kubeletPlugin.tolerations[0].key=nvidia.com/gpu \ --set kubeletPlugin.tolerations[0].operator=Exists \ --set kubeletPlugin.tolerations[1].key=kubernetes.io/arch \ --set kubeletPlugin.tolerations[1].operator=Existsמתקינים את האופרטור KubeRay, בהיקף של מרחב השמות של עומס העבודה:
kubectl create namespace ${NAMESPACE} helm repo add kuberay https://ray-project.github.io/kuberay-helm/ && helm repo update helm upgrade --install kuberay-operator kuberay/kuberay-operator \ --namespace ${NAMESPACE} \ --set singleNamespaceInstall=true --set "watchNamespace={${NAMESPACE}}"
הגדרת מיפויי רשת (GKE Standard – A4 ו-A3 Ultra בלבד)
A4 ו-A3 Ultra
טייס אוטומטי
השלב הזה נדרש להגדרות GPU ב-GKE Standard (רק A4 ו-A3 Ultra). אם אתם משתמשים ב-A4X (GB200), GKE מנהל את ממשקי הרשת באופן אוטומטי, ולכן אפשר לדלג על הקטע הזה.
רגילה
בודקים את קובץ המניפסט
network-mapping.yaml:החלת המניפסט:
A4X
השלב הזה נדרש להגדרות GPU ב-GKE Standard (רק A4 ו-A3 Ultra). אם אתם משתמשים ב-A4X (GB200), GKE מנהל את ממשקי הרשת באופן אוטומטי, ולכן אפשר לדלג על הקטע הזה.
הכנת הנתונים והאחסון
הגדרת משאבים של Cloud Storage ו-Kubernetes:
יוצרים קטגוריה של Cloud Storage:
יוצרים חשבון שירות של Kubernetes (KSA) ומקשרים אותו לדלי:
יוצרים את ה-Secret עבור Hugging Face:
בודקים את קובץ המניפסט
gcsfuse-storage.yaml:החלת המניפסט:
הגדרת DRANET
מגדירים את ה-DRANET:
A4 ו-A3 Ultra
טייס אוטומטי
יוצרים את מניפסט ComputeClass:
מחילים את
computeclass-dranet.yamlהמניפסט (שנוצר בשלב הקודם) ואתresourceclaim-dranet.yamlהמניפסט (שנכלל במאגר הדוגמאות):
רגילה
לא נדרשת הגדרה של DRANET. אפשר להמשיך ישירות לקטע הבא.
A4X
המשתנה DRANET מוגדר על ידי Cluster Toolkit. אפשר להמשיך ישירות לקטע הבא.
הכנת המודל והנתונים
מאכלסים את הקטגוריה של Cloud Storage במשקלים של המודל ובמערכי הנתונים. אפשר להריץ את הפקודות האלה באופן מקומי או ב-Pod של GKE כדי לאכלס את הדלי:
A4 ו-A3 Ultra
טייס אוטומטי
בודקים את משימת הכנת הנתונים:
מפעילים את המשימה:
עוקבים אחרי העבודה:
רגילה
בודקים את משימת הכנת הנתונים:
מפעילים את המשימה:
עוקבים אחרי העבודה:
A4X
משכפלים את מאגר ה-verl, מכינים את הסביבה הווירטואלית ומעבדים את קבוצת הנתונים GSM8K:
git clone https://github.com/volcengine/verl.git git -C verl checkout ${VERL_REF} VENV_DIR=.venv python3 -m venv $VENV_DIR source $VENV_DIR/bin/activate pip install verl python verl/examples/data_preprocess/gsm8k.py --local_save_dir ~/data/gsm8kמורידים את המודל Qwen2.5-32B-Instruct באמצעות Hugging Face CLI (ההורדה הזו דורשת כ-66 GB של שטח דיסק):
hf download Qwen/Qwen2.5-32B-Instruct --local-dir Qwen2.5-32B-Instructמעלים את המודל, הנתונים וקוד ה-VERL לקטגוריה של Cloud Storage:
gcloud storage cp --recursive verl gs://${GS_BUCKET}/verl gcloud storage cp --recursive Qwen2.5-32B-Instruct gs://${GS_BUCKET}/Qwen2.5-32B-Instruct gcloud storage cp --recursive ~/data/gsm8k/* gs://${GS_BUCKET}/gsm8k/
פריסת משאב מותאם אישית של RayCluster
פריסת משאב מותאם אישית של RayCluster, שמורכב מ-Pod אחד של ראש המערכת ומכמה Pods של עובדים עם תמיכה ב-GPU.
A4 ו-A3 Ultra
בוחרים את מצב האשכול של GKE שבו השתמשתם כדי ליצור את האשכול:
טייס אוטומטי
בודקים את עומס העבודה של RayCluster:
החלת ה-RayCluster:
רגילה
בודקים את עומס העבודה של RayCluster:
החלת ה-RayCluster:
A4X
יוצרים את RDMA
ResourceClaimTemplateואת NVIDIAComputeDomain. כל Pod של GPU worker תופס ארבעה כרטיסי RDMA NIC (כל המסילות של הצומת שלו) וערוץ IMEX אחד. שומרים את קובץ המניפסט הבא ב-compute-domain-a4x.yaml:apiVersion: resource.k8s.io/v1 kind: ResourceClaimTemplate metadata: name: verl-rdma-nic namespace: ${NAMESPACE} spec: spec: devices: requests: - name: nic exactly: deviceClassName: mrdma.google.com allocationMode: ExactCount count: 1 --- apiVersion: resource.nvidia.com/v1beta1 kind: ComputeDomain metadata: name: verl-compute-domain namespace: ${NAMESPACE} spec: numNodes: ${NUM_GPU_NODES} channel: resourceClaimTemplate: name: verl-compute-domain-channelהחלת המניפסט:
kubectl apply -f compute-domain-a4x.yamlפורסים את RayCluster. ה-Pod של Ray head פועל בצומת A4X בלי לבקש GPU (כי התמונה היא
arm64בלבד). שומרים את ההגדרות הבאות ב-ray-cluster-a4x.yaml:apiVersion: ray.io/v1 kind: RayCluster metadata: name: gb200-ray-cluster namespace: ${NAMESPACE} spec: rayVersion: '2.49.0' headGroupSpec: rayStartParams: dashboard-host: '0.0.0.0' num-cpus: "0" template: metadata: annotations: gke-gcsfuse/volumes: "true" spec: serviceAccountName: ${KSA_NAME} nodeSelector: cloud.google.com/gke-accelerator: nvidia-gb200 tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule - key: kubernetes.io/arch operator: Exists effect: NoSchedule containers: - name: ray-head image: ${VERL_IMAGE} lifecycle: postStart: exec: command: - /bin/bash - -c - pip3 install --quiet TransferQueue==0.1.8 ports: - containerPort: 6379 name: gcs-server - containerPort: 8265 name: dashboard - containerPort: 10001 name: client resources: limits: cpu: "12" memory: 32Gi ephemeral-storage: 20Gi requests: cpu: "12" memory: 32Gi ephemeral-storage: 20Gi volumeMounts: - mountPath: /tmp/ray name: ray-logs - name: training-bucket-vol mountPath: /data volumes: - name: ray-logs emptyDir: {} - name: training-bucket-vol persistentVolumeClaim: claimName: training-bucket-pvc workerGroupSpecs: - replicas: ${NUM_GPU_NODES} minReplicas: ${NUM_GPU_NODES} maxReplicas: ${NUM_GPU_NODES} groupName: gpu-group rayStartParams: num-cpus: "120" template: metadata: annotations: gke-gcsfuse/volumes: "true" spec: serviceAccountName: ${KSA_NAME} nodeSelector: cloud.google.com/gke-accelerator: nvidia-gb200 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: ray.io/group: gpu-group topologyKey: kubernetes.io/hostname tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule - key: kubernetes.io/arch operator: Exists effect: NoSchedule containers: - name: ray-worker image: ${VERL_IMAGE} lifecycle: postStart: exec: command: - /bin/bash - -c - pip3 install --quiet TransferQueue==0.1.8 env: - name: LD_LIBRARY_PATH value: /usr/local/nvidia/lib64 resources: limits: cpu: "120" memory: 600Gi nvidia.com/gpu: "4" ephemeral-storage: 500Gi requests: cpu: "120" memory: 600Gi nvidia.com/gpu: "4" ephemeral-storage: 500Gi claims: - name: rdma-nic-0 - name: rdma-nic-1 - name: rdma-nic-2 - name: rdma-nic-3 - name: compute-domain-channel volumeMounts: - name: nvidia mountPath: /usr/local/nvidia - name: gib mountPath: /usr/local/gib - name: shared-memory mountPath: /dev/shm - name: ray-tmp-storage mountPath: /tmp - name: training-bucket-vol mountPath: /data resourceClaims: - name: rdma-nic-0 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-1 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-2 resourceClaimTemplateName: verl-rdma-nic - name: rdma-nic-3 resourceClaimTemplateName: verl-rdma-nic - name: compute-domain-channel resourceClaimTemplateName: verl-compute-domain-channel volumes: - name: gib hostPath: path: /home/kubernetes/bin/gib - name: nvidia hostPath: path: /home/kubernetes/bin/nvidia - name: shared-memory emptyDir: medium: Memory sizeLimit: 200Gi - name: ray-tmp-storage emptyDir: {} - name: training-bucket-vol persistentVolumeClaim: claimName: training-bucket-pvcמחילים את המניפסט של RayCluster:
envsubst < ray-cluster-a4x.yaml | kubectl apply -f -ממתינים עד שמצב של Pod ראשי אחד וארבעה Pods של עובדים יהיה
Running:kubectl get pods -w
הפעלת משימת GRPO
מגדירים את משימת ההדרכה של למידת חיזוקים ושולחים אותה:
A4 ו-A3 Ultra
מגדירים את Ray Client:
שחזור של שירות Ray Head:
מגדירים העברה ליציאה אחרת לצומת של לוח הבקרה של Ray. צריך להשתמש בחלון Terminal נפרד בשביל השלב הזה, כי הפקודה הזו חוסמת את ה-Terminal בזמן שהיא פועלת. משתמשים ב-
Control+C כדי לעצור את התהליך: בודקים את קובץ המניפסט
runtime-env.yaml:אם אתם משתמשים ב-GPU מסוג H200, צריך לשנות את
NCCL_TUNER_CONFIG_PATHל-/usr/local/gib/configs/tuner_config_a3u.txtpb.הקובץ הזה משמש את לקוח Ray. אין צורך להחיל את המניפסט הזה על האשכול.
שולחים את המשימה באמצעות
ray job submit:עוקבים אחרי היומנים בלוח הבקרה של Ray או בפלט של המסוף. מחפשים את הערך
critic/score/meanכדי לראות אם יש עלייה, שמצביעה על למידה.אחרי שהאימון מסתיים, אפשר למצוא את נקודות הבקרה של המודל שאומן ב-
gs://$GS_BUCKET/verl/checkpoints.
A4X
אחזור שם ה-Pod של Ray head:
export HEAD_POD=$(kubectl get pod -n ${NAMESPACE} -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}')מגדירים את קובץ סביבת זמן הריצה של Ray ישירות ב-Pod הראשי:
kubectl exec ${HEAD_POD} -c ray-head -- bash -c 'mkdir -p /tmp/submit && cat > /tmp/submit/runtime-env.yaml <<EOF working_dir: "." env_vars: PYTHONPATH: "/data/verl" LD_LIBRARY_PATH: "/usr/local/nvidia/lib64:/usr/local/gib/lib64" NCCL_DEBUG: "INFO" NCCL_ENV_PLUGIN: "gcp" HF_HOME: "/data/huggingface_cache" GLOO_SOCKET_IFNAME: "eth0" EOF'שולחים את משימת האימון של GRPO על ידי הרצה ב-Ray head Pod:
kubectl exec ${HEAD_POD} -c ray-head -- bash -c 'cd /tmp/submit && \ ray job submit --runtime-env runtime-env.yaml --no-wait -- \ python3 -m verl.trainer.main_ppo \ algorithm.adv_estimator=grpo \ data.train_files=/data/gsm8k/train.parquet \ data.val_files=/data/gsm8k/test.parquet \ data.train_batch_size=256 \ data.max_prompt_length=512 \ data.max_response_length=512 \ actor_rollout_ref.model.path=/data/Qwen2.5-32B-Instruct \ actor_rollout_ref.actor.optim.lr=1e-5 \ actor_rollout_ref.actor.ppo_mini_batch_size=64 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=8 \ actor_rollout_ref.actor.use_kl_loss=True \ actor_rollout_ref.actor.strategy=fsdp2 \ actor_rollout_ref.rollout.name=vllm \ actor_rollout_ref.rollout.tensor_model_parallel_size=4 \ actor_rollout_ref.rollout.gpu_memory_utilization=0.6 \ actor_rollout_ref.rollout.n=8 \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=16 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=16 \ algorithm.kl_ctrl.kl_coef=0.001 \ trainer.logger=console \ trainer.n_gpus_per_node=4 \ trainer.nnodes=4 \ trainer.save_freq=10 \ trainer.test_freq=10 \ trainer.total_epochs=2 \ trainer.default_local_dir=/data/verl/checkpoints'עוקבים אחרי יומני העבודות (באמצעות המזהה הייחודי שמוחזר על ידי
ray job submit):kubectl exec ${HEAD_POD} -c ray-head -- ray job logs <var>JOB_ID</var> --followהחלפה של
JOB_ID. כדי לוודא ש-NVLink בין צמתים פעיל, מחפשים ביומנים שורות של NCCL שמכילותvia P2P/MNNVL.
הסרת המשאבים
כדי להימנע מחיובים, מוחקים את המשאבים:
A4 ו-A3 Ultra
טייס אוטומטי
מוחקים את אשכול Ray:
מחיקת Cloud Storage FUSE:
מוחקים את משאבי DRANET:
מוחקים את הקטגוריה של Cloud Storage:
מחיקת אשכול GKE:
רגילה
מוחקים את אשכול Ray:
מחיקת Cloud Storage FUSE:
מוחקים את הקטגוריה של Cloud Storage:
מחיקת אשכול GKE:
מחיקת רשתות VPC ורשתות משנה:
A4X
kubectl delete raycluster gb200-ray-cluster
kubectl delete computedomain verl-compute-domain
gcloud storage rm -r gs://${GS_BUCKET}
gcloud container clusters delete ${CLUSTER_NAME} --location=${CONTROL_PLANE_REGION}