אימון מודל עם יחידות GPU במצב רגיל של GKE

במדריך למתחילים הזה נסביר איך פורסים מודל אימון עם מעבדי GPU ב-Google Kubernetes Engine ‏ (GKE) ומאחסנים את התחזיות ב-Cloud Storage. במדריך הזה משתמשים במודל TensorFlow ובאשכולות GKE Standard. אפשר גם להריץ את עומסי העבודה האלה באשכולות של Autopilot עם פחות שלבי הגדרה. הוראות מפורטות זמינות במאמר אימון מודל באמצעות GPU במצב GKE Autopilot.

המסמך הזה מיועד לאדמינים של GKE שיש להם אשכולות רגילים קיימים ורוצים להריץ עומסי עבודה של GPU בפעם הראשונה.

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

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Kubernetes Engine and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  7. If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.

  8. Verify that billing is enabled for your Google Cloud project.

  9. Enable the Kubernetes Engine and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  10. במסוף Google Cloud , מפעילים את Cloud Shell.

    הפעלת Cloud Shell

    בחלק התחתון של Google Cloud המסוף יתחיל סשן של Cloud Shell ותופיע הודעה של שורת הפקודה. Cloud Shell היא סביבת מעטפת שבה ה-CLI של Google Cloud מותקן ומוגדרים ערכים לפרויקט הקיים. הסשן יופעל תוך כמה שניות.

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות לאימון מודל ב-GPU, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

שכפול המאגר לדוגמה

ב-Cloud Shell, מריצים את הפקודה הבאה:

git clone https://github.com/GoogleCloudPlatform/ai-on-gke/ ai-on-gke
cd ai-on-gke/tutorials-and-examples/gpu-examples/training-single-gpu

יצירת אשכול במצב רגיל ומאגר צמתים של GPU

אפשר להשתמש ב-Cloud Shell כדי:

  1. יוצרים אשכול Standard שמשתמש באיחוד זהויות של עומסי עבודה ל-GKE ומתקינים את הדרייבר של Cloud Storage FUSE:

    gcloud container clusters create gke-gpu-cluster \
        --addons GcsFuseCsiDriver \
        --location=us-central1 \
        --num-nodes=1 \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    מחליפים את PROJECT_ID במזהה הפרויקט ב- Google Cloud.

    יצירת האשכול עשויה להימשך כמה דקות.

  2. יוצרים מאגר צמתים של GPU:

    gcloud container node-pools create gke-gpu-pool-1 \
        --accelerator=type=nvidia-tesla-t4,count=1,gpu-driver-version=default \
        --machine-type=n1-standard-16 --num-nodes=1 \
        --location=us-central1 \
        --cluster=gke-gpu-cluster
    

יצירת קטגוריה של Cloud Storage

  1. נכנסים לדף Create a bucket במסוף Google Cloud :

    כניסה לדף Create a bucket

  2. בשדה Name your bucket (שם הקטגוריה), מזינים את השם הבא:

    PROJECT_ID-gke-gpu-bucket
    
  3. לוחצים על Continue.

  4. בקטע Location type, בוחרים באפשרות Region.

  5. ברשימה אזור בוחרים באפשרות us-central1 (Iowa) ולוחצים על המשך.

  6. בקטע Choose a storage class for your data (בחירת סוג אחסון לנתונים), לוחצים על Continue (המשך).

  7. בקטע Choose how to control access to objects, בוחרים באפשרות Uniform בשביל בקרת גישה.

  8. לוחצים על יצירה.

  9. בתיבת הדו-שיח Public access will be prevented, מוודאים שתיבת הסימון Enforce public access prevention on this bucket מסומנת, ולוחצים על Confirm.

הגדרת גישה לדלי באמצעות איחוד זהויות של עומסי עבודה ל-GKE

כדי לאפשר ל-cluster לגשת לקטגוריה של Cloud Storage, מבצעים את הפעולות הבאות:

  1. יוצרים Google Cloud חשבון שירות.
  2. יוצרים ServiceAccount של Kubernetes באשכול.
  3. מקשרים את חשבון השירות של Kubernetes לחשבון השירות Google Cloud .

