本教程介绍了如何使用 Ray Core、Ray Train、PyTorch Fully Sharded Data Parallel (FSDP2) 和 TorchTPU,在 Google Kubernetes Engine (GKE) 中的多主机 Cloud TPU 切片上运行分布式 PyTorch 工作负载并微调 Gemma 4 模型。
本教程适用于机器学习 (ML) 工程师、平台管理员和运维人员,以及希望在 Kubernetes 中的多主机 TPU 切片上编排分布式 PyTorch 训练工作负载的数据和 AI 专家。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。
在开始本教程之前,请确保您熟悉以下内容:
背景
本部分介绍本教程中使用的关键技术。
TPU
张量处理单元 (TPU) 是 Google 为机器学习工作负载定制设计的加速器。本教程同时支持 TPU Trillium (v6e) 和 Ironwood (TPU7x)。在多主机 TPU 切片中,多个 TPU 主机通过高速芯片间互连 (ICI) 网络直接通信,提供训练模型所需的聚合高带宽内存 (HBM) 和低延迟集体通信,这些模型超出了单个芯片或 TPU 主机的内存容量。
TorchTPU
TorchTPU 是适用于 Cloud TPU 的开源 PyTorch 后端,由 Google 和 Meta 合作开发。借助 TorchTPU,您只需对代码进行极少量的修改,即可在 TPU 硬件上运行现有的 PyTorch 模型,并通过加速线性代数 (XLA) 编译器将训练和推理工作负载从单芯片扩展到多切片 TPU Pod。TorchTPU 在 TPU ICI 网络上使用“每个设备一个进程”的执行模型,并支持标准 PyTorch API,包括即刻执行、torch.compile、torch.distributed、DeviceMesh、DTensor 和完全分片数据并行 (FSDP2)。
在 TPU 上运行 KubeRay 和 Ray
KubeRay 是一个 Kubernetes Operator,用于部署和管理 Ray 应用。启用 Ray on GKE 插件会部署托管式 KubeRay Operator 和 KubeRay TPU Webhook。当 KubeRay 创建请求 google.com/tpu 资源的 worker Pod 时,Webhook 会自动配置多主机协调所需的 Pod 主机名、无头 Service 和 TPU 环境变量。
Ray 会在启动时检测每个节点上的 TPU 拓扑,并在 TPU 切片之间调度分布式工作负载。您可以在两个级别编排分布式 TorchTPU 工作负载:
- Ray Core 为自定义分布式执行循环(例如张量并行计算或强化学习 [RL] 流水线)提供拓扑感知型放置组和 actor 调度。
- Ray Train 提供托管式分布式数据并行和模型并行训练,包括 PyTorch 分布式数据并行 (DDP)、PyTorch FSDP2 和 JAX 单程序多数据 (SPMD),并具有内置检查点和自动故障恢复功能。
目标
本教程介绍了如何执行以下操作:
- 在 TPU Trillium (v6e) 或 Ironwood (TPU7x) 上创建 Autopilot 或 Standard 模式的 GKE 集群。
- 构建一个容器映像,在 TorchTPU 基础映像之上叠加 Ray 和 Hugging Face 训练库。
- 部署 RayCluster 自定义资源,以预配头节点和 TPU 工作器节点。
- 使用 Ray Core 在 TPU 切片上通过 PyTorch
DeviceMesh和DTensor运行分布式张量并行计算。 - 使用 Ray Train,通过 PyTorch FSDP2 在多主机 TPU 切片上微调 Gemma 4 模型。
费用
在本教程中,您将使用 Google Cloud的以下收费组件:
您可使用价格计算器根据您的预计使用量来估算费用。
完成本教程中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Artifact Registry API、Cloud Storage API 和 Google Kubernetes Engine API。 启用 API
- 如需使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行
gcloud components update命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
- 验证您的项目在所选可用区中是否有足够的 TPU Trillium (v6e) 或 Ironwood (TPU7x) 容量配额。如需了解详情,请参阅 Cloud TPU 配额。
- 确保您的账号具有以下 IAM 角色:
- Kubernetes Engine Admin (
roles/container.admin) - Artifact Registry Administrator (
roles/artifactregistry.admin) - Storage Admin (
roles/storage.admin)
- Kubernetes Engine Admin (
准备环境
在本教程中,您将使用 Cloud Shell 来管理 Google Cloud上托管的资源。Cloud Shell 预安装了本教程所需的软件,包括 kubectl、docker、python3 和 gcloud CLI。
如需使用 Cloud Shell 设置您的环境,请按照以下步骤操作:
在 Google Cloud 控制台中,点击Google Cloud 控制台中的
激活 Cloud Shell 以启动 Cloud Shell 会话。此操作会在 Google Cloud 控制台的底部窗格中启动会话。
克隆
kubernetes-engine-samples代码库并切换到本教程的示例目录:git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samples/ai-ml/gke-ray/raytrain/torchtpu创建并激活安装了 Ray CLI 的本地 Python 虚拟环境:
python3 -m venv ~/ray-env source ~/ray-env/bin/activate pip install "ray[default]==2.58.0"如需下载 Gemma 4 模型权重,请在 Hugging Face 上确认 Google 许可协议:
- 前往 Hugging Face 上的 Gemma 4 模型页面。
- 登录并点击同意并访问代码库,接受许可条款。
- 在 Hugging Face 账号设置中,生成具有
Read权限的用户访问令牌。
为您的 Google Cloud 项目、集群、Cloud Storage 存储桶和 Hugging Face 令牌设置环境变量:
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=CLUSTER_NAME export REGION=REGION export ZONE=ZONE export ARTIFACT_REGISTRY=ARTIFACT_REGISTRY export BUCKET_NAME=BUCKET_NAME export HF_TOKEN=HF_TOKEN export IMAGE_URI=${REGION}-docker.pkg.dev/${PROJECT_ID}/${ARTIFACT_REGISTRY}/ray-torchtpu:latest gcloud config set project ${PROJECT_ID}替换以下内容:
PROJECT_ID:您的 Google Cloud 项目 ID。CLUSTER_NAME:GKE 集群的名称,例如ray-torchtpu-cluster。REGION:Artifact Registry 代码库、Cloud Storage 存储桶和 TPU 容量所在的区域。ZONE:您的 TPU 容量所在的可用区。如需了解按 TPU 版本划分的可用区域和可用区,请参阅 TPU 区域和可用区。ARTIFACT_REGISTRY:Artifact Registry Docker 仓库的名称,例如ray-torchtpu。BUCKET_NAME:用于存储 Ray Train 检查点的 Cloud Storage 存储桶的名称,例如PROJECT_ID-ray-torchtpu。HF_TOKEN:您的 Hugging Face 访问令牌。
创建 GKE 集群
您可以在启用了托管式 Ray Operator 插件的 GKE Autopilot 或 Standard 集群中运行分布式 TorchTPU 训练工作负载。
创建 GKE 集群并为
kubectl命令行工具配置凭据:Autopilot
创建启用了 Ray Operator 插件的区域级 GKE Autopilot 集群:
gcloud container clusters create-auto ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --region=${REGION} \ --cluster-version=1.36 \ --enable-ray-operator在后面的步骤中部署 RayCluster 自定义资源时,GKE Autopilot 会自动预配与 Pod 资源请求和节点选择器匹配的 CPU 头节点和多主机 TPU 切片。
配置
kubectl命令行工具以与您的集群通信:gcloud container clusters get-credentials ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --region=${REGION}
标准
创建一个可用区级 GKE Standard 集群,该集群具有一个 CPU 节点池,用于托管 Ray 头部 Pod,并启用了映像流式传输、GKE Dataplane V2 和 Workload Identity Federation for GKE:
gcloud container clusters create ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --zone=${ZONE} \ --cluster-version=1.36 \ --machine-type=n2-standard-8 \ --num-nodes=1 \ --addons=RayOperator \ --enable-image-streaming \ --enable-dataplane-v2 \ --workload-pool=${PROJECT_ID}.配置
kubectl命令行工具以与您的集群通信:gcloud container clusters get-credentials ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --zone=${ZONE}在 TPU Trillium (v6e) 上创建一个包含 16 个设备的多主机 TPU 切片节点池,该节点池具有跨 4 个主机的
4x4拓扑;或在 Ironwood (TPU7x) 上创建一个包含 16 个设备的多主机 TPU 切片节点池,该节点池具有跨 2 个主机的2x2x2拓扑:Trillium (v6e)
gcloud container node-pools create tpu-multi-host-pool \ --project=${PROJECT_ID} \ --cluster=${CLUSTER_NAME} \ --zone=${ZONE} \ --machine-type=ct6e-standard-4t \ --tpu-topology=4x4 \ --num-nodes=4Ironwood (TPU7x)
gcloud container node-pools create tpu-multi-host-pool \ --project=${PROJECT_ID} \ --cluster=${CLUSTER_NAME} \ --zone=${ZONE} \ --machine-type=tpu7x-standard-4t \ --tpu-topology=2x2x2 \ --num-nodes=2
创建一个 Cloud Storage 存储桶,用于存储多主机 TPU 节点之间共享的 Ray Train 检查点,并向
defaultKubernetes ServiceAccount 资源授予对该存储桶的访问权限:gcloud storage buckets create gs://${BUCKET_NAME} --location=${REGION} PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \ --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}./subject/ns/default/sa/default" \ --role="roles/storage.objectAdmin"使用您的 Hugging Face 访问令牌创建一个 Kubernetes Secret,以便 Ray Pod 可以下载受限的 Gemma 4 权重:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN}
构建容器映像
构建一个容器映像,在预构建的 TorchTPU 基础映像(包含 TorchTPU 和 libtpu 库)之上安装 Ray 和 Hugging Face 训练库。
创建 Artifact Registry Docker 代码库并配置 Docker 身份验证:
gcloud artifacts repositories create ${ARTIFACT_REGISTRY} \ --repository-format=docker \ --location=${REGION} gcloud auth configure-docker ${REGION}-docker.pkg.dev,us-docker.pkg.dev检查示例目录中的
Dockerfile:在 Ironwood (TPU7x) 上使用 Ray
TorchTrainer类进行单切片训练和按小芯片调度需要 Ray 2.58.0 或更高版本,而微调 Gemma 4 需要transformers库 5.5.0 或更高版本。构建映像并将其推送到 Artifact Registry:
docker build -t ${IMAGE_URI} . docker push ${IMAGE_URI}
部署 RayCluster 自定义资源
部署 RayCluster 自定义资源,该资源会预配一个 CPU 头 Pod、一个用于 Ray 共享内存对象存储区的内存中 /dev/shm 卷,以及一个多主机 TPU 工作进程组。
在示例代码库中查看适用于您的 TPU 版本的 RayCluster 清单:
Trillium (v6e)
Ironwood (TPU7x)
在 Ironwood (TPU7x) 上,每个物理芯片包含两个芯粒,每个四芯片主机提供八个逻辑 TPU 核心。清单会将
resources部分中的TPU字段值设置为"8",并将RAY_TPU_RESOURCE_PER_CHIP环境变量设置为"2",以便在每台主机上通告和调度 8 个逻辑TPU资源。应用清单以创建 RayCluster 自定义资源:
Trillium (v6e)
envsubst < ray-cluster.tpu-v6e-multihost.yaml | kubectl apply -f -Ironwood (TPU7x)
envsubst < ray-cluster.tpu-v7x-multihost.yaml | kubectl apply -f -等待 RayCluster 头 Pod 和所有 TPU 工作进程 Pod 达到
Running状态:kubectl get pods -l ray.io/cluster=ray-torchtpu-cluster输出类似于以下内容:
Trillium (v6e)
NAME READY STATUS RESTARTS AGE ray-torchtpu-cluster-head-pdpk6 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-brwpc 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-dx4w7 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-h4d4w 1/1 Running 0 2m30s ray-torchtpu-cluster-v6e-16-worker-t2g24 1/1 Running 0 2m30sIronwood (TPU7x)
NAME READY STATUS RESTARTS AGE ray-torchtpu-cluster-head-k9x2m 1/1 Running 0 2m30s ray-torchtpu-cluster-tpu7x-16-worker-7cwpq 1/1 Running 0 2m30s ray-torchtpu-cluster-tpu7x-16-worker-m98r9 1/1 Running 0 2m30s检查其中一个工作器 Pod 上的环境变量,确认 KubeRay TPU 网络钩子已注入多主机 TPU 协调和 TorchTPU 拓扑变量:
kubectl get pods -l ray.io/node-type=worker \ -o=jsonpath='{range .items[0].spec.containers[0].env[*]}{.name}={.value}{"\n"}{end}' \ | grep -E "TPU_WORKER_ID|TPU_WORKER_HOSTNAMES|TPU_NAME|TORCH_TPU_TOPOLOGY|TORCH_TPU_SLICEBUILDER_ADDRESSES"输出类似于以下内容:
Trillium (v6e)
TPU_WORKER_HOSTNAMES=v6e-16-0-0.ray-torchtpu-cluster-headless,v6e-16-0-1.ray-torchtpu-cluster-headless,v6e-16-0-2.ray-torchtpu-cluster-headless,v6e-16-0-3.ray-torchtpu-cluster-headless TORCH_TPU_TOPOLOGY=4,4,1 TORCH_TPU_SLICEBUILDER_ADDRESSES=v6e-16-0-0.ray-torchtpu-cluster-headless:8471,v6e-16-0-0.ray-torchtpu-cluster-headless:8472,v6e-16-0-0.ray-torchtpu-cluster-headless:8473,v6e-16-0-0.ray-torchtpu-cluster-headless:8474,v6e-16-0-1.ray-torchtpu-cluster-headless:8471,v6e-16-0-1.ray-torchtpu-cluster-headless:8472,v6e-16-0-1.ray-torchtpu-cluster-headless:8473,v6e-16-0-1.ray-torchtpu-cluster-headless:8474,v6e-16-0-2.ray-torchtpu-cluster-headless:8471,v6e-16-0-2.ray-torchtpu-cluster-headless:8472,v6e-16-0-2.ray-torchtpu-cluster-headless:8473,v6e-16-0-2.ray-torchtpu-cluster-headless:8474,v6e-16-0-3.ray-torchtpu-cluster-headless:8471,v6e-16-0-3.ray-torchtpu-cluster-headless:8472,v6e-16-0-3.ray-torchtpu-cluster-headless:8473,v6e-16-0-3.ray-torchtpu-cluster-headless:8474 TPU_WORKER_ID=3 TPU_NAME=v6e-16-0Ironwood (TPU7x)
TPU_WORKER_HOSTNAMES=tpu7x-16-0-0.ray-torchtpu-cluster-headless,tpu7x-16-0-1.ray-torchtpu-cluster-headless TORCH_TPU_TOPOLOGY=2,2,2,2 TORCH_TPU_SLICEBUILDER_ADDRESSES=tpu7x-16-0-0.ray-torchtpu-cluster-headless:8471,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8472,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8473,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8474,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8475,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8476,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8477,tpu7x-16-0-0.ray-torchtpu-cluster-headless:8478,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8471,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8472,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8473,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8474,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8475,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8476,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8477,tpu7x-16-0-1.ray-torchtpu-cluster-headless:8478 TPU_WORKER_ID=1 TPU_NAME=tpu7x-16-0建立到 Ray 头服务的端口转发会话:
kubectl port-forward svc/ray-torchtpu-cluster-head-svc 8265:8265 >/dev/null 2>&1 &您可以在 Ray 信息中心的集群标签页中检查 TPU 工作器节点及其自动检测到的
ray.io/tpu-*标签。
使用 Ray Core 运行分布式张量并行处理
Ray Core 在 ray.util.tpu 模块中提供了 slice_placement_group 函数,用于预留完整的多主机 TPU 切片;还提供了 PlacementGroupSchedulingStrategy 类,用于在切片中的每个逻辑 TPU 设备上调度一个 Ray actor。
查看示例代码库中的
ray_core_collectives.py脚本:该脚本分三步在 TPU 切片上运行分布式张量并行处理:
slice_placement_group函数会预留一个 16 设备 TPU 切片,并在每个 TPU 设备上调度一个TorchTPUSliceWorkeractor。- 每个 actor 都会根据其主机索引和本地设备 ID 计算其全局排名,然后初始化
tpu_dist进程组。 init_device_mesh和parallelize_module函数会将前馈层分片到所有 16 个 TPU 设备上,根据单设备 CPU 参考值验证输出,并通过 ICI 运行all_reduce集合。
提交适用于您的 TPU 版本的 Ray Core 作业:
Trillium (v6e)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_core_collectives.py --topology=4x4 --accelerator-type=TPU-V6EIronwood (TPU7x)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_core_collectives.py --topology=2x2x2 --accelerator-type=TPU-V7X输出类似于以下内容:
Trillium (v6e)
Rank 0 (worker_id=0, local_rank=0, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 1 (worker_id=0, local_rank=1, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 2 (worker_id=0, local_rank=2, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 3 (worker_id=0, local_rank=3, ip=10.72.3.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 4 (worker_id=1, local_rank=0, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 5 (worker_id=1, local_rank=1, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 6 (worker_id=1, local_rank=2, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 7 (worker_id=1, local_rank=3, ip=10.72.14.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 8 (worker_id=2, local_rank=0, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 9 (worker_id=2, local_rank=1, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 10 (worker_id=2, local_rank=2, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 11 (worker_id=2, local_rank=3, ip=10.72.7.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 12 (worker_id=3, local_rank=0, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 13 (worker_id=3, local_rank=1, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 14 (worker_id=3, local_rank=2, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 15 (worker_id=3, local_rank=3, ip=10.72.6.20): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] All 16 TorchTPU ranks verified DTensor TP parity (max_abs_diff=0.002470) and all_reduce sum = 136.0 ------------------------------------------ Job 'raysubmit_HFTkKrjSnfza3ZFD' succeeded ------------------------------------------Ironwood (TPU7x)
Rank 0 (worker_id=0, local_rank=0, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 1 (worker_id=0, local_rank=1, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 2 (worker_id=0, local_rank=2, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 3 (worker_id=0, local_rank=3, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 4 (worker_id=0, local_rank=4, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 5 (worker_id=0, local_rank=5, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 6 (worker_id=0, local_rank=6, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 7 (worker_id=0, local_rank=7, ip=172.16.14.6): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 8 (worker_id=1, local_rank=0, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 9 (worker_id=1, local_rank=1, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 10 (worker_id=1, local_rank=2, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 11 (worker_id=1, local_rank=3, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 12 (worker_id=1, local_rank=4, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 13 (worker_id=1, local_rank=5, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 14 (worker_id=1, local_rank=6, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] Rank 15 (worker_id=1, local_rank=7, ip=172.16.15.7): all_reduce_sum=[136.0, 136.0, 136.0, 136.0] All 16 TorchTPU ranks verified DTensor TP parity (max_abs_diff=0.002470) and all_reduce sum = 136.0 ------------------------------------------ Job 'raysubmit_MrJbAe3hvARBcBN2' succeeded ------------------------------------------
使用 Ray Train 和 PyTorch FSDP2 微调 Gemma 4 模型
Ray Train TorchTrainer 类可自动执行 TPU 切片预留、工作器放置以及跨多主机 TPU 切片的 torch.distributed 初始化。
查看示例代码库中的
ray_train_llm_finetune.py脚本,该脚本使用databricks/databricks-dolly-15k指令数据集对google/gemma-4-E2B-it模型进行微调:该脚本使用以下组件配置
TorchTrainer类:ScalingConfig类用于为训练作业配置分布式工作器拓扑。设置use_tpu=True、num_workers=16、topology和accelerator_type参数会预留一个 16 设备 TPU 切片,并为每个 TPU 核心安排一个工作器。TorchConfig类在工作器之间配置torch.distributed进程组。设置backend="tpu_dist"参数会在train_func函数运行之前通过 TPU ICI 网络连接所有 16 个工作器。create_dataloader函数会下载指令数据集并对其进行分词,使用 PyTorchDataLoader对象对词元序列进行批处理,并调用ray.train.torch.prepare_data_loader函数,以便每个工作器在其分配的 TPU 设备上接收每个全局批次的不相交分片。train_func函数会以bfloat16精度加载模型,并在每个前馈块和根模型上调用 PyTorch FSDP2fully_shard函数,以在所有 16 个 TPU 核心之间对参数、梯度和优化器状态进行分片。Checkpoint类和ray.train.report函数会在每个周期结束时收集 rank 0 上的完整模型状态字典,并将检查点上传到 Cloud Storage 存储桶。
提交适用于您的 TPU 版本的
TorchTrainerFSDP2 微调作业:Trillium (v6e)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_train_llm_finetune.py \ --topology=4x4 \ --accelerator-type=TPU-V6E \ --storage-path=gs://${BUCKET_NAME}/ray_train_torchtpuIronwood (TPU7x)
ray job submit \ --address http://localhost:8265 \ --working-dir . \ --runtime-env-json '{"excludes": ["ray-env", ".git", "*.whl"]}' \ -- python3 ray_train_llm_finetune.py \ --topology=2x2x2 \ --accelerator-type=TPU-V7X \ --storage-path=gs://${BUCKET_NAME}/ray_train_torchtpu输出类似于以下内容:
Trillium (v6e)
Starting Ray Train FSDP2 SFT job: model=google/gemma-4-E2B-it, topology=4x4, accelerator_type=TPU-V6E, num_workers=16 (TrainController pid=5407) Attempting to start training worker group of size 16 with the following resources: [{'TPU': 1, 'accelerator_type:TPU-V6E': 0.001}] * 16 (RayTrainWorker pid=19733, ip=10.72.3.20) Setting up process group for: env:// [rank=0, world_size=16] (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 1/3 | loss=3.1402 | epoch_time=28.17s | tokens/s=18613.5 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-08-10.762175) (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 2/3 | loss=2.3318 | epoch_time=26.07s | tokens/s=20112.8 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-10-02.548088) (RayTrainWorker pid=19733, ip=10.72.3.20) Epoch 3/3 | loss=2.2050 | epoch_time=25.52s | tokens/s=20545.2 (RayTrainWorker pid=19733, ip=10.72.3.20) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-11-48.701853) Training completed! Final metrics: {'epoch': 3, 'loss': 2.205, 'epoch_time_s': 25.52, 'tokens_per_s': 20545.2} Saved checkpoint: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791864427/checkpoint_2026-10-13_04-11-48.701853) ------------------------------------------ Job 'raysubmit_zbm4pnFZitA1YECA' succeeded ------------------------------------------Ironwood (TPU7x)
Starting Ray Train FSDP2 SFT job: model=google/gemma-4-E2B-it, topology=2x2x2, accelerator_type=TPU-V7X, num_workers=16 (TrainController pid=1162) Attempting to start training worker group of size 16 with the following resources: [{'TPU': 1, 'accelerator_type:TPU-V7X': 0.001}] * 16 (RayTrainWorker pid=257, ip=172.16.26.6) Setting up process group for: env:// [rank=0, world_size=16] (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 1/3 | loss=3.1407 | epoch_time=26.28s | tokens/s=19953.3 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-52-00.026930) (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 2/3 | loss=2.3235 | epoch_time=16.68s | tokens/s=31429.9 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-53-33.533341) (RayTrainWorker pid=257, ip=172.16.26.6) Epoch 3/3 | loss=2.1964 | epoch_time=16.98s | tokens/s=30884.6 (RayTrainWorker pid=257, ip=172.16.26.6) Checkpoint successfully created at: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-55-01.508219) Training completed! Final metrics: {'epoch': 3, 'loss': 2.1964, 'epoch_time_s': 16.98, 'tokens_per_s': 30884.6} Saved checkpoint: Checkpoint(filesystem=gcs, path=my-project-ray-torchtpu/ray_train_torchtpu/torchtpu_gemma4_fsdp2_sft_1791867004/checkpoint_2026-10-13_04-55-01.508219) ------------------------------------------ Job 'raysubmit_zSNnCXhHkwKiSmJh' succeeded ------------------------------------------训练输出如下所示:
- 第 1 个周期包括初始 XLA 图编译。周期 2 和 3 重用
/dev/shm/torch_tpu_cache中缓存的可执行文件,在 TPU Trillium (v6e) 上达到每秒超过 20,000 个 token,在 Ironwood (TPU7x) 上达到每秒 31,000 个 token。 - 在
databricks/databricks-dolly-15k指令数据集上进行三个微调周期后,在所有 16 个 FSDP2 工作器等级之间同步的全局交叉熵损失从第 1 个周期的 3.14 降至第 3 个周期的 2.20。 - 在每个周期结束时,rank 0 会收集完整的模型状态字典,并将检查点上传到您的 Cloud Storage 存储桶,同时保留
CheckpointConfig(num_to_keep=1, checkpoint_score_attribute="loss", checkpoint_score_order="min")对象中配置的损失最低的检查点。
- 第 1 个周期包括初始 XLA 图编译。周期 2 和 3 重用
观察工作负载性能
如需在 Cloud Monitoring 中监控 TPU TensorCore 利用率、HBM 用量和 Ray 集群指标,请参阅收集和查看 GKE 上的 Ray 集群的日志和指标以及在 Ray 信息中心内查看 TPU 指标。
访问 Ray 信息中心
如需在内置 Ray 信息中心内检查 Ray actor、放置组和训练作业的状态,请按照以下步骤操作:
如果到 Ray 头服务的端口转发尚未运行,请在后台启动:
kubectl port-forward svc/ray-torchtpu-cluster-head-svc 8265:8265 >/dev/null 2>&1 &在 Cloud Shell 中,点击
网页预览,然后选择在端口 8265 上预览,或在本地浏览器中打开
http://localhost:8265。点击作业、集群和指标标签页,检查工作器日志、展示位置组状态、TPU 节点标签和按节点划分的 TPU 利用率图表。
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除 RayCluster 自定义资源、GKE 集群、Cloud Storage 存储桶和 Artifact Registry 代码库:
停止后台端口转发进程,并删除 RayCluster 自定义资源和 Kubernetes Secret:
pkill -f "kubectl port-forward" || true kubectl delete raycluster ray-torchtpu-cluster kubectl delete secret hf-secret --ignore-not-found删除 GKE 集群:
Autopilot
gcloud container clusters delete ${CLUSTER_NAME} \ --region=${REGION}标准
gcloud container clusters delete ${CLUSTER_NAME} \ --zone=${ZONE}删除 Cloud Storage 存储桶及其检查点内容:
gcloud storage rm --recursive gs://${BUCKET_NAME}删除 Artifact Registry 代码库:
gcloud artifacts repositories delete ${ARTIFACT_REGISTRY} \ --location=${REGION}
后续步骤
- 详细了解 Cloud TPU 上的 PyTorch。
- 浏览 TorchTPU 文档。
- 了解如何使用 Ray 和 TorchTPU 在多主机 TPU 上部署 LLM。
- 了解如何使用 DWS 和 Kueue 优化 TPU 上的 AI 训练。
- 阅读 GKE 中的 TPU 简介。
- 浏览 Ray Train 文档。