אימון מודל באמצעות PyTorch,‏ Ray ו-Google Kubernetes Engine‏ (GKE)

אתם יכולים לאמן ולפרוס מודלים של למידת מכונה (ML) בסביבה חזקה וניתנת להרחבה. אפשר לעשות את זה באמצעות שילוב של Ray,‏ PyTorch ותוסף Ray Operator ב-Google Kubernetes Engine‏ (GKE). ‫GKE מספק את השליטה והביצועים שנדרשים לעומסי עבודה תובעניים של AI/ML. עומסי העבודה האלה כוללים אימון של מודלים בסיסיים גדולים וטיפול בבקשות הסקה בהיקף גדול. במדריך הזה תלמדו איך להשתמש בהתאמה אוטומטית לעומס של GKE ובמחשוב מבוזר של Ray כדי לייעל את תהליכי העבודה של למידת מכונה.

מידע על Ray

‫Ray היא מסגרת מחשוב מבוססת קוד פתוח שניתנת להרחבה, לאפליקציות של AI/ML. ‫Ray Train הוא רכיב ב-Ray שמיועד לאימון ולכוונון של מודלים מבוזרים. אפשר להשתמש ב-Ray Train API כדי להרחיב את ההדרכה למספר מכונות ולשלב עם ספריות של למידת מכונה כמו PyTorch.

אפשר לפרוס משימות אימון של Ray באמצעות המשאב RayCluster או RayJob. מומלץ להשתמש במשאב RayJob כשפורסים משימות Ray בסביבת ייצור, מהסיבות הבאות

  • משאב RayJob יוצר אשכול Ray זמני שאפשר למחוק אותו באופן אוטומטי כשמשימה מסתיימת.
  • המשאב RayJob תומך בכללי מדיניות של ניסיונות חוזרים להרצה גמישה של משימות.
  • אתם יכולים לנהל משימות Ray באמצעות דפוסי Kubernetes API מוכרים.

מטרות

המדריך הזה מיועד ללקוחות של AI גנרטיבי, למשתמשים חדשים או קיימים ב-GKE, למהנדסי למידת מכונה, למהנדסי MLOps‏ (DevOps) או למנהלי פלטפורמות שרוצים להשתמש ביכולות של Kubernetes לתזמור קונטיינרים כדי להציג מודלים באמצעות Ray.

  • יוצרים אשכול GKE.
  • יוצרים אשכול Ray באמצעות משאב מותאם אישית מסוג RayCluster.
  • אימון מודל באמצעות משימת Ray.
  • פורסים משימת Ray באמצעות המשאב המותאם אישית RayJob.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

כדי ליצור הערכת עלויות בהתאם לשימוש החזוי, אתם יכולים להשתמש במחשבון התמחור.

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.

לפני שמתחילים

ב-Cloud Shell מותקנת מראש התוכנה שדרושה למדריך הזה, כולל kubectl ו-ה-CLI של gcloud. אם אתם לא משתמשים ב-Cloud Shell, אתם צריכים להתקין את ה-CLI של gcloud.

  1. נכנסים לחשבון Google Cloud . אנחנו ממליצים למשתמשים חדשים ב- Google Cloud ליצור חשבון כדי שיוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. התקינו את ה-CLI של Google Cloud.

  3. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  4. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  5. יוצרים או בוחרים פרויקט ב- 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 .

  6. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  7. מפעילים את GKE API, אם הוא עדיין לא מופעל:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com
  8. התקינו את ה-CLI של Google Cloud.

  9. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  10. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  11. יוצרים או בוחרים פרויקט ב- 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 .

  12. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  13. מפעילים את GKE API, אם הוא עדיין לא מופעל:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com
  14. מעניקים תפקידים לחשבון המשתמש. מריצים את הפקודה הבאה לכל אחד מהתפקידים הבאים ב-IAM: roles/container.clusterAdmin, roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫PROJECT_ID: מזהה הפרויקט.
    • ‫USER_IDENTIFIER: המזהה של חשבון המשתמש . לדוגמה, myemail@example.com.
    • ‫ROLE: תפקיד ה-IAM שאתם מקצים לחשבון המשתמש.