יצירה של Google Cloud חשבון שירות

  1. במסוף Google Cloud , נכנסים לדף יצירת חשבון שירות:

    כניסה לדף Create service account

  2. בשדה מזהה חשבון שירות, מזינים gke-ai-sa.

  3. לוחצים על Create and continue.

  4. ברשימה Role בוחרים בתפקיד Cloud Storage > Storage Insights Collector Service.

  5. לוחצים על הוספת תפקיד נוסף.

  6. ברשימה Select a role, בוחרים בתפקיד Cloud Storage > Storage Object Admin.

  7. לוחצים על המשך ואז על סיום.

יצירת חשבון שירות של Kubernetes באשכול

ב-Cloud Shell, מבצעים את הפעולות הבאות:

  1. יוצרים מרחב שמות של Kubernetes:

    kubectl create namespace gke-ai-namespace
    
  2. יוצרים חשבון שירות של Kubernetes במרחב השמות:

    kubectl create serviceaccount gpu-k8s-sa --namespace=gke-ai-namespace
    

קישור חשבון השירות של Kubernetes לחשבון השירות Google Cloud

ב-Cloud Shell, מריצים את הפקודות הבאות:

  1. מוסיפים קישור IAM ל Google Cloud חשבון השירות:

    gcloud iam service-accounts add-iam-policy-binding gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-ai-namespace/gpu-k8s-sa]"
    

    הדגל --member מספק את הזהות המלאה של חשבון השירות ב-Kubernetes ב- Google Cloud.

  2. הוספת הערה ל-ServiceAccount ב-Kubernetes:

    kubectl annotate serviceaccount gpu-k8s-sa \
        --namespace gke-ai-namespace \
        iam.gke.io/gcp-service-account=gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com
    

בדיקה אם ל-Pods יש גישה לקטגוריה של Cloud Storage

  1. ב-Cloud Shell, יוצרים את משתני הסביבה הבאים:

    export K8S_SA_NAME=gpu-k8s-sa
    export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
    

    מחליפים את PROJECT_ID במזהה הפרויקט ב- Google Cloud.

  2. יוצרים Pod עם קונטיינר TensorFlow:

    envsubst < src/gke-config/standard-tensorflow-bash.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    

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

  3. יוצרים קובץ לדוגמה בקטגוריה:

    touch sample-file
    gcloud storage cp sample-file gs://PROJECT_ID-gke-gpu-bucket
    
  4. מחכים שה-Pod יהיה מוכן:

    kubectl wait --for=condition=Ready pod/test-tensorflow-pod -n=gke-ai-namespace --timeout=180s
    

    כשה-Pod מוכן, הפלט הוא:

    pod/test-tensorflow-pod condition met
    
  5. פותחים מעטפת במאגר TensorFlow:

    kubectl -n gke-ai-namespace exec --stdin --tty test-tensorflow-pod --container tensorflow -- /bin/bash
    
  6. מנסים לקרוא את קובץ הדוגמה שיצרתם:

    ls /data
    

    הפלט מציג את קובץ הדוגמה.

  7. בודקים את היומנים כדי לזהות את ה-GPU שמצורף ל-Pod:

    python3 -m pip install 'tensorflow[and-cuda]'
    python -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
    

    הפלט מציג את ה-GPU שמצורף ל-Pod, באופן דומה לזה:

    ...
    PhysicalDevice(name='/physical_device:GPU:0',device_type='GPU')
    
  8. יוצאים מהקונטיינר:

    exit
    
  9. מוחקים את ה-Pod לדוגמה:

    kubectl delete -f src/gke-config/standard-tensorflow-bash.yaml \
        --namespace=gke-ai-namespace
    

אימון וחיזוי באמצעות מערך הנתונים MNIST

