本页面介绍如何在 Standard 模式下的 Google Kubernetes Engine (GKE) 集群中最大限度地提高高性能 GPU 工作负载的网络带宽和吞吐量。本页面适用于为机器学习 (ML) 工作负载提供支持的机器学习工程师和平台管理员。您应该已熟悉网络接口卡 (NIC) 和 TCP 等网络技术,以及 NVIDIA Collective Communications Library (NCCL) 等加速器技术。
人工智能 (AI)、机器学习和高性能计算 (HPC) 应用需要通过缩短作业完成时间来获得极大的加速,从而优化性能。例如,用于对话式 AI 和图像生成的机器学习模型需要强大的可伸缩性和计算能力。
Google Cloud GPU 超级计算机简介
Google Cloud 提供专为可伸缩的大型模型构建的加速器优化超级计算机。这种机器具有以下优势:
- 每个机器搭载八个 NVIDIA H100 GPU。
- 主 NIC 可支持最高 200 Gbps 的带宽。
- 最多可具有四个次要 NIC,每个 NIC 可支持最高 200 Gbps 的 GPU 数据传输带宽。
如需查看完整的优势列表,请参阅 Compute Engine 文档中的 A3 机器系列。
您的 GKE 工作负载必须使用单个节点上所有可用的 GPU 和所有可用的次要 NIC,并使用大部分的可用带宽。本文档中所述的解决方案非常适合需要高性能、高吞吐量和低延迟的工作负载。
最大限度地提高带宽所必需的特性和功能
如需最大限度地提高 GPU 超级计算机节点中的网络带宽,请使用以下所有功能:
- GPUDirect-TCPX:减少与 GPU 传输数据包载荷所需的开销,与不使用 GPUDirect-TCPX 的 GPU 相比,可大幅提高吞吐量。
- gVNIC:支持 GPUDirect-TCPX 功能,例如数据包标头拆分、流导向和缓冲区管理。使用 GPUDirect-TCPX 需要 gVNIC。如需详细了解 gVNIC,请参阅提高 GPU 节点的网络流量速度。
- 多网络:将次要 NIC 添加到加速器优化的机器。对于 A3 机器,添加四个额外的 NIC。为避免冲突,每个 NIC 都与其专属的 VPC 中的单独子网相关联。如需详细了解多网络支持,请参阅设置 Pod 的多网络支持。
- 布置政策:使用资源布置政策将特定工作负载的所有 GPU 节点放置在物理位置彼此靠近的服务器上,以最大限度地缩短延迟时间。如需了解详情,请参阅为 GKE 节点定义紧凑布置。
流程概览
如需使用所有这些功能,您需要完成以下任务:
- 创建 Virtual Private Cloud (VPC) 和子网
- 创建 GKE 环境:
- 创建启用多网络的集群
- 创建具有以下特征的节点池:
- 启用了 gVNIC
- 为每个次要 NIC 指定了多网络子网
- 节点使用搭载 H100 GPU(4 个次要 NIC 和 8 个 GPU)的 A3 机器系列
- 安装了最新 NVIDIA 驱动程序
- 安装 GPUDirect-TCPX 二进制文件和 NCCL 插件
- 部署测试工作负载以验证 GPUDirect-TCPX 设置
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
- 确保您有足够的 H100 GPU 配额。如需申请更多配额,请参阅 GPU 配额。
使用要求
- GPUDirect-TCPX 在 GKE 1.27 版或更高版本上受支持,并且需要:
- 对于 GKE 1.27 版,请使用 GKE 补丁 1.27.7-gke.1121000 版或更高版本。
- 对于 GKE 1.28 版,请使用 GKE 补丁 1.28.8-gke.1095000 版或更高版本。
- 对于 GKE 1.29 版,请使用 GKE 补丁 1.29.3-gke.1093000 版或更高版本。
- 您的 GPU 节点必须使用 535 或更高版本的 NVIDIA 驱动程序。
- 您必须使用 GKE Dataplane V2。
限制
存在以下限制:
- 您无法在 Autopilot 集群中使用 GPUDirect-TCPX
- 您只能在 GKE 1.27 版或更高版本上并且通过以下补丁版本来使用 GPUDirect-TCPX:
- 对于 GKE 1.27 版,请使用 GKE 补丁 1.27.7-gke.1121000 版或更高版本。
- 对于 GKE 1.28 版,请使用 GKE 补丁 1.28.8-gke.1095000 版或更高版本。
- 对于 GKE 1.29 版,请使用 GKE 补丁 1.29.3-gke.1093000 版或更高版本。
- 您无法将 GPUDirect-TCPX 与多实例 GPU 或 GPU 分时搭配使用
- 您无法使用 NCCL FastSocket
- 您的环境必须支持在 Pod 规范中设置
hostNetwork: true
如需将本地 SSD 用于 Pod 存储,您必须明确指定要挂接到底层 A3 虚拟机的本地 SSD 的确切数量,为此,对于临时存储请使用
--ephemeral-storage-local-ssd=count=SSD_COUNT
标志,对于块存储访问请使用--local-nvme-ssd-block=count=SSD_COUNT
标志。如果省略此标志,您将无法在 Pod 中使用本地 SSD。仅当您想要将本地 SSD 用于数据访问时才需要这些标志。GKE 中支持的机器大小为
a3-highgpu-8g
,相应的本地 SSD 数量为16
。
创建 VPC 和子网
在项目中为将要添加到节点的每个虚拟 NIC 创建单独的 VPC 网络。每个 VPC 都必须具有一个子网和一条允许内部网络流量的防火墙规则。为了最大限度地提高带宽,我们建议您创建四个新网络。
更新项目中的默认 VPC 子网,以便为 Pod 和 Service 添加次要 IP 地址范围:
gcloud compute networks subnets update DEFAULT_NETWORK \ --region=REGION \ --add-secondary-ranges="CLUSTER_NAME-pods=POD_IP_ADDRESS_RANGE,CLUSTER_NAME-services=SERVICE_IP_ADDRESS_RANGE"
替换以下内容:
DEFAULT_NETWORK
:项目中默认子网的名称。REGION
:默认子网的区域。CLUSTER_NAME
:GKE 集群的名称。POD_IP_ADDRESS_RANGE
:要使用的集群中 Pod 的 IP 地址范围(采用 CIDR 表示法)。例如10.64.0.0/19
。SERVICE_IP_ADDRESS_RANGE
:要使用的集群中 Service 的 IP 地址范围(采用 CIDR 表示法)。必须与 Pod 范围不同。例如10.65.0.0/19
。
在项目中为 GPUDirect-TCPX 创建 VPC 网络,每个 VPC 网络都具有一个子网和一条防火墙规则:
for N in $(seq 1 4); do gcloud compute networks create PROJECT_ID-net-$N \ --subnet-mode=custom \ --mtu=8244 gcloud compute networks subnets create PROJECT_ID-sub-$N \ --network=PROJECT_ID-net-$N \ --region=REGION \ --range=SUBNET_RANGE gcloud compute firewall-rules create PROJECT_ID-internal-$N \ --network=PROJECT_ID-net-$N \ --action=ALLOW \ --rules=tcp:0-65535,udp:0-65535,icmp \ --source-ranges=SOURCE_RANGE done
替换以下内容:
PROJECT_ID
:您的 Google Cloud 项目 ID。REGION
:每个子网的 Compute Engine 区域。SUBNET_RANGE
:每个子网的 IP 地址范围,采用 CIDR 表示法。此示例命令将针对四个子网进行迭代,因此请使用变量来更改每个子网的 IP 地址。例如,指定192.168.$N.0/24
,从而使第一个子网使用192.168.1.0/24
,第二个子网使用192.168.2.0/24
,以此类推。SOURCE_RANGE
:允许入站流量的防火墙规则的来源 IP 地址范围(采用 CIDR 表示法)。例如192.168.0.0/16
。
验证网络已创建:
gcloud compute networks list
创建 GKE 环境
创建一个使用多网络(预览版)的新 GKE 集群,并创建一个 GPU 节点池,该节点池使用搭载 H100 GPU 并具有四个额外 NIC 的 A3 机器。您无法通过更新现有集群来使用多网络。
创建集群:
gcloud container clusters create CLUSTER_NAME \ --location=LOCATION \ --cluster-version=VERSION \ --enable-dataplane-v2 --enable-ip-alias \ --enable-multi-networking \ --no-enable-autoupgrade \ --cluster-secondary-range-name=CLUSTER_NAME-pods \ --services-secondary-range-name=CLUSTER_NAME-services
替换以下内容:
CLUSTER_NAME
:新集群的名称。LOCATION
:集群的 Compute Engine 区域。VERSION
:集群的 GKE 版本。必须是“要求”部分中所述的受支持版本。
此命令还明确指定了您在上一部分中创建的集群中 Pod 和 Service 的次要 IP 地址。
在与您创建的 VPC 网络和子网相对应的集群中创建 Network 和 GKENetworkParamSet 资源:
kubectl apply -f - <<EOF apiVersion: networking.gke.io/v1 kind: Network metadata: name: vpc1 spec: parametersRef: group: networking.gke.io kind: GKENetworkParamSet name: vpc1 type: Device --- apiVersion: networking.gke.io/v1 kind: Network metadata: name: vpc2 spec: parametersRef: group: networking.gke.io kind: GKENetworkParamSet name: vpc2 type: Device --- apiVersion: networking.gke.io/v1 kind: Network metadata: name: vpc3 spec: parametersRef: group: networking.gke.io kind: GKENetworkParamSet name: vpc3 type: Device --- apiVersion: networking.gke.io/v1 kind: Network metadata: name: vpc4 spec: parametersRef: group: networking.gke.io kind: GKENetworkParamSet name: vpc4 type: Device --- apiVersion: networking.gke.io/v1 kind: GKENetworkParamSet metadata: name: vpc1 spec: vpc: PROJECT_ID-net-1 vpcSubnet: PROJECT_ID-sub-1 deviceMode: NetDevice --- apiVersion: networking.gke.io/v1 kind: GKENetworkParamSet metadata: name: vpc2 spec: vpc: PROJECT_ID-net-2 vpcSubnet: PROJECT_ID-sub-2 deviceMode: NetDevice --- apiVersion: networking.gke.io/v1 kind: GKENetworkParamSet metadata: name: vpc3 spec: vpc: PROJECT_ID-net-3 vpcSubnet: PROJECT_ID-sub-3 deviceMode: NetDevice --- apiVersion: networking.gke.io/v1 kind: GKENetworkParamSet metadata: name: vpc4 spec: vpc: PROJECT_ID-net-4 vpcSubnet: PROJECT_ID-sub-4 deviceMode: NetDevice EOF
这些资源会告诉 GKE 以直通模式为 GPU 流量配置 NIC。GKE 不会为此流量应用使用 eBPF 的内置网络编程。
为 H100 GPU 创建节点池:
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --location=LOCATION \ --machine-type=a3-highgpu-8g \ --accelerator=type=nvidia-h100-80gb,count=8,gpu-driver-version=LATEST \ --additional-node-network=network=PROJECT_ID-net-1,subnetwork=PROJECT_ID-sub-1 \ --additional-node-network=network=PROJECT_ID-net-2,subnetwork=PROJECT_ID-sub-2 \ --additional-node-network=network=PROJECT_ID-net-3,subnetwork=PROJECT_ID-sub-3 \ --additional-node-network=network=PROJECT_ID-net-4,subnetwork=PROJECT_ID-sub-4 \ --enable-gvnic \ --no-enable-autoupgrade \ [--ephemeral-storage-local-ssd=count=16]
将
NODE_POOL_NAME
替换为节点池的名称。如果此命令失败,则您的项目中可能没有足够的 H100 GPU 配额。确保您拥有配额,然后重试命令。
获取集群中的节点列表:
kubectl get nodes
验证每个 GPU 节点都有八个 GPU:
kubectl describe node NODE_NAME
输出类似于以下内容:
Capacity: ... nvidia.com/gpu: 8 Allocatable: ... nvidia.com/gpu: 8
安装 GPUDirect-TCPX 并配置 NCCL
本部分介绍如何使用 DaemonSet 安装 GPUDirect-TCPX 二进制文件和特定 NCCL。
查看 DaemonSet 清单:
此 DaemonSet 会执行以下操作:
- 在节点上安装 NCCL 库和 GPUDirect-TCPX 二进制文件。
- 将库和二进制文件存储在虚拟机上的
/home/kubernetes/bin/nvidia/lib64
目录中。默认情况下,GKE 会将此目录装载到需要使用 NCCL 和 GPUDirect-TCPX 的 GPU 容器中的/usr/local/nvidia/lib64
路径中。
部署 DaemonSet:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-tcpx-installer.yaml
NCCL 插件大约需要两分钟才能开始运行。
验证 DaemonSet Pod 的状态:
kubectl get pods -n=kube-system -l=name=nccl-tcpx-installer
输出类似于以下内容:
nccl-tcpx-installer-6c2pv 1/1 Running 0 2m11s nccl-tcpx-installer-qgg82 1/1 Running 0 2m11s
部署测试工作负载
在本部分中,您将部署一个示例工作负载来验证 NCCL 和 GPUDirect-TCPX 按预期运行。此工作负载包含一个名为 tcpx-daemon 的边车容器,它运行一个服务以使 Pod 能够使用 GPUDirect-TCPX。您必须将此边车容器添加到您自己环境中需要使用 GPUDirect-TCPX 的所有 Pod。如需查看要添加到清单的必填字段的代码段,请参阅本文档中的将 GPUDirect-TCPX 添加到清单。
- 查看 GitHub 中的
nccl-config-default.yaml
ConfigMap 清单。此清单部署初始化 NCCL allgather 测试的脚本并设置特定于 NCCL 的环境变量。 查看 GitHub 中的
nccl-test.yaml
清单。此清单执行以下操作:- 部署两个 Pod,每个 Pod 都在具有 H100 GPU 的节点中运行。
- 在每个 Pod 中部署一个名为
tcpx-daemon
的边车容器,以使这些 Pod 能够使用 GPUDirect-TCPX。
部署 ConfigMap 和测试工作负载:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-config-default.yaml kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-test.yaml
运行以下命令以触发节点的 NCCL all-gather 测试:
head_pod=$(kubectl get pods --output='custom-columns=POD:.metadata.name' --no-headers | head -n1) nodes=($(kubectl get pods --output='custom-columns=NODE:.spec.nodeName' --no-headers)) kubectl exec --stdin --tty --container=nccl-test ${head_pod} -- /configs/allgather.sh ${nodes[@]}
输出类似于以下内容:
# out-of-place in-place # size count type redop root time algbw busbw #wrong time algbw busbw #wrong # (B) (elements) (us) (GB/s) (GB/s) (us) (GB/s) (GB/s) 1048576 16384 float none -1 696.8 1.50 1.41 0 729.0 1.44 1.35 0 2097152 32768 float none -1 776.4 2.70 2.53 0 726.7 2.89 2.71 0 4194304 65536 float none -1 774.3 5.42 5.08 0 805.1 5.21 4.88 0 8388608 131072 float none -1 812.1 10.33 9.68 0 817.6 10.26 9.62 0 16777216 262144 float none -1 1035.2 16.21 15.19 0 1067.8 15.71 14.73 0 33554432 524288 float none -1 1183.3 28.36 26.59 0 1211.8 27.69 25.96 0 67108864 1048576 float none -1 1593.4 42.12 39.49 0 1510.5 44.43 41.65 0 134217728 2097152 float none -1 2127.8 63.08 59.13 0 2312.7 58.03 54.41 0 268435456 4194304 float none -1 3603.0 74.50 69.85 0 3586.2 74.85 70.17 0 536870912 8388608 float none -1 7101.7 75.60 70.87 0 7060.9 76.03 71.28 0 # Out of bounds values : 0 OK # Avg bus bandwidth : 29.8293
使用 NCCL 环境变量提高性能
您可以选择设置特定的环境变量,以提高使用 NCCL 的工作负载的性能。默认情况下,您在部署测试工作负载部分中部署的 nccl-config-default.yaml
ConfigMap 会设置一些 NCCL 变量。变量配置存储在 ConfigMap 中的 run-nccl.sh
脚本中。
如需更改 NCCL 环境变量,请部署包含修改变量的更新 ConfigMap 清单。GitHub 中的 nccl-config-latest.yaml
清单包含每个建议的变量以及更新的 run-nccl.sh
脚本。
以下命令使用更新后的 nccl-config-latest.yaml
ConfigMap 更新具有默认变量的现有 ConfigMap:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/gpudirect-tcpx/nccl-config-latest.yaml
Kubernetes 更新 ConfigMap 大约需要两分钟。
如需检查 NCCL 环境变量,请运行以下命令:
head_pod=$(kubectl get pods --output='custom-columns=POD:.metadata.name' --no-headers | head -n1)
kubectl exec --stdin --tty --container=nccl-test ${head_pod} -- cat /configs/run-nccl.sh
将 GPUDirect-TCPX 添加到清单
本部分提供了为使 Pod 能够使用 PodDirect-TCPX 而必须添加到 Kubernetes 清单的必填字段。
将以下字段添加到 Pod 规范中:
spec: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet volumes: - name: libraries hostPath: path: /home/kubernetes/bin/nvidia/lib64 - name: tcpx-socket hostPath: path: /run/tcpx
将以下容器添加到清单中以运行 tcpx-daemon 服务:
- name: tcpx-daemon image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpx/tcpgpudmarxd-dev:v2.0.9 command: - /tcpgpudmarxd/build/app/tcpgpudmarxd - --gpu_nic_preset - a3vm - --gpu_shmem_type - fd - --uds_path - /run/tcpx - --setup_param - \"--verbose 128 2 0 \" securityContext: privileged: true volumeMounts: - name: libraries mountPath: /usr/local/nvidia/lib64 - name: tcpx-socket mountPath: /run/tcpx env: - name: LD_LIBRARY_PATH value: /usr/local/nvidia/lib64
将以下卷装载添加到请求 GPU 的所有容器:
volumeMounts: - name: tcpx-socket mountPath: /tmp - name: libraries mountPath: /usr/local/nvidia/lib64
将以下环境变量添加到每个 GPU 容器:
env: - name: LD_LIBRARY_PATH value: /usr/local/nvidia/lib64
(可选)添加环境变量以配置 NCCL 选项。如需了解详情,请参阅本文档中的使用 NCCL 环境变量提高性能部分。
完成后的 Pod 规范如下所示:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
labels:
name: example-pod
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: tcpx-daemon
image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpx/tcpgpudmarxd-dev:v2.0.9
command:
- /tcpgpudmarxd/build/app/tcpgpudmarxd
- --gpu_nic_preset
- a3vm
- --gpu_shmem_type
- fd
- --uds_path
- /run/tcpx
- --setup_param
- \"--verbose 128 2 0 \"
securityContext:
privileged: true
volumeMounts:
- name: libraries
mountPath: /usr/local/nvidia/lib64
- name: tcpx-socket
mountPath: /run/tcpx
env:
- name: LD_LIBRARY_PATH
value: /usr/local/nvidia/lib64
- name: nccl-test
image: us-docker.pkg.dev/gce-ai-infra/gpudirect-tcpx/nccl-plugin-gpudirecttcpx:v3.1.2
imagePullPolicy: Always
command:
- /bin/sh
- -c
- "while true; do echo hello; sleep 1; done"
env:
- name: LD_LIBRARY_PATH
value: /usr/local/nvidia/lib64
volumeMounts:
- name: tcpx-socket
mountPath: /run/tcpx
- name: libraries
mountPath: /usr/local/nvidia/lib64
resources:
limits:
nvidia.com/gpu: 8
volumes:
- name: libraries
hostPath:
path: /home/kubernetes/bin/nvidia/lib64
- name: tcpx-socket
hostPath:
path: /run/tcpx