הכנת הסביבה

כדי להכין את הסביבה:

  1. מפעילים סשן של Cloud Shell מGoogle Cloud המסוף על ידי לחיצה על Activate Cloud Shell סמל ההפעלה של Cloud Shell. Google Cloud ייפתח סשן בחלונית התחתונה של מסוף Google Cloud .

  2. הגדרת משתני סביבה:

    export PROJECT_ID=PROJECT_ID
    export CLUSTER_NAME=ray-cluster
    export COMPUTE_REGION=us-central1
    export COMPUTE_ZONE=us-central1-c
    export CLUSTER_VERSION=CLUSTER_VERSION
    export TUTORIAL_HOME=`pwd`
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud.
    • ‫CLUSTER_VERSION: גרסת GKE לשימוש. הגרסה צריכה להיות 1.30.1 ואילך.
  3. משכפלים את המאגר ב-GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. עוברים לספריית העבודה:

    cd kubernetes-engine-samples/ai-ml/gke-ray/raytrain/pytorch-mnist
    
  5. יוצרים סביבה וירטואלית של Python:

    python -m venv myenv && \
    source myenv/bin/activate
    
  6. מתקינים את Ray.

יצירת אשכול GKE

יוצרים אשכול GKE במצב Autopilot או Standard:

טייס אוטומטי

יצירת אשכול Autopilot:

gcloud container clusters create-auto ${CLUSTER_NAME}  \
    --enable-ray-operator \
    --cluster-version=${CLUSTER_VERSION} \
    --location=${COMPUTE_REGION}

רגילה

יצירת אשכול רגיל:

gcloud container clusters create ${CLUSTER_NAME} \
    --addons=RayOperator \
    --cluster-version=${CLUSTER_VERSION}  \
    --machine-type=e2-standard-8 \
    --location=${COMPUTE_ZONE} \
    --num-nodes=4

פריסה של משאב RayCluster

פורסים משאב RayCluster באשכול:

  1. בודקים את המניפסט הבא:

    apiVersion: ray.io/v1
    kind: RayCluster
    metadata:
      name: pytorch-mnist-cluster
    spec:
      rayVersion: '2.37.0'
      headGroupSpec:
        rayStartParams:
          dashboard-host: '0.0.0.0'
        template:
          metadata:
          spec:
            containers:
            - name: ray-head
              image: rayproject/ray:2.37.0
              ports:
              - containerPort: 6379
                name: gcs
              - containerPort: 8265
                name: dashboard
              - containerPort: 10001
                name: client
              resources:
                limits:
                  cpu: "2"
                  ephemeral-storage: "9Gi"
                  memory: "4Gi"
                requests:
                  cpu: "2"
                  ephemeral-storage: "9Gi"
                  memory: "4Gi"
      workerGroupSpecs:
      - replicas: 4
        minReplicas: 1
        maxReplicas: 5
        groupName: worker-group
        rayStartParams: {}
        template:
          spec:
            containers:
            - name: ray-worker
              image: rayproject/ray:2.37.0
              resources:
                limits:
                  cpu: "4"
                  ephemeral-storage: "9Gi"
                  memory: "8Gi"
                requests:
                  cpu: "4"
                  ephemeral-storage: "9Gi"
                  memory: "8Gi"

    במניפסט הזה מתואר משאב בהתאמה אישית מסוג RayCluster.

  2. מחילים את המניפסט על אשכול GKE:

    kubectl apply -f ray-cluster.yaml
    
  3. מוודאים שמשאב ה-RayCluster מוכן:

    kubectl get raycluster
    

    הפלט אמור להיראות כך:

    NAME                    DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
    pytorch-mnist-cluster   2                 2                   6      20Gi     0      ready    63s
    

    בפלט הזה, הערך ready בעמודה STATUS מציין שהמשאב RayCluster מוכן.

התחברות למשאב RayCluster