בקטע הזה מריצים עומס עבודה של אימון על מערך הנתונים לדוגמה MNIST.

  1. מעתיקים את הנתונים לדוגמה לקטגוריה של Cloud Storage:

    gcloud storage cp src/tensorflow-mnist-example gs://PROJECT_ID-gke-gpu-bucket/ --recursive
    
  2. יוצרים את משתני הסביבה הבאים:

    export K8S_SA_NAME=gpu-k8s-sa
    export BUCKET_NAME=PROJECT_ID-gke-gpu-bucket
    
  3. בודקים את משימת האימון:

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: mnist-training-job
    spec:
      template:
        metadata:
          name: mnist
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-tesla-t4
          tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
          containers:
          - name: tensorflow
            image: tensorflow/tensorflow:latest-gpu 
            command: ["/bin/bash", "-c", "--"]
            args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_train_distributed.py"]
            resources:
              limits:
                nvidia.com/gpu: 1
                cpu: 1
                memory: 3Gi
            volumeMounts:
            - name: gcs-fuse-csi-vol
              mountPath: /data
              readOnly: false
          serviceAccountName: $K8S_SA_NAME
          volumes:
          - name: gcs-fuse-csi-vol
            csi:
              driver: gcsfuse.csi.storage.gke.io
              readOnly: false
              volumeAttributes:
                bucketName: $BUCKET_NAME
                mountOptions: "implicit-dirs"
          restartPolicy: "Never"
  4. פורסים את משימת האימון:

    envsubst < src/gke-config/standard-tf-mnist-train.yaml | kubectl -n gke-ai-namespace apply -f -
    

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

  5. מחכים עד שהסטטוס של העבודה יהיה Completed:

    kubectl wait -n gke-ai-namespace --for=condition=Complete job/mnist-training-job --timeout=180s
    

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

    job.batch/mnist-training-job condition met
    
  6. בודקים את היומנים מהקונטיינר של TensorFlow:

    kubectl logs -f jobs/mnist-training-job -c tensorflow -n gke-ai-namespace
    

    בפלט מוצגים האירועים הבאים:

    • התקנת חבילות Python נדרשות
    • הורדת מערך הנתונים MNIST
    • אימון המודל באמצעות GPU
    • שמירת המודל
    • הערכת המודל
    ...
    Epoch 12/12
    927/938 [============================>.] - ETA: 0s - loss: 0.0188 - accuracy: 0.9954
    Learning rate for epoch 12 is 9.999999747378752e-06
    938/938 [==============================] - 5s 6ms/step - loss: 0.0187 - accuracy: 0.9954 - lr: 1.0000e-05
    157/157 [==============================] - 1s 4ms/step - loss: 0.0424 - accuracy: 0.9861
    Eval loss: 0.04236088693141937, Eval accuracy: 0.9861000180244446
    Training finished. Model saved
    
  7. מחיקת עומס העבודה של האימון:

    kubectl -n gke-ai-namespace delete -f src/gke-config/standard-tf-mnist-train.yaml
    

