שימוש בתמונת מערכת הפעלה מותאמת אישית
אתם יכולים להשתמש בתמונת מערכת הפעלה בהתאמה אישית למכונות הווירטואליות של TPU כדי לטעון מראש תוכנה, להשתמש בהפצה ספציפית של מערכת הפעלה או להחיל שינויים מותאמים אישית בקרנל. יצירת תמונה בהתאמה אישית כוללת ביצוע שינויים ספציפיים במערכת במהלך תהליך יצירת התמונה, והגדרת התמונה לטיפול במשימות בזמן האתחול שנדרשות לפונקציונליות של TPU.
אם אתם משתמשים בתמונת מערכת הפעלה בהתאמה אישית עם TPU, חשוב לזכור את ההצהרות הבאות:
- Google מספקת תמונות של Ubuntu עם תמיכה לטווח ארוך (LTS) שעברו אופטימיזציה ל-TPU כברירת מחדל. השינויים במערכת ההפעלה שמפורטים בדף הזה מאומתים רק לתמונות של Ubuntu LTS שעברו אופטימיזציה ל-TPU ונתמכות על ידי Google.
- באחריותכם לבצע אקסטרפולציה של השינויים הנדרשים במערכת ההפעלה עבור כל הפצה אחרת של מערכת ההפעלה או תמונות בהתאמה אישית. Google לא מבטיחה שהשינויים ב-Ubuntu שמפורטים בדף הזה יפעלו עם הפצות אחרות של מערכת ההפעלה או עם תמונה אחרת של Ubuntu עם ליבה מותאמת אישית.
- Google לא יוצרת או מספקת בדיקות לתמונות של מערכות הפעלה אחרות מלבד תמונות ברירת המחדל של Ubuntu LTS שעברו אופטימיזציה ל-TPU. צריך ליצור ולבדוק את תמונת מערכת ההפעלה המותאמת אישית.
מידע נוסף על תמונות ברירת המחדל של Ubuntu LTS שעברו אופטימיזציה ל-TPU זמין במאמר בנושא תמונות של מערכת הפעלה ל-TPU.
דרישות מוקדמות
תמונת הבסיס צריכה לכלול את הרכיבים הבאים:
- Python 3
- CLI של gcloud
ביצוע שינויים במהלך יצירת התמונה
מבצעים את השינויים הבאים כשיוצרים תמונת Ubuntu מותאמת אישית.
קישור מכשירי TPU ל-VFIO
כדי לאפשר למערכת ההפעלה של האורח לגשת לחומרת TPU, צריך לקשר את מכשירי ה-TPU למנהל ההתקן vfio-pci.
יוצרים קובץ כללי udev בשם
99-tpu-vfiopci.rulesב-/etc/udev/rules.d/:# Rules for binding vfio-enabled TPU devices to vfio-pci. # v5p SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0062", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00ad", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci" # v6e SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x006f", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00d1", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci" # TPU7x SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0076", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00f2", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci" # Bind all 'bind_to_vfio_pci' tagged devices to vfio-pci. TAG=="bind_to_vfio_pci", RUN+="/lib/udev/bind_to_vfio_pci.sh $kernel"יוצרים סקריפט בשם
bind_to_vfio_pci.shב-/lib/udev/:#!/bin/bash #!/usr/bin/env bash # Run ./bind_to_vfio_pci.sh <DBDF> # Binds the device at <DBDF> to vfio-pci. # If the device is already bound to a driver, unbinds it first. # Load the vfio-pci module into the kernel. No-op if already loaded. modprobe vfio-pci DBDF_REGEX="^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}.[[:xdigit:]]$" unset BDF if [[ $1 =~ $DBDF_REGEX ]]; then BDF=$1 else echo "Error: BDF arg ($1) is not in form dddd:bb:dd.f" exit 1 fi PCI_PATH="/sys/bus/pci/devices/$BDF" echo "vfio-pci" > "$PCI_PATH/driver_override" PCI_DRIVER_PATH="$PCI_PATH/driver" if [[ -d "$PCI_DRIVER_PATH" ]]; then curr_driver=$(readlink "$PCI_DRIVER_PATH") curr_driver=${curr_driver##*/} if [[ $curr_driver == "vfio-pci" ]]; then echo "$BDF already bound to vfio-pci" exit 0 else echo "$BDF" > "$PCI_DRIVER_PATH/unbind" if [[ -d "$PCI_DRIVER_PATH" ]]; then echo "Error: Unable to unbind $PCI_DRIVER_PATH" exit 1 fi echo "Unbound $BDF from driver $curr_driver" fi fi echo "$BDF" > /sys/bus/pci/drivers_probe echo "Bound $BDF to vfio-pci" # Grant read/write access on VFIO device to all users IOMMU_GROUP=$(readlink "$PCI_PATH/iommu_group" | xargs basename) VFIO_DEV="/dev/vfio/$IOMMU_GROUP" if [[ -c "$VFIO_DEV" ]]; then chmod 0666 "$VFIO_DEV" else echo "$VFIO_DEV not found" exit 1 fi # Set allow_unsafe_interrupts for x86 platforms. (uname -a | grep -q x86_64) && echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts # This is only needed to avoid non-zero exit code from previous command. echo "All Done!"הופכים את הסקריפט לניתן להרצה:
chmod +x /lib/udev/bind_to_vfio_pci.shנותנים לכל המשתמשים במערכת גישה למכשיר TPU:
echo 'KERNEL=="accel*" MODE="0666"' >> /etc/udev/rules.d/99-tpu.rules
שינוי התמונה כדי לשפר את הביצועים
כדי להבטיח ביצועים אופטימליים, צריך לשנות את מגבלות המערכת והפרמטרים הבאים.
מגבלות זיכרון
אפשר לאפשר לתהליך יחיד לנעול זיכרון ללא הגבלה על ידי עדכון של
/etc/security/limits.conf:
echo '* hard memlock unlimited' >> /etc/security/limits.conf
echo '* soft memlock unlimited' >> /etc/security/limits.conf
מגבלות על קבצים
כדי להגדיל את מספר הקבצים הפתוחים, מעדכנים את /etc/security/limits.conf:
echo "* soft nofile 100000" >> /etc/security/limits.conf
echo "* hard nofile 100000" >> /etc/security/limits.conf
echo "root soft nofile 100000" >> /etc/security/limits.conf
echo "root hard nofile 100000" >> /etc/security/limits.conf
פרמטרים של ליבה
מעדכנים את ההגדרות של GRUB (בדרך כלל ב-/etc/default/grub) כך שיכללו את הפרמטרים הבאים ב-GRUB_CMDLINE_LINUX:
-
idle=poll: מונע מהמעבד (CPU) להיכנס למצבי המתנה עם צריכת חשמל נמוכה. -
intel_iommu=on,sm_on: מאפשרת את יחידת ניהול הזיכרון של קלט/פלט של אינטל (IOMMU). נדרש לארכיטקטורות TPU7x ו-v5p. -
transparent_hugepage=always: הפעלה של Transparent Huge Pages (THP).
כדי לעדכן את פרמטרים של ליבת המערכת:
כדי למנוע מהמעבד לעבור למצב המתנה עם צריכת חשמל נמוכה, מגדירים את המשתנה הבא, שבו תשתמשו בשלב הבא.
kernel_cmdline="idle=poll"מפעילים את Intel Input-Output Memory Management Unit (IOMMU). השלב הזה נדרש עבור TPU7x ו-TPU v5p.
kernel_cmdline="${kernel_cmdline} intel_iommu=on,sm_on"; sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"${kernel_cmdline}\"/" /etc/default/grub echo "Status: New kernel cmdline: $(cat /etc/default/grub | grep -e '^GRUB_CMDLINE_LINUX=')" update-grubהפעלת דפים גדולים שקופים (THP):
echo "Status: Enabling THP" sed -i -r 's/GRUB_CMDLINE_LINUX="[a-zA-Z0-9_= ]*/& transparent_hugepage=always/' /etc/default/grub update-grub
התקנת סוכן vBar
סוכן vBar נדרש כדי שהרשת של חיבורים בין-שבביים (ICI) תפעל.
כדי להתקין את סוכן vBar, מריצים את הפקודות הבאות:
אימות Docker באמצעות Artifact Registry:
gcloud auth configure-docker us-docker.pkg.devשליפת קובץ אימג' של Docker מ-Artifact Registry:
docker pull gcr.io/cloud-tpu-v2-images/vbar_control_agent:0.0.1מריצים קונטיינר באמצעות קובץ האימג' של סוכן vBar:
docker run --privileged --net=host vbar_control_agent:0.0.1
אופציונלי: התקנה והפעלה של הכלי AI Telemetry Collector
הכלי AI Telemetry Collector פועל בתוך מכונת ה-VM של TPU ומאפשר לכם לגשת למדדי זמן ריצה ולמדדי תשתית דרך Cloud Monitoring או דרך צינור ניטור משלכם שמבוסס על Prometheus. אתם יכולים להשתמש בכלי לאיסוף נתוני טלמטריה של AI עם מערכת הפעלה מותאמת אישית באמצעות ai-telemetry-collector קובץ האימג' של Docker. אפשר להתקין את התמונה במערכת ההפעלה המותאמת אישית ולהשתמש בקובץ config.yaml כדי להגדיר את מרווחי האיסוף, להפעיל או להשבית מדדים ספציפיים או לשנות את יעדי הייצוא.
כדי להתקין את הכלי לאיסוף נתוני טלמטריה של AI, מריצים את הפקודות הבאות:
אימות Docker באמצעות Artifact Registry:
gcloud auth configure-docker us-docker.pkg.devשליפת קובץ אימג' של Docker מ-Artifact Registry:
docker pull gcr.io/cloud-tpu-v2-images/ai-telemetry-collector:latestמריצים קונטיינר באמצעות תמונת ה-AI Telemetry Collector עם הגדרת ברירת המחדל:
docker run --privileged --net=host ai-telemetry-collector:latestלמידע על שימוש בקובץ תצורה בהתאמה אישית או על הוספה של קובצי תצורה נוספים, אפשר לעיין במאמר AI Telemetry Collector.
ביצוע שינויים בזמן האתחול
מגדירים את התמונה כך שתבצע את המשימות בקטעים הבאים בכל פעם שמפעילים מכונה וירטואלית. אתם יכולים להשתמש בכלי cloud-init כדי להגדיר משימות שמתבצעות בזמן האתחול על ידי העברת מטא-נתונים למופעים. ההגדרות בקטעים הבאים משתמשות במודולים כמו write_files ו-runcmd.
קטעי קוד שמגדירים קבצים לכתיבה צריכים להיכלל במפתח write_files:, ופקודות שצריך להריץ בזמן האתחול צריכות להיכלל במפתח runcmd: בהגדרות cloud-init.
הפעלת סוכן vBar
מפעילים את סוכן השליטה vBar עם מזהי המשתמש והקבוצה המתאימים:
vbar_control_agent --logtostderr --gid= --uid= --chroot= --census_enabled=false --loas_pwd_fallback_in_corp
הגדרת משתני סביבה
כדי לוודא שהסביבה שלכם מאותחלת בצורה נכונה עבור עומסי עבודה של TPU, אתם צריכים לאחזר משתני הגדרות זמן ריצה משרת המטא-נתונים של Compute Engine במהלך תהליך אתחול המערכת. כדי לעשות זאת, מוסיפים את קטע הקוד הבא לקטע write_files: בהגדרות של cloud-init. קטע הקוד הזה יוצר סקריפט בשם /var/scripts/configure-env-vars.sh. הסקריפט הזה מבצע אוטומטית אחזור של מאפיינים ממפתח המטא-נתונים tpu-env ושומר אותם ב-/${HOME}/tpu-env כדי להשתמש בהם במערך התוכנה של TPU.
- path: /var/scripts/configure-env-vars.sh
permissions: 0444
owner: root
content: |
grep -q CLOUDSDK_PYTHON /etc/environment || echo "CLOUDSDK_PYTHON=/usr/bin/python3" >> /etc/environment
export HOME=/home/tpu-runtime
curl -s 'http://metadata.google.internal/computeMetadata/v1/instance/attributes/tpu-env' -H 'Metadata-Flavor: Google' > /tmp/tpu-env.yaml
eval $(python3 -c '''
import yaml
stream_in=open("/tmp/tpu-env.yaml", "r")
for k,v in yaml.safe_load(stream_in).items():
print("{var}=\"{value}\"".format(var = k, value = str(v)))
''' > "/${HOME}/tpu-env"
)
rm -f "/tmp/tpu-env.yaml"
printenv
cat ${HOME}/tpu-env
אחזור מטא-נתונים של מכונה וירטואלית
קטע הקוד הבא יוצר סקריפט בשם /var/scripts/get-vm-metadata.py, כלי Python לשליחת שאילתות לשרת המטא-נתונים באופן פרוגרמטי לגבי מאפיינים ספציפיים של מופע ותגי מטא-נתונים בהתאמה אישית. מוסיפים את השורה הבאה לקטע write_files: בהגדרות של cloud-init:
- path: /var/scripts/get-vm-metadata.py
permissions: 0444
owner: root
content: |
import sys, requests, os
if len(sys.argv) < 2:
sys.stderr.write('Must provide key')
os._exit(1)
key = sys.argv[1]
default = None
if len(sys.argv) > 2:
default = sys.argv[2]
attribute_type = 'attributes'
if len(sys.argv) > 3:
attribute_type = sys.argv[3]
request = requests.get("http://metadata.google.internal/computeMetadata/v1/instance/{}/{}".format(attribute_type, key), headers={'Metadata-Flavor': 'Google'})
if request.status_code == 200:
print(request.content)
elif request.status_code == 404 or request.status_code == '403':
sys.stderr.write('Metadata key: {} does not exist\n'.format(key))
if default:
print(default)
else:
sys.stderr.write('Lookup failed with: {}'.format(request))
הגדלת הזמן הקצוב לתפוגה ב-Cloud Storage
אם עומס העבודה שלכם מתקשר עם Cloud Storage, כדאי להגדיל את משך הזמן הקצוב לתפוגה על ידי הוספת ערכים של זמן קצוב לתפוגה אל /etc/environment. כדי לעשות זאת, מוסיפים את קטע הקוד הבא לקטע write_files: בהגדרות של cloud-init, וכך נוצר סקריפט בשם /var/scripts/configure-gcs-timeouts.sh.
- path: /var/scripts/configure-gcs-timeouts.sh
permissions: 0444
owner: root
content: |
echo "GCS_RESOLVE_REFRESH_SECS=60" >> /etc/environment
echo "GCS_REQUEST_CONNECTION_TIMEOUT_SECS=300" >> /etc/environment
echo "GCS_METADATA_REQUEST_TIMEOUT_SECS=300" >> /etc/environment
echo "GCS_READ_REQUEST_TIMEOUT_SECS=300" >> /etc/environment
echo "GCS_WRITE_REQUEST_TIMEOUT_SECS=600" >> /etc/environment
המאמרים הבאים
- מעיינים בתמונות של מערכת ההפעלה TPU שזמינות.
- איך מנהלים מכונות וירטואליות של TPU