מתחברים למשאב RayCluster כדי לשלוח עבודת Ray.

  1. מוודאים ש-GKE יצר את שירות RayCluster:

    kubectl get svc pytorch-mnist-cluster-head-svc
    

    הפלט אמור להיראות כך:

    NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                AGE
    pytorch-mnist-cluster-head-svc   ClusterIP   34.118.238.247   <none>        10001/TCP,8265/TCP,6379/TCP,8080/TCP   109s
    
  2. מקימים סשן של העברת יציאות לראש של Ray:

    kubectl port-forward svc/pytorch-mnist-cluster-head-svc 8265:8265 2>&1 >/dev/null &
    
  3. מוודאים שלקוח Ray יכול להתחבר לאשכול Ray באמצעות localhost:

    ray list nodes --address http://localhost:8265
    

    הפלט אמור להיראות כך:

    Stats:
    ------------------------------
    Total: 3
    
    Table:
    ------------------------------
        NODE_ID                                                   NODE_IP     IS_HEAD_NODE    STATE    NODE_NAME    RESOURCES_TOTAL                 LABELS
    0  1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2  10.28.1.21  False           ALIVE    10.28.1.21   CPU: 2.0                        ray.io/node_id: 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2
    # Several lines of output omitted
    

אימון מודל

אימון מודל PyTorch באמצעות מערך הנתונים Fashion MNIST:

  1. שולחים עבודת Ray וממתינים לסיום העבודה:

    ray job submit --submission-id pytorch-mnist-job --working-dir . --runtime-env-json='{"pip": ["torch", "torchvision"], "excludes": ["myenv"]}' --address http://localhost:8265 -- python train.py
    

    הפלט אמור להיראות כך:

    Job submission server address: http://localhost:8265
    
    --------------------------------------------
    Job 'pytorch-mnist-job' submitted successfully
    --------------------------------------------
    
    Next steps
      Query the logs of the job:
        ray job logs pytorch-mnist-job
      Query the status of the job:
        ray job status pytorch-mnist-job
      Request the job to be stopped:
        ray job stop pytorch-mnist-job
    
    Handling connection for 8265
    Tailing logs until the job exits (disable with --no-wait):
    ...
    ...
    
  2. בודקים את סטטוס המשימה:

    ray job status pytorch-mnist
    

    הפלט אמור להיראות כך:

    Job submission server address: http://localhost:8265
    Status for job 'pytorch-mnist-job': RUNNING
    Status message: Job is currently running.
    

    מחכים עד שהסטטוס של Status for job יהיה COMPLETE. התהליך יכול להימשך 15 דקות או יותר.

  3. צפייה ביומנים של משימות Ray:

    ray job logs pytorch-mnist
    

    הפלט אמור להיראות כך:

    Training started with configuration:
    ╭─────────────────────────────────────────────────╮
    │ Training config                                  │
    ├──────────────────────────────────────────────────┤
    │ train_loop_config/batch_size_per_worker       8  │
    │ train_loop_config/epochs                     10  │
    │ train_loop_config/lr                      0.001  │
    ╰─────────────────────────────────────────────────╯
    
    # Several lines omitted
    
    Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
    ╭───────────────────────────────╮
    │ Training result                │
    ├────────────────────────────────┤
    │ checkpoint_dir_name            │
    │ time_this_iter_s      25.7394  │
    │ time_total_s          351.233  │
    │ training_iteration         10  │
    │ accuracy               0.8656  │
    │ loss                  0.37827  │
    ╰───────────────────────────────╯
    
    # Several lines omitted
    -------------------------------
    Job 'pytorch-mnist' succeeded
    -------------------------------
    

פריסת RayJob