פריסת עומס עבודה של הסקה

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

  1. מעתיקים את התמונות לחיזוי לקטגוריה:

    gcloud storage cp data/mnist_predict gs://PROJECT_ID-gke-gpu-bucket/ --recursive
    
  2. בודקים את עומס העבודה של ההסקה:

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: mnist-batch-prediction-job
    spec:
      template:
        metadata:
          name: mnist
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-tesla-t4
          tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
          containers:
          - name: tensorflow
            image: tensorflow/tensorflow:latest-gpu 
            command: ["/bin/bash", "-c", "--"]
            args: ["cd /data/tensorflow-mnist-example; pip install -r requirements.txt; python tensorflow_mnist_batch_predict.py"]
            resources:
              limits:
                nvidia.com/gpu: 1
                cpu: 1
                memory: 3Gi
            volumeMounts:
            - name: gcs-fuse-csi-vol
              mountPath: /data
              readOnly: false
          serviceAccountName: $K8S_SA_NAME
          volumes:
          - name: gcs-fuse-csi-vol
            csi:
              driver: gcsfuse.csi.storage.gke.io
              readOnly: false
              volumeAttributes:
                bucketName: $BUCKET_NAME
                mountOptions: "implicit-dirs"
          restartPolicy: "Never"
  3. פריסת עומס העבודה של ההסקה:

    envsubst < src/gke-config/standard-tf-mnist-batch-predict.yaml | kubectl -n gke-ai-namespace apply -f -
    

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

  4. מחכים עד שהסטטוס של העבודה יהיה Completed:

    kubectl wait -n gke-ai-namespace --for=condition=Complete job/mnist-batch-prediction-job --timeout=180s
    

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

    job.batch/mnist-batch-prediction-job condition met
    
  5. בודקים את היומנים מהקונטיינר של TensorFlow:

    kubectl logs -f jobs/mnist-batch-prediction-job -c tensorflow -n gke-ai-namespace
    

    הפלט הוא החיזוי לכל תמונה ורמת הסמך של המודל בחיזוי, בדומה למה שמוצג כאן:

    Found 10 files belonging to 1 classes.
    1/1 [==============================] - 2s 2s/step
    The image /data/mnist_predict/0.png is the number 0 with a 100.00 percent confidence.
    The image /data/mnist_predict/1.png is the number 1 with a 99.99 percent confidence.
    The image /data/mnist_predict/2.png is the number 2 with a 100.00 percent confidence.
    The image /data/mnist_predict/3.png is the number 3 with a 99.95 percent confidence.
    The image /data/mnist_predict/4.png is the number 4 with a 100.00 percent confidence.
    The image /data/mnist_predict/5.png is the number 5 with a 100.00 percent confidence.
    The image /data/mnist_predict/6.png is the number 6 with a 99.97 percent confidence.
    The image /data/mnist_predict/7.png is the number 7 with a 100.00 percent confidence.
    The image /data/mnist_predict/8.png is the number 8 with a 100.00 percent confidence.
    The image /data/mnist_predict/9.png is the number 9 with a 99.65 percent confidence.
    

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שיצרתם במדריך הזה, אפשר לבצע אחת מהפעולות הבאות:

  • אם רוצים לשמור את אשכול GKE: מוחקים את משאבי Kubernetes באשכול ואת משאבי Google Cloud
  • שמירת הפרויקט: מחיקת אשכול GKE והמשאבים Google Cloud Google Cloud
  • מחיקת הפרויקט

מחיקת משאבי Kubernetes באשכול ובמשאבים Google Cloud

  1. מוחקים את מרחב השמות של Kubernetes ואת עומסי העבודה שפרסתם:

    kubectl -n gke-ai-namespace delete -f src/gke-config/standard-tf-mnist-batch-predict.yaml
    kubectl delete namespace gke-ai-namespace
    
  2. מוחקים את הקטגוריה של Cloud Storage:

    1. נכנסים לדף Buckets:

      כניסה לדף Buckets

    2. מסמנים את התיבה PROJECT_ID-gke-gpu-bucket.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים DELETE ולוחצים על מחיקה.

  3. מוחקים את Google Cloud חשבון השירות:

    1. עוברים לדף Service accounts:

      כניסה לדף Service accounts

    2. בוחרים את הפרויקט הרצוי.

    3. מסמנים את התיבה gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com.

    4. לוחצים על מחיקה.

    5. לוחצים על מחיקה כדי לאשר.

מחיקת אשכול GKE והמשאבים Google Cloud

  1. מחיקת אשכול GKE:

    1. עוברים לדף Clusters:

      מעבר אל Clusters

    2. מסמנים את התיבה של gke-gpu-cluster.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים gke-gpu-cluster ולוחצים על מחיקה.

  2. מוחקים את הקטגוריה של Cloud Storage:

    1. נכנסים לדף Buckets:

      כניסה לדף Buckets

    2. מסמנים את התיבה PROJECT_ID-gke-gpu-bucket.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים DELETE ולוחצים על מחיקה.

  3. מוחקים את Google Cloud חשבון השירות:

    1. עוברים לדף Service accounts:

      כניסה לדף Service accounts

    2. בוחרים את הפרויקט הרצוי.

    3. מסמנים את התיבה gke-ai-sa@PROJECT_ID.iam.gserviceaccount.com.

    4. לוחצים על מחיקה.

    5. לוחצים על מחיקה כדי לאשר.

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

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

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