カスタム OS イメージを使用する
TPU VM にカスタム OS イメージを使用すると、ソフトウェアをプリロードしたり、特定の OS ディストリビューションを使用したり、カスタム カーネルの変更を適用したりできます。カスタム イメージの作成では、イメージの作成プロセス中に特定のシステム変更を行い、TPU 機能に必要なブートタイム タスクを処理するようにイメージを構成します。
TPU でカスタム OS イメージを使用する場合は、次の免責事項に注意してください。
- Google は、デフォルトの TPU 最適化 Ubuntu 長期サポート(LTS)イメージを提供しています。このページに記載されている OS の変更は、Google がサポートする TPU 最適化 Ubuntu LTS イメージでのみ検証されています。
- 他の OS ディストリビューションやカスタム イメージに必要な OS の変更を推定するのは、お客様の責任です。Google は、このページに記載されている Ubuntu の変更が、他の OS ディストリビューションやカスタム カーネルを含む別の Ubuntu イメージで動作することを保証しません。
- Google は、デフォルトの TPU 最適化 Ubuntu LTS イメージ以外の OS イメージのテストを構築または提供していません。カスタム OS イメージをビルドしてテストする必要があります。
デフォルトの TPU 最適化 Ubuntu LTS イメージの詳細については、TPU OS イメージをご覧ください。
前提条件
ベースイメージには、次のコンポーネントがインストールされている必要があります。
- Python 3
- gcloud CLI
イメージの作成中に変更を行う
カスタム Ubuntu イメージのビルド時に、次の変更を適用します。
TPU デバイスを VFIO にバインドする
ゲスト OS が TPU ハードウェアにアクセスできるようにするには、TPU デバイスを vfio-pci ドライバにバインドする必要があります。
/etc/udev/rules.d/に99-tpu-vfiopci.rulesという名前の udev ルールファイルを作成します。# 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"/lib/udev/にbind_to_vfio_pci.shという名前のスクリプトを作成します。#!/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: Intel 入出力メモリ管理ユニット(IOMMU)を有効にします。TPU7x アーキテクチャと v5p アーキテクチャで必要です。transparent_hugepage=always: Transparent Huge Pages(THP)を有効にします。
次の手順では、これらのカーネル パラメータを更新する方法について説明します。
次の変数を設定して、CPU が低電力アイドル状態に移行しないようにします。この変数は次のステップで使用します。
kernel_cmdline="idle=poll"Intel 入出力メモリ管理ユニット(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-grubTransparent Huge Pages(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 エージェントをインストールする
チップ間相互接続(ICI)ネットワークが機能するには、vBar エージェントが必要です。
vBar エージェントをインストールするには、次のコマンドを実行します。
Artifact Registry で Docker を認証します。
gcloud auth configure-docker us-docker.pkg.devArtifact Registry から Docker イメージを pull します。
docker pull gcr.io/cloud-tpu-v2-images/vbar_control_agent:0.0.1vBar エージェント イメージを使用してコンテナを実行します。
docker run --privileged --net=host vbar_control_agent:0.0.1
省略可: AI テレメトリー コレクタをインストールして実行する
AI テレメトリー コレクタは TPU VM 内で実行され、Cloud Monitoring または独自の Prometheus ベースのモニタリング パイプラインを介して、ランタイム指標とインフラストラクチャ指標にアクセスできます。ai-telemetry-collector Docker イメージを使用すると、カスタム OS で AI Telemetry Collector を使用できます。イメージをカスタム OS にインストールし、config.yaml ファイルを使用して収集間隔を指定したり、特定の指標を有効または無効にしたり、エクスポート先を変更したりできます。
AI テレメトリー コレクタをインストールするには、次のコマンドを実行します。
Artifact Registry で Docker を認証します。
gcloud auth configure-docker us-docker.pkg.devArtifact Registry から Docker イメージを pull します。
docker pull gcr.io/cloud-tpu-v2-images/ai-telemetry-collector:latestデフォルト構成で AI テレメトリー コレクタ イメージを使用してコンテナを実行します。
docker run --privileged --net=host ai-telemetry-collector:latestカスタム構成ファイルの使用や追加の構成ファイルの追加については、AI テレメトリー コレクタをご覧ください。
起動時間の変更
VM が起動するたびに、以降のセクションのタスクを実行するようにイメージを構成します。cloud-init ツールを使用して、インスタンスにメタデータを渡すことで、起動時のタスクを構成できます。次のセクションの構成では、write_files や runcmd などのモジュールを使用します。書き込むファイルを定義するスニペットは write_files: キーの下に含め、起動時に実行するコマンドは cloud-init 構成の runcmd: キーの下に含める必要があります。
vBar エージェントを起動する
適切なユーザー ID とグループ ID を使用して vBar 制御エージェントを開始します。
vbar_control_agent --logtostderr --gid= --uid= --chroot= --census_enabled=false --loas_pwd_fallback_in_corp
環境変数を構成する
TPU ワークロード用に環境が正しく初期化されるようにするには、システム起動プロセス中に Compute Engine メタデータ サーバーからランタイム構成変数を取得する必要があります。これを行うには、cloud-init 構成の write_files: セクションに次のスニペットを追加します。これにより、/var/scripts/configure-env-vars.sh という名前のスクリプトが作成されます。このスクリプトは、tpu-env メタデータキーから属性を取得する処理を自動化し、TPU ソフトウェア スタックで使用される /${HOME}/tpu-env に保存します。
- 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
VM メタデータを取得する
次のスニペットは、/var/scripts/get-vm-metadata.py という名前のスクリプトを作成します。これは、特定のインスタンス属性とカスタム メタデータタグについてメタデータ サーバーにプログラムでクエリを実行する Python ユーティリティです。cloud-init 構成の write_files: セクションに次の内容を追加します。
- 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 にタイムアウト値を追加して、タイムアウト時間を増やします。これを行うには、cloud-init 構成の write_files: セクションに次のスニペットを追加します。これにより、/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 OS イメージを確認します。
- TPU VM を管理する方法を学習する。