המשאב המותאם אישית RayJob מנהל את מחזור החיים של משאב RayCluster במהלך ההפעלה של משימת Ray אחת.

  1. בודקים את המניפסט הבא:

    apiVersion: ray.io/v1
    kind: RayJob
    metadata:
      name: pytorch-mnist-job
    spec:
      shutdownAfterJobFinishes: true
      entrypoint: python ai-ml/gke-ray/raytrain/pytorch-mnist/train.py
      runtimeEnvYAML: |
        pip:
          - torch
          - torchvision
        working_dir: "https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/archive/main.zip"
        env_vars:
          NUM_WORKERS: "4"
          CPUS_PER_WORKER: "2"
      rayClusterSpec:
        rayVersion: '2.37.0'
        headGroupSpec:
          rayStartParams: {}
          template:
            spec:
              containers:
                - name: ray-head
                  image: rayproject/ray:2.37.0
                  ports:
                    - containerPort: 6379
                      name: gcs-server
                    - containerPort: 8265
                      name: dashboard
                    - containerPort: 10001
                      name: client
                  resources:
                    limits:
                      cpu: "2"
                      ephemeral-storage: "9Gi"
                      memory: "4Gi"
                    requests:
                      cpu: "2"
                      ephemeral-storage: "9Gi"
                      memory: "4Gi"
        workerGroupSpecs:
          - replicas: 4
            minReplicas: 1
            maxReplicas: 5
            groupName: small-group
            rayStartParams: {}
            template:
              spec:
                containers:
                  - name: ray-worker
                    image: rayproject/ray:2.37.0
                    resources:
                      limits:
                        cpu: "4"
                        ephemeral-storage: "9Gi"
                        memory: "8Gi"
                      requests:
                        cpu: "4"
                        ephemeral-storage: "9Gi"
                        memory: "8Gi"

    המניפסט הזה מתאר משאב בהתאמה אישית של RayJob.

  2. מחילים את המניפסט על אשכול GKE:

    kubectl apply -f ray-job.yaml
    
  3. מוודאים שמשאב RayJob פועל:

    kubectl get rayjob
    

    הפלט אמור להיראות כך:

    NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME   AGE
    pytorch-mnist-job   RUNNING      Running             2024-06-19T15:43:32Z              2m29s
    

    בפלט הזה, העמודה DEPLOYMENT STATUS מציינת שהמשאב של RayJob הוא Running.

  4. צפייה בסטטוס של משאב RayJob:

    kubectl logs -f -l job-name=pytorch-mnist-job
    

    הפלט אמור להיראות כך:

    Training started with configuration:
    ╭─────────────────────────────────────────────────╮
    │ Training config                                  │
    ├──────────────────────────────────────────────────┤
    │ train_loop_config/batch_size_per_worker       8  │
    │ train_loop_config/epochs                     10  │
    │ train_loop_config/lr                      0.001  │
    ╰─────────────────────────────────────────────────╯
    
    # Several lines omitted
    
    Training finished iteration 10 at 2024-06-19 08:29:36. Total running time: 9min 18s
    ╭───────────────────────────────╮
    │ Training result                │
    ├────────────────────────────────┤
    │ checkpoint_dir_name            │
    │ time_this_iter_s      25.7394  │
    │ time_total_s          351.233  │
    │ training_iteration         10  │
    │ accuracy               0.8656  │
    │ loss                  0.37827  │
    ╰───────────────────────────────╯
    
    # Several lines omitted
    -------------------------------
    Job 'pytorch-mnist' succeeded
    -------------------------------
    
  5. מוודאים שמשימת Ray הושלמה:

    kubectl get rayjob
    

    הפלט אמור להיראות כך:

    NAME                JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME               AGE
    pytorch-mnist-job   SUCCEEDED    Complete            2024-06-19T15:43:32Z   2024-06-19T15:51:12Z   9m6s
    

    בפלט הזה, העמודה DEPLOYMENT STATUS מציינת שהמשאב של RayJob הוא Complete.

מעקב אחרי עומסי העבודה של Ray

כדי לראות את הפרטים של RayJobs, אפשר לעבור לקטע Kubernetes Engine > AI/ML > Jobs ב Google Cloud מסוף.

הצגת משימות Ray במסוף Google Cloud

הסרת המשאבים

מחיקת הפרויקט

    כדי למחוק Google Cloud פרויקט:

    gcloud projects delete PROJECT_ID

מחיקת משאבים ספציפיים

אם השתמשתם בפרויקט קיים ואתם לא רוצים למחוק אותו, אתם יכולים למחוק את המשאבים הנפרדים. כדי למחוק את האשכול, מקלידים:

gcloud container clusters delete ${CLUSTER_NAME}

המאמרים הבאים

  • כדאי להעמיק את הקריאה ולהכיר דוגמאות לארכיטקטורות, תרשימים ושיטות מומלצות בנושאי Google Cloud. כל אלה זמינים במרכז הארכיטקטורה של Cloud.