使用GPU#
本文档提供了使用 KubeRay 进行 GPU 使用的技巧。
要在 Kubernetes 上使用 GPU,需要配置您的 Kubernetes 设置,并在您的 Ray 集群配置中添加额外的值。
要了解不同云上的GPU使用情况,请参阅 GKE 、 EKS 和 AKS 的说明。
快速入门:提供基于GPU的StableDiffusion模型#
你可以在文档的 示例 部分找到几个 GPU 工作负载示例。 StableDiffusion 示例 是一个不错的起点。
基于GPU的机器学习依赖项#
Ray Docker Hub 托管了基于CUDA的容器镜像,这些镜像打包了Ray和某些机器学习库。例如,镜像 rayproject/ray-ml:2.6.3-gpu
非常适合使用Ray 2.6.3运行基于GPU的ML工作负载。Ray ML镜像打包了这些文档中使用的Ray库所需的依赖项(如TensorFlow和PyTorch)。要添加自定义依赖项,请使用以下两种方法之一或两者:
使用官方的 Ray docker 镜像 之一作为基础构建 docker 镜像。
使用 Ray 运行时环境。
为 GPU 使用配置 Ray Pod#
使用 Nvidia GPU 需要在 RayCluster
的 headGroupSpec
和/或 workerGroupSpecs
的容器字段中指定 nvidia.com/gpu
资源的 limits
和 requests
。
以下是一个 RayCluster 工作组配置片段,最多支持 5 个 GPU 工作节点。
groupName: gpu-group
replicas: 0
minReplicas: 0
maxReplicas: 5
...
template:
spec:
...
containers:
- name: ray-node
image: rayproject/ray-ml:2.6.3-gpu
...
resources:
nvidia.com/gpu: 1 # Optional, included just for documentation.
cpu: 3
memory: 50Gi
limits:
nvidia.com/gpu: 1 # Required to use GPU.
cpu: 3
memory: 50Gi
...
群组中的每个 Ray pod 都可以调度在 AWS p2.xlarge
实例上(1 个 GPU,4 个 vCPU,61Gi RAM)。
小技巧
GPU 实例是昂贵的 – 考虑为您的 GPU Ray 工作者设置自动扩展,如上述 minReplicas:0
和 maxReplicas:5
设置所示。要启用自动扩展,还要记得在 RayCluster 的 spec
中设置 enableInTreeAutoscaling:True
。最后,确保您配置了 GPU Kubernetes 节点的组或池,以进行自动扩展。有关自动扩展节点池的详细信息,请参阅您的 云提供商的文档。
GPU 多租户#
如果一个 Pod 在其资源配置中不包含 nvidia.com/gpu
,用户通常期望该 Pod 对任何 GPU 设备无感知,即使它被调度到一个 GPU 节点上。然而,当 nvidia.com/gpu
未被指定时,NVIDIA_VISIBLE_DEVICES
的默认值变为 all
,使得 Pod 能够感知节点上的所有 GPU 设备。这种行为并非 KubeRay 独有,而是 NVIDIA 已知的问题。一个变通方法是,在不需要 GPU 设备的 Pod 中将 NVIDIA_VISIBLE_DEVICES
环境变量设置为 void
。
一些有用的链接:
GPUs 和 Ray#
本节讨论在 Kubernetes 上运行的 Ray 应用程序的 GPU 使用情况。有关 Ray 中 GPU 使用的常规指导,另请参阅 加速器支持。
KubeRay 操作符向 Ray 调度器和 Ray 自动缩放器通告容器 GPU 资源限制。特别是,Ray 容器的 ray start
入口点将自动配置适当的 --num-gpus
选项。
GPU 工作负载调度#
在部署了可以访问GPU的Ray pod之后,它将能够执行带有gpu请求注释的任务和角色。例如,装饰器 @ray.remote(num_gpus=1)
注释了一个需要1个GPU的任务或角色。
GPU 自动扩展#
Ray 自动扩展器了解每个 Ray 工作组中的 GPU 容量。假设我们有一个如上配置片段中配置的 RayCluster:
Ray 的 Pod 有一个工作组,每个 Pod 都有 1 单位的 GPU 容量。
Ray 集群当前没有该组的任何工作节点。
maxReplicas
对于该组至少为 2。
然后,以下 Ray 程序将触发 2 个 GPU 工作节点的扩展。
import ray
ray.init()
@ray.remote(num_gpus=1)
class GPUActor:
def say_hello(self):
print("I live in a pod with GPU access.")
# Request actor placement.
gpu_actors = [GPUActor.remote() for _ in range(2)]
# The following command will block until two Ray pods with GPU access are scaled
# up and the actors are placed.
ray.get([actor.say_hello.remote() for actor in gpu_actors])
程序退出后,角色将被垃圾回收。GPU工作节点将在空闲超时后缩减(默认60秒)。如果GPU工作节点运行在Kubernetes节点的自动扩展池中,Kubernetes节点也将被缩减。
请求GPU#
您也可以向 自动扩展器 直接请求以扩展GPU资源。
import ray
ray.init()
ray.autoscaler.sdk.request_resources(bundles=[{"GPU": 1}] * 2)
在节点被扩展后,它们将持续存在,直到请求被明确覆盖。以下程序将移除资源请求。
import ray
ray.init()
ray.autoscaler.sdk.request_resources(bundles=[])
GPU 工作节点随后可以缩减规模。
覆盖 Ray GPU 容量(高级)#
对于专业用途,可以覆盖 Ray pod 向 Ray 报告的 GPU 容量。为此,请为头节点或工作组 rayStartParams
的 num-gpus
键设置一个值。例如,
rayStartParams:
# Note that all rayStartParam values must be supplied as strings.
num-gpus: "2"
Ray 调度器和自动扩展器将为组中的每个 Ray pod 计算 2 个 GPU 容量单位,即使容器限制没有表明 GPU 的存在。
GPU 吊舱调度 (高级)#
GPU 污点和容忍#
备注
托管的 Kubernetes 服务通常会为你处理与 GPU 相关的污点和容忍度。如果你使用的是托管的 Kubernetes 服务,你可能不需要担心这一部分。
Kubernetes 的 Nvidia gpu 插件 对 GPU 节点应用 污点;这些污点阻止非 GPU Pod 被调度到 GPU 节点上。像 GKE、EKS 和 AKS 这样的托管 Kubernetes 服务会自动将匹配的 容忍 应用到请求 GPU 资源的 Pod 上。容忍是通过 Kubernetes 的 ExtendedResourceToleration 准入控制器 来应用的。如果你的 Kubernetes 集群没有启用这个准入控制器,你可能需要手动为每个 GPU Pod 配置添加一个 GPU 容忍。例如,
apiVersion: v1
kind: Pod
metadata:
generateName: example-cluster-ray-worker
spec:
...
tolerations:
- effect: NoSchedule
key: nvidia.com/gpu
operator: Exists
...
containers:
- name: ray-node
image: rayproject/ray:nightly-gpu
...
节点选择器和节点标签#
为了确保 Ray pod 绑定到满足特定条件的 Kubernetes 节点(例如存在 GPU 硬件),您可能希望使用 workerGroup
的 pod 模板 spec
中的 nodeSelector
字段。有关 Pod 到节点分配的更多信息,请参阅 Kubernetes 文档。
进一步的参考和讨论#
阅读关于 Kubernetes 设备插件 这里,关于 Kubernetes GPU 插件 这里,以及关于 Nvidia 的 Kubernetes GPU 插件 这里。