使用分布式工作负载


Red Hat OpenShift AI Cloud Service 1

使用分布式工作负载,实现更快、效率更高的数据处理和模型培训

摘要

分布式工作负载使数据科学家可以并行使用多个集群节点,以获得更快、效率更高的数据处理和模型培训。CodeFlare 框架简化了任务编配和监控,并提供与高级 GPU 支持的自动化资源扩展和最佳节点利用率的无缝集成。

前言

要更快地培训复杂机器学习模型或处理数据,您可以使用分布式工作负载功能并行在多个 OpenShift worker 节点上运行作业。这种方法可显著减少任务完成时间,并允许使用更大的数据集和更复杂的模型。

第 1 章 分布式工作负载概述

您可以使用分布式工作负载功能来排队、扩展和管理在 OpenShift 集群中多个节点运行数据科学工作负载所需的资源。通常,数据科学工作负载包括几种人工智能(AI)工作负载,包括机器学习(ML)和 Python 工作负载。

分布式工作负载提供以下优点:

  • 由于减少处理时间,您可以更快速、更频繁地进行实验。
  • 您可以使用较大的数据集,这可能会导致更准确的模型。
  • 您可以使用无法在单个节点上接受的复杂模型。
  • 您可以随时提交分布式工作负载,系统然后在所需资源可用时调度分布式工作负载。

1.1. 分布式工作负载基础架构

分布式工作负载基础架构包括以下组件:

CodeFlare Operator
保护部署的 Ray 集群,并授予对其 URL 的访问
CodeFlare SDK

为任何基于 Python 的环境定义和控制远程分布式计算作业和基础架构

注意

CodeFlare SDK 未作为 OpenShift AI 的一部分安装,但它包含在 OpenShift AI 提供的工作台镜像中。

Kubeflow Training Operator
为使用 PyTorch 等不同 ML 框架创建的 ML 模型提供微调和可扩展的分布式培训
Kubeflow Training Operator Python Software Development Kit (training Operator SDK)
简化分布式培训的创建和调优作业
注意

Training Operator SDK 不作为 OpenShift AI 的一部分安装,但它包含在 OpenShift AI 提供的工作台镜像中。

KubeRay
在 OpenShift 上管理远程 Ray 集群,以运行分布式计算工作负载
Red Hat build of Kueue Operator
管理配额以及分布式工作负载如何使用配额,以及管理分布式工作负载的队列与配额相关

有关安装这些组件的详情,请参考 安装分布式工作负载组件

1.2. 分布式工作负载的类型

根据您要运行的分布式工作负载类型,您必须使用不同的 OpenShift AI 组件:

  • 基于 Ray 的分布式工作负载:使用 codeflarekueray 组件。
  • 培训基于 Operator 的分布式工作负载:使用 trainingoperatorkueue 组件。

对于基于 Ray 的分布式工作负载,您可以使用基于 Ray 的分布式工作负载,您可以使用 Kue 和支持的加速器:

  • 使用 Kue 管理分布式工作负载的资源。
  • 将 CUDA 培训镜像用于 NVIDIA GPU,为 AMD GPU 使用基于 ROCm 的文档镜像。

有关支持的加速器的更多信息,请参阅 Red Hat OpenShift AI: 支持的配置 知识库文章

您可以从数据科学管道、Jupyter 笔记本或 Microsoft Visual Studio Code 文件运行分布式工作负载。

注意

数据科学管道工作负载不由分布式工作负载功能管理,不包含在分布式工作负载指标中。

第 2 章 准备分布式培训环境

在运行分布式培训或调优工作前,请按如下所示准备培训环境:

  • 使用适当的工作台镜像创建一个工作台。查看每个工作台镜像中的软件包列表,以查找最适合您分布式培训工作负载的镜像。
  • 确保您有向 OpenShift 集群进行身份验证的凭据。
  • 选择适当的培训图像。从 Red Hat OpenShift AI 提供的基本培训镜像列表中选择,或创建自定义培训镜像。

有关 Red Hat OpenShift AI 提供的工作台镜像和培训镜像的详情,请参考 Red Hat OpenShift AI: 支持的配置 知识库文章。

2.1. 为分布式培训创建工作台

使用适当的资源创建一个工作台来运行分布式培训或调优作业。

重要

硬件配置集功能目前在 Red Hat OpenShift AI 中作为技术预览功能提供。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

默认情况下,硬件配置集(包括启用了 Kueue-enabled 的配置集)在仪表板导航菜单和用户界面中隐藏,而加速器配置集仍可见。另外,与已弃用的加速器配置集功能关联的用户界面组件仍然会显示。要在仪表板导航菜单中显示 Settings → Hardware profiles 选项,以及与硬件配置集关联的用户界面组件,在 OpenShift 中的 OdhDashboardConfig 自定义资源(CR)中将 disableHardwareProfiles 和 disableKue 值设置为 false

有关设置仪表板配置选项的更多信息,请参阅 自定义仪表板

先决条件

  • 您可以使用支持的加速器访问具有足够 worker 节点的 OpenShift 集群,以运行您的培训或调优作业。
  • 集群管理员配置了集群,如下所示:
  • 安装并激活了 Kueue Operator 的红帽构建,如 使用 Kue 配置工作负载管理 中所述。

流程

  1. 登录到 Red Hat OpenShift AI web 控制台。
  2. 如果要将工作台添加到现有项目中,请打开项目并继续下一步。

    如果要将工作台添加到新项目中,请按如下所示创建项目:

    1. 在左侧导航窗格中,单击 Data Science projects,然后单击 Create project
    2. 输入项目名称,以及可选的描述,然后点 Create。项目详情页面将打开,默认选择 Overview 选项卡。
  3. 创建一个工作台,如下所示:

    1. 在项目详情页面上,单击 Workbench 选项卡,再单击 Create workbench
    2. 输入工作台名称,以及可选的描述。
    3. Workbench image 部分中,从 Image 选择 列表中选择适合您的培训或调优作业的镜像。如果存在项目范围内的镜像,Image 选择 列表包含子标题,以区分全局镜像和项目范围内的镜像。

      例如,要使用 Kubeflow 培训 运行 Fine-tuning model 中描述的示例微调作业,请选择 PyTorch

    4. Deployment size 部分中,从 Hardware profile 列表中为您的工作台选择一个合适的硬件配置集。

      如果存在项目范围内的硬件配置文件,则 Hardware profile 列表包含子标题,以区分全局硬件配置文件和项目范围内的硬件配置文件。

      硬件配置集指定分配给容器的 CPU 数量和内存量,为两者设置保证最小值(request)和最大值(limit)。

    5. 如果要更改默认值,点 Customize resource requests and limit,并输入新的最小值(request)和最大值(limit)值。
    6. Cluster storage 部分,点 Attach existing storageCreate storage 指定存储详情,以便您可以在工作台间共享数据以及培训或调优运行。

      例如,要使用 Kubeflow training 运行 Fine-tuning model 中描述的微调作业示例,请指定 ReadWriteMany (RWX)功能的存储类。

    7. 检查存储配置并点 Create workbench

验证

Workbenches 选项卡上,状态从 Starting 变为 Running

2.2. 使用集群服务器和令牌进行身份验证

要与 OpenShift 集群交互,您必须通过指定集群服务器和令牌来向 OpenShift API 进行身份验证。您可以从 OpenShift 控制台找到这些值。

先决条件

  • 您可以访问 OpenShift 控制台。

流程

  1. 登录 OpenShift 控制台。

    在 OpenShift AI 顶部导航栏中,点应用程序启动程序图标( The application launcher ),然后点 OpenShift Console

  2. 在 OpenShift 控制台右上角,单击您的用户名,然后单击 Copy login command
  3. 在打开的新标签页中,以您要使用的凭据的用户身份登录。
  4. 单击 Display Token
  5. Log in with this token 部分,找到所需的值,如下所示:

    • 令牌 值是 the- token= 前缀后的文本。
    • server 值是位于 the- server= 前缀后的文本。
    注意

    令牌和 服务器 值是安全凭证,请谨慎处理它们。

    • 不要将令牌和服务器详情保存到笔记本文件中。
    • 不要在 Git 中存储令牌和服务器详细信息。

    令牌会在 24 小时后过期。

  6. 您可以使用令牌和服务器详情以各种方式进行身份验证,如下例所示:

    • 您可以在笔记本单元中指定值:

      api_server = "<server>"
      token = "<token>"
      Copy to Clipboard Toggle word wrap
    • 您可以使用 此令牌命令复制整个 Log in 并粘贴终端窗口中的命令, 来登录 OpenShift 命令行界面(CLI)。

      $ oc login --token=<token> --server=<server>
      Copy to Clipboard Toggle word wrap

2.3. 管理自定义培训镜像

要运行分布式培训工作,您可以使用 OpenShift AI 提供的一个基本培训镜像,也可以创建自己的自定义培训镜像。您可以选择将自定义培训镜像推送到集成的 OpenShift 镜像 registry 中,以使您的镜像可供其他用户使用。

2.3.1. 关于基本培训镜像

用于分布式工作负载的基本培训镜像通过运行分布式培训工作所需的工具和库优化。您可以使用提供的基础镜像,也可以创建特定于您的需要的自定义镜像。

有关红帽支持培训镜像和软件包的详情,请参考 Red Hat OpenShift AI: 支持的配置

下表列出了默认情况下随 Red Hat OpenShift AI 安装的培训镜像。这些镜像是 AMD64 镜像,可能不适用于其他架构。

Expand
表 2.1. 默认培训基础镜像
镜像类型描述

Ray CUDA

如果您使用计算密集型模型,而您想要使用 NVIDIA GPU 支持加速培训作业,您可以使用 Ray Compute Unified Device Architecture (CUDA)基础镜像来获得对 NVIDIA CUDA 工具包的访问。使用这个工具包,您可以使用为 NVIDIA GPU 优化的库和工具来加快您的工作。

Ray ROCm

如果您使用计算密集型模型,而您想要使用 AMD GPU 支持加速培训作业,您可以使用 Ray ROCm 基础镜像来获得对 AMD ROCm 软件堆栈的访问。使用这个软件堆栈,您可以使用为 AMD GPU 优化的库和工具来加快您的工作。

KFTO CUDA

如果您使用计算密集型模型,而您想要使用 NVIDIA GPU 支持加快培训作业,您可以使用 Kubeflow training Operator CUDA 基础镜像来访问 NVIDIA CUDA 工具包。使用这个工具包,您可以使用为 NVIDIA GPU 优化的库和工具来加快您的工作。

KFTO ROCm

如果您使用计算密集型模型,而您想要使用 AMD GPU 支持加快培训作业,您可以使用 Kubeflow training Operator ROCm 基础镜像来获得对 AMD ROCm 软件堆栈的访问。使用这个软件堆栈,您可以使用为 AMD GPU 优化的库和工具来加快您的工作。

如果这些镜像中提供的预安装软件包不足以满足您的用例,则您可以选择:

  • 在启动默认镜像后安装其他库。如果您要在运行培训工作时在临时命令中添加库,则此选项很好。但是,管理已安装库的依赖项可能具有挑战性。
  • 创建包含额外库或软件包的自定义镜像。如需更多信息,请参阅 创建自定义培训镜像

2.3.2. 创建自定义培训镜像

您可以通过向基础培训镜像添加软件包来创建自定义培训镜像。

先决条件

  • 您可以访问已选择用作自定义镜像基础的培训镜像。

    根据 镜像类型(如 Ray 或 Kubeflow training Operator)、加速器框架 (如用于 NVIDIA GPU 的 CUDA)或 AMD GPU 的 ROCm 选择镜像,以及 Python 版本 (如 3.9 或 3.11)。

    下表显示了一些基本培训镜像示例:

    Expand
    表 2.2. 基本培训镜像示例
    镜像类型加速器框架Python 版本基本培训镜像示例预安装的软件包

    ray

    CUDA

    3.9

    ray:2.35.0-py39-cu121

    Ray 2.35.0, Python 3.9, CUDA 12.1

    ray

    CUDA

    3.11

    ray:2.47.1-py311-cu121

    Ray 2.47.1, Python 3.11, CUDA 12.1

    ray

    ROCm

    3.9

    ray:2.35.0-py39-rocm62

    Ray 2.35.0, Python 3.9, ROCm 6.2

    ray

    ROCm

    3.11

    ray:2.47.1-py311-rocm62

    Ray 2.47.1, Python 3.11, ROCm 6.2

    KFTO

    CUDA

    3.11

    training:py311-cuda124-torch251

    Python 3.11, CUDA 12.4, PyTorch 2.5.1

    KFTO

    ROCm

    3.11

    training:py311-rocm62-torch251

    Python 3.11, ROCm 6.2, PyTorch 2.5.1

    如需 OpenShift AI 基础镜像及其预安装软件包的完整列表,请参阅 支持的配置

  • 您已在本地环境中安装了 Podman,您可以访问容器 registry。

    有关 Podman 和容器注册表的更多信息,请参阅 构建、运行和管理容器

流程

  1. 在终端窗口中,为您的工作创建一个目录,并更改到该目录。
  2. IMG 环境变量设置为自定义镜像的名称。在本节中的示例命令中,my_training_image 是自定义镜像的名称。

    export IMG=my_training_image
    Copy to Clipboard Toggle word wrap
  3. 使用以下内容创建名为 Dockerfile 的文件:

    1. 使用 FROM 指令指定合适的基本培训镜像的位置。

      在以下命令中,将 _<base- training-image>_ 替换为您选择的基本培训镜像的名称:

      FROM quay.io/modh/<base-training-image>
      Copy to Clipboard Toggle word wrap

      示例:

      FROM quay.io/modh/ray:2.47.1-py311-cu121
      Copy to Clipboard Toggle word wrap
      FROM quay.io/modh/training:py311-rocm62-torch251
      Copy to Clipboard Toggle word wrap
    2. 使用 RUN 指令安装其他软件包。您还可以通过使用数字符号(#)为每个注释行添加注释到 Dockerfile。

      以下示例演示了如何安装 Python PyTorch 软件包的特定版本:

      # Install PyTorch
      RUN python3 -m pip install torch==2.5.1
      Copy to Clipboard Toggle word wrap
  4. 构建 镜像文件。将 -t 选项与 podman build 命令一起使用,以创建指定自定义镜像名称和版本的镜像标签,以便更轻松地引用和管理镜像:

    podman build -t <custom-image-name>:_<version>_ -f Dockerfile
    Copy to Clipboard Toggle word wrap

    Example:

    podman build -t ${IMG}:0.0.1 -f Dockerfile
    Copy to Clipboard Toggle word wrap

    构建输出表示构建过程完成。

  5. 显示镜像列表:

    podman images
    Copy to Clipboard Toggle word wrap

    如果成功创建了新镜像,则会将其包含在镜像列表中。

  6. 将镜像推送到容器 registry 中:

    podman push ${IMG}:0.0.1
    Copy to Clipboard Toggle word wrap
  7. 可选:使新镜像可供其他用户使用,如 将镜像推送到集成的 OpenShift 镜像 registry 中所述。

要使镜像可供 OpenShift 集群中的其他用户使用,您可以将镜像推送到 集成的 OpenShift 镜像 registry 中,即内置的容器镜像 registry。

如需有关集成的 OpenShift 镜像 registry 的更多信息,请参阅 集成 OpenShift 镜像 registry

先决条件

流程

  1. 在一个终端窗口中,登录到 OpenShift CLI,如下例所示:

    $ oc login <openshift_cluster_url> -u <admin_username> -p <password>
    Copy to Clipboard Toggle word wrap
  2. IMG 环境变量设置为镜像的名称。在本节中的示例命令中,my_training_image 是镜像的名称。

    export IMG=my_training_image
    Copy to Clipboard Toggle word wrap
  3. 登录到集成的镜像 registry:

    podman login -u $(oc whoami) -p $(oc whoami -t) $(oc registry info)
    Copy to Clipboard Toggle word wrap
  4. 为集成镜像 registry 标记镜像:

    podman tag ${IMG} $(oc registry info)/$(oc project -q)/${IMG}
    Copy to Clipboard Toggle word wrap
  5. 将镜像推送到集成的镜像 registry:

    podman push $(oc registry info)/$(oc project -q)/${IMG}
    Copy to Clipboard Toggle word wrap
  6. 检索您想要的标签的镜像存储库位置:

    oc get is ${IMG} -o jsonpath='{.status.tags[?(@.tag=="<TAG>")].items[0].dockerImageReference}'
    Copy to Clipboard Toggle word wrap

    现在,任何用户都可以在 Ray 集群或培训工作的 image 参数中指定这个检索到的镜像位置值来使用您的镜像。

第 3 章 运行基于 Ray 的分布式工作负载

在 OpenShift AI 中,您可以从 Jupyter 笔记本或从管道运行基于 Ray 的分布式工作负载。

如果可以从该环境中访问所有需要的软件,则可以在断开连接的环境中运行基于 Ray 的分布式工作负载。例如,您必须从断开连接的环境中访问 Ray 集群镜像,以及工作负载使用的数据集和 Python 依赖项。

要从 Jupyter 笔记本运行分布式工作负载,您必须配置 Ray 集群。您还必须提供环境特定信息,如集群身份验证详情。

本节中的示例请参阅 JupyterLab 集成开发环境(IDE)。

3.1.1. 从 CodeFlare SDK 下载演示 Jupyter 笔记本

CodeFlare SDK 中的演示 Jupyter 笔记本提供了如何在您自己的 Jupyter 笔记本中使用 CodeFlare 堆栈的指南。下载演示 Jupyter 笔记本,以便您了解如何在本地运行 Jupyter 笔记本。

先决条件

  • 您可以访问配置为运行分布式工作负载的数据科学项目,如 管理分布式工作负载 中所述。
  • 您可以访问包含工作台的数据科学项目,工作台正在运行包含 CodeFlare SDK 的默认工作台镜像,如 Standard Data Science 笔记本。有关项目和工作台 的详情,请参考使用数据科学项目
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您已登陆到 Red Hat OpenShift AI,启动工作台,并登录到 JupyterLab。

流程

  1. 在 JupyterLab 界面中,点 File > New > Notebook。指定您首选的 Python 版本,然后点 Select

    使用 .ipynb 文件扩展名创建一个新的 Jupyter 笔记本文件。

  2. 在新笔记本的单元格中添加以下代码:

    下载演示 Jupyter 笔记本的代码

    from codeflare_sdk import copy_demo_nbs
    copy_demo_nbs()
    Copy to Clipboard Toggle word wrap

  3. 选择单元,然后点 Run > Run selected cell

    几秒钟后,copy_demo_nbs () 函数复制与 CodeFlare SDK 当前安装版本的 demo Jupyter 笔记本,并将其克隆到 demo-notebooks 文件夹中。

  4. 在左侧导航窗格中,右键单击新笔记本,再单击删除
  5. 单击 Delete 确认。

验证

在 JupyterLab 接口中找到下载的演示 Jupyter 笔记本,如下所示:

  1. 在左侧导航窗格中,双击 demo-notebooks
  2. 双击 additional-demos,并验证 文件夹是否包含几个演示 Jupyter 笔记本。
  3. 单击 demo-notebooks
  4. 双击 guided-demos,并验证 文件夹是否包含几个演示 Jupyter 笔记本。

您可以运行这些演示 Jupyter 笔记本,如从 CodeFlare SDK 中运行演示 Jupyter 笔记本 中所述。

3.1.2. 从 CodeFlare SDK 中运行演示 Jupyter 笔记本

要从 CodeFlare SDK 中运行演示 Jupyter 笔记本,您必须提供环境特定信息。

在此流程示例中,您可以编辑 JupyterLab 中的演示 Jupyter 笔记本以提供所需信息,然后运行 Jupyter 笔记本。

先决条件

  • 您可以访问配置为运行分布式工作负载的数据科学项目,如 管理分布式工作负载 中所述。
  • 您可以从数据科学集群访问以下软件:

    • 与硬件架构兼容的 Ray 集群镜像
    • 工作负载使用的数据集和模型
    • 工作负载的 Python 依赖项,可以在 Ray 镜像或您自己的 Python Package Index (PyPI)服务器中
  • 您可以访问包含工作台的数据科学项目,工作台正在运行包含 CodeFlare SDK 的默认工作台镜像,如 Standard Data Science workbench。有关项目和工作台 的详情,请参考使用数据科学项目
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您已登陆到 Red Hat OpenShift AI,启动工作台,并登录到 JupyterLab。
  • 您已下载了 CodeFlare SDK 提供的演示 Jupyter 笔记本,如从 CodeFlare SDK 下载演示 Jupyter 笔记本 中所述。

流程

  1. 检查您的集群管理员是否为 Ray 集群定义了 默认 本地队列。

    您可以使用 codeflare_sdk.list_local_queues () 函数查看当前命名空间中的所有本地队列,以及与每个本地队列关联的资源类型。

    或者,您可以使用 OpenShift Web 控制台,如下所示:

    1. 在 OpenShift Web 控制台中,从 Project 列表中选择您的项目。
    2. 单击 Search,然后从 Resources 列表中选择 LocalQueue 以显示项目的本地队列列表。

      如果没有列出本地队列,请联络您的集群管理员。

    3. 查看每个本地队列的详情:

      1. 单击本地队列名称。
      2. YAML 选项卡,并查看 metadata.annotations 部分。

        如果 kueue.x-k8s.io/default-queue 注解被设置为 'true',则队列将配置为默认的本地队列。

        注意

        如果集群管理员没有定义默认的本地队列,则必须在每个 Jupyter 笔记本中指定本地队列。

  2. 在 JupyterLab 界面中,打开 demo-notebooks > guided-demos 文件夹。
  3. 通过双击每个 Jupyter 笔记本文件来打开所有 Jupyter 笔记本。

    Jupyter 笔记本文件具有 .ipynb 文件名扩展名。

  4. 在每个 Jupyter 笔记本中,确保 导入 部分从 CodeFlare SDK 中导入所需的组件,如下所示:

    import 部分示例

    from codeflare_sdk import Cluster, ClusterConfiguration, TokenAuthentication
    Copy to Clipboard Toggle word wrap

  5. 在每个 Jupyter 笔记本中,更新 TokenAuthentication 部分,以提供 令牌和 服务器 详情,以使用 CodeFlare SDK 向 OpenShift 集群进行身份验证。

    有关如何查找服务器和令牌详情的详情,请参考使用集群服务器和令牌进行身份验证

  6. 可选:如果要使用自定义证书,请更新 TokenAuthentication 部分,以添加 ca_cert_path 参数以指定自定义证书的位置,如下例所示:

    身份验证部分示例

    auth = TokenAuthentication(
        token = "XXXXX",
        server = "XXXXX",
        skip_tls=False,
        ca_cert_path="/path/to/cert"
    )
    auth.login()
    Copy to Clipboard Toggle word wrap

    或者,您可以设置 CF_SDK_CA_CERT_PATH 环境变量来指定自定义证书的位置。

  7. 在每个 Jupyter 笔记本中,按如下所示更新集群配置部分:

    1. 如果指定了 namespace 值,将 example 值替换为项目的名称。

      如果省略这一行,则会在当前项目中创建 Ray 集群。

    2. 如果指定了 image 值,将 example 值替换为到合适的 Ray 集群镜像的链接。Ray 集群镜像中的 Python 版本必须与工作台中的 Python 版本相同。

      如果省略这一行,则默认使用以下 Ray 集群镜像之一,具体取决于工作台中检测到的 Python 版本:

      • Python 3.9: quay.io/modh/ray:2.35.0-py39-cu121
      • python 3.11: quay.io/modh/ray:2.47.1-py311-cu121

      默认 Ray 镜像与指定 CUDA 版本支持的 NVIDIA GPU 兼容。默认镜像是 AMD64 镜像,可能不适用于其他架构。

      提供了其他兼容 ROCm 的集群镜像,它们与指定的 ROCm 版本支持的 AMD 加速器兼容。这些镜像是 AMD64 镜像,可能不适用于其他架构。

      有关最新可用培训镜像及其预装软件包的详情,包括 CUDA 和 ROCm 版本,请参阅 Red Hat OpenShift AI: 支持的配置

    3. 如果集群管理员没有配置默认本地队列,请为 Ray 集群指定本地队列,如下例所示:

      本地队列分配示例

      local_queue="your_local_queue_name"
      Copy to Clipboard Toggle word wrap

    4. 可选: 将标签 参数的字典分配给 Ray 集群以进行识别和管理目的,如下例所示:

      标签分配示例

      labels = {"exampleLabel1": "exampleLabel1Value", "exampleLabel2": "exampleLabel2Value"}
      Copy to Clipboard Toggle word wrap

  8. 2_basic_interactive.ipynb Jupyter 笔记本中,确保 Ray 集群创建部分中包含以下 Ray 集群身份验证代码:

    Ray 集群身份验证代码

    from codeflare_sdk import generate_cert
    generate_cert.generate_tls_cert(cluster.config.name, cluster.config.namespace)
    generate_cert.export_env(cluster.config.name, cluster.config.namespace)
    Copy to Clipboard Toggle word wrap

    注意

    在 OpenShift AI 的 CodeFlare 组件中默认启用 mutual Transport Layer Security (mTLS)。您必须包含 Ray 集群身份验证代码,以便启用在 Jupyter 笔记本中运行的 Ray 客户端,以连接到启用了 mTLS 的安全 Ray 集群。

  9. 按照 file-name 前缀(0_1_ 等)运行 Jupyter 笔记本。

    1. 在每个 Jupyter 笔记本中,依次运行每个单元,并查看单元输出。
    2. 如果显示错误,请查看输出以查找有关问题的信息和所需的纠正操作。例如,按照指示替换任何已弃用的参数。另请参阅 用户对分布式工作负载的常见问题进行故障排除
    3. 有关在 Jupyter 笔记本中工作时,您可以使用交互式浏览器控制简化 Ray 集群任务的更多信息,请参阅 在 Jupyter 笔记本中 管理 Ray 集群

验证

  1. Jupyter 笔记本运行以在没有错误的情况下完成。
  2. 在 Jupyter 笔记本中,cluster.status () 函数或 cluster.details () 函数的输出表示 Ray 集群是 Active

3.1.3. 从 Jupyter 笔记本中管理 Ray 集群

在 Jupyter 笔记本中操作时,您可以使用交互式浏览器控制来简化 Ray 集群任务。

交互式浏览器控制提供了对等命令的替代选择,但不替换它们。您可以通过在 Jupyter 笔记本中运行命令来继续管理 Ray 集群,以便在脚本和管道中轻松使用。

有几个不同的交互式浏览器控制可用:

  • 当您运行提供集群配置的单元时,Jupyter 笔记本会自动显示启动或删除集群的控制。
  • 您可以运行 view_clusters () 命令来添加提供以下功能的控制:

    • 查看您可以访问的 Ray 集群列表。
    • 查看所选 Ray 集群的集群状态和分配资源等集群信息。您可以在 Jupyter 笔记本中查看此信息,而无需切换到 OpenShift 控制台或 Ray 仪表板。
    • 直接从 Jupyter 笔记本打开 Ray 仪表板,以查看提交的作业。
    • 刷新所选集群的 Ray 集群列表和集群信息。

    您可以将这些控件添加到现有 Jupyter 笔记本中,或者从单独的 Jupyter 笔记本管理 Ray 集群。

3_widget_example.ipynb 演示 Jupyter 笔记本显示所有可用的互动浏览器控制。在此流程示例中,您可以创建一个新的 Jupyter 笔记本来管理 Ray 集群,类似于 3_widget_example.ipynb 演示 Jupyter 笔记本中提供的示例。

先决条件

  • 您可以访问配置为运行分布式工作负载的数据科学项目,如 管理分布式工作负载 中所述。
  • 您可以从数据科学集群访问以下软件:

    • 与硬件架构兼容的 Ray 集群镜像
    • 工作负载使用的数据集和模型
    • 工作负载的 Python 依赖项,可以在 Ray 镜像或您自己的 Python Package Index (PyPI)服务器中
  • 您可以访问包含工作台的数据科学项目,工作台正在运行包含 CodeFlare SDK 的默认工作台镜像,如 Standard Data Science workbench。有关项目和工作台 的详情,请参考使用数据科学项目
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您已登陆到 Red Hat OpenShift AI,启动工作台,并登录到 JupyterLab。
  • 您已下载了 CodeFlare SDK 提供的演示 Jupyter 笔记本,如从 CodeFlare SDK 下载演示 Jupyter 笔记本 中所述。

流程

  1. 按照从 CodeFlare SDK 中运行演示 Jupyter 笔记本中所述,按照文件名前缀(0_1_ 等)运行所有演示 Jupyter 笔记本
  2. 在每个演示 Jupyter 笔记本中,在运行集群配置步骤时,Jupyter 笔记本中会自动显示以下互动控制:

    • Cluster Up: 您可以点此按钮启动 Ray 集群。此按钮等同于 cluster.up () 命令。当您点此按钮时,信息会显示集群是否已成功创建。
    • Cluster Down :您可以点此按钮删除 Ray 集群。此按钮等同于 cluster.down () 命令。集群将立即删除,系统不会提示您确认删除。当您点此按钮时,信息会显示集群是否已成功删除。
    • 等待 集群 :您可以选择这个选项来指定笔记本单元应等待 Ray 集群仪表板就绪,然后继续下一步。这个选项等同于 cluster.wait_ready () 命令。
  3. 在 JupyterLab 界面中,创建一个新的 Jupyter 笔记本来管理 Ray 集群,如下所示:

    1. File > New > Notebook。指定您首选的 Python 版本,然后点 Select

      使用 .ipynb 文件扩展名创建一个新的 Jupyter 笔记本文件。

    2. 在新的 Jupyter 笔记本中添加以下代码:

      导入所需软件包的代码

      from codeflare_sdk import TokenAuthentication, view_clusters
      Copy to Clipboard Toggle word wrap

      view_clusters 软件包提供了用于列出集群的交互式浏览器控制,显示集群详情、打开 Ray 仪表板并刷新集群数据。

    3. 添加新的笔记本单元,并在新单元中添加以下代码:

      要进行身份验证的代码

      auth = TokenAuthentication(
          token = "XXXXX",
          server = "XXXXX",
          skip_tls=False
      )
      auth.login()
      Copy to Clipboard Toggle word wrap

      有关如何查找令牌和服务器值的详情,请参考从 CodeFlare SDK 中运行演示 Jupyter 笔记本

    4. 添加新的笔记本单元,并在新单元中添加以下代码:

      查看当前项目中的集群的代码

      view_clusters()
      Copy to Clipboard Toggle word wrap

      当您运行没有指定参数的 view_clusters () 命令时,您可以生成 当前 项目中的所有 Ray 集群的列表,并显示与 cluster.details () 函数类似的信息。

      如果可以访问另一个项目,您可以通过指定项目名称来列出该项目中的 Ray 集群,如下例所示:

      查看另一个项目中的集群的代码

      view_clusters("my_second_project")
      Copy to Clipboard Toggle word wrap

    5. File > Save Notebook As,输入 demo-notebooks/guided-demos/manage_ray_clusters.ipynb,然后点击 Save
  4. demo-notebooks/guided-demos/manage_ray_clusters.ipynb Jupyter notebook 中,选择每个单元格,然后点击 Run > Run selected cell
  5. 当您使用 view_clusters () 函数运行单元时,输出取决于是否存在 Ray 集群。

    如果没有 Ray 集群,则会显示以下文本,其中 _[project-name]_ 是目标项目的名称:

    No clusters found in the [project-name] namespace.
    Copy to Clipboard Toggle word wrap

    否则,Jupyter 笔记本显示有关现有 Ray 集群的以下信息:

    • 选择现有集群

      在此标题下,每个现有集群会显示一个切换按钮。点集群名称来选择集群。集群详情部分已更新,显示有关所选集群的详情,如集群名称、OpenShift AI 项目名称、集群资源信息和集群状态。

    • 删除集群

      点击此按钮删除所选集群。这个按钮等同于 Cluster Down 按钮。集群将立即删除,系统不会提示您确认删除。消息显示集群是否已成功删除,对应的按钮将不再显示在 Select an existing cluster 标题下。

    • 查看作业

      点击此按钮,打开所选集群的 Ray 仪表板中的 Jobs 选项卡,并查看提交的作业详情。对应的 URL 显示在 Jupyter 笔记本中。

    • 打开 Ray Dashboard

      点击此按钮打开所选集群的 Ray 仪表板中的 Overview 选项卡。对应的 URL 显示在 Jupyter 笔记本中。

    • 刷新数据

      点这个按钮刷新 Ray 集群列表以及所选集群的集群详情。当您选择集群以及删除所选集群时,集群详情会自动刷新。

验证

  1. 演示 Jupyter 笔记本运行以在没有错误的情况下完成。
  2. manage_ray_clusters.ipynb Jupyter 笔记本中,view_clusters () 函数的输出是正确的。

要从管道运行分布式工作负载,您必须首先更新管道,使其包含指向您的 Ray 集群镜像的链接。

先决条件

  • 您可以访问配置为运行分布式工作负载的数据科学项目,如 管理分布式工作负载 中所述。
  • 您可以从数据科学集群访问以下软件:

    • 与硬件架构兼容的 Ray 集群镜像
    • 工作负载使用的数据集和模型
    • 工作负载的 Python 依赖项,可以在 Ray 镜像或您自己的 Python Package Index (PyPI)服务器中
  • 您可以访问包含工作台的数据科学项目,工作台正在运行包含 CodeFlare SDK 的默认工作台镜像,如 Standard Data Science workbench。有关项目和工作台 的详情,请参考使用数据科学项目
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您可以访问 S3 兼容对象存储。
  • 您已登陆到 Red Hat OpenShift AI。

流程

  1. 创建连接以将对象存储连接到您的数据科学项目,如添加与 数据科学项目的连接 中所述。
  2. 将管道服务器配置为使用连接,如 配置管道服务器 中所述。
  3. 创建数据科学管道,如下所示:

    1. 安装所有管道所需的 kfp Python 软件包:

      $ pip install kfp
      Copy to Clipboard Toggle word wrap
    2. 安装管道所需的任何其他依赖项。
    3. 在 Python 代码中构建您的数据科学管道。

      例如,使用以下内容创建名为 compile_example.py 的文件:

      from kfp import dsl
      
      
      @dsl.component(
          base_image="registry.redhat.io/ubi9/python-311:latest",
          packages_to_install=['codeflare-sdk']
      )
      
      
      def ray_fn():
         import ray 
      1
      
         from codeflare_sdk import Cluster, ClusterConfiguration, generate_cert 
      2
      
      
         cluster = Cluster( 
      3
      
             ClusterConfiguration(
                 namespace="my_project", 
      4
      
                 name="raytest",
                 num_workers=1,
                 head_cpu_requests="500m",
                 head_cpu_limits="500m",
                 worker_memory_requests=1,
                 worker_memory_limits=1,
                 worker_extended_resource_requests={"nvidia.com/gpu": 1}, 
      5
      
                 image="quay.io/modh/ray:2.47.1-py311-cu121", 
      6
      
                 local_queue="local_queue_name", 
      7
      
             )
         )
      
      
         print(cluster.status())
         cluster.up() 
      8
      
         cluster.wait_ready() 
      9
      
         print(cluster.status())
         print(cluster.details())
      
      
         ray_dashboard_uri = cluster.cluster_dashboard_uri()
         ray_cluster_uri = cluster.cluster_uri()
         print(ray_dashboard_uri, ray_cluster_uri)
      
         # Enable Ray client to connect to secure Ray cluster that has mTLS enabled
         generate_cert.generate_tls_cert(cluster.config.name, cluster.config.namespace) 
      10
      
         generate_cert.export_env(cluster.config.name, cluster.config.namespace)
      
      
         ray.init(address=ray_cluster_uri)
         print("Ray cluster is up and running: ", ray.is_initialized())
      
      
         @ray.remote
         def train_fn(): 
      11
      
             # complex training function
             return 100
      
      
         result = ray.get(train_fn.remote())
         assert 100 == result
         ray.shutdown()
         cluster.down() 
      12
      
         auth.logout()
         return result
      
      
      @dsl.pipeline( 
      13
      
         name="Ray Simple Example",
         description="Ray Simple Example",
      )
      
      
      def ray_integration():
         ray_fn()
      
      
      if __name__ == '__main__': 
      14
      
          from kfp.compiler import Compiler
          Compiler().compile(ray_integration, 'compiled-example.yaml')
      Copy to Clipboard Toggle word wrap
      1
      导入 Ray。
      2
      从 CodeFlare SDK 中导入软件包以定义集群功能。
      3
      指定 Ray 集群配置:将这些示例值替换为 Ray 集群的值。
      4
      可选:指定创建 Ray 集群的项目。将示例值替换为项目的名称。如果省略这一行,则会在当前项目中创建 Ray 集群。
      5
      可选:为 Ray 集群指定请求的加速器(本例中为 1 NVIDIA GPU)。如果不使用 NVIDIA GPU,请将 nvidia.com/gpu 替换为加速器的正确值;例如,为 AMD GPU 指定 amd.com/gpu。如果不需要加速器,请将值设为 0 或省略该行。
      6
      指定 Ray 集群镜像的位置。Ray 集群镜像中的 Python 版本必须与工作台中的 Python 版本相同。如果省略此行,则使用默认 CUDA 兼容 Ray 集群镜像之一,具体取决于工作台中检测到的 Python 版本。默认的 Ray 镜像是 AMD64 镜像,可能不适用于其他架构。如果您在断开连接的环境中运行这个代码,请将默认值替换为您的环境的位置。有关最新可用培训镜像及其预安装的软件包的详情,请参考 Red Hat OpenShift AI: 支持的配置
      7
      指定将向其提交 Ray 集群的本地队列。如果配置了默认的本地队列,您可以省略这一行。
      8
      使用指定的镜像和配置创建 Ray 集群。
      9
      在继续操作前,等待 Ray 集群就绪。
      10
      启用 Ray 客户端连接到启用了 mutual Transport Layer Security (mTLS)的安全 Ray 集群。OpenShift AI 中的 CodeFlare 组件中默认启用 mTLS。
      11
      将本节中的示例详情替换为您的工作负载详情。
      12
      当工作负载完成后,删除 Ray 集群。
      13
      将示例名称和描述替换为您的工作负载值。
      14
      编译 Python 代码,并将输出保存到 YAML 文件中。
    4. 编译 Python 文件(本例中为 compile_example.py 文件):

      $ python compile_example.py
      Copy to Clipboard Toggle word wrap

      此命令创建一个 YAML 文件(本例中为 compiled-example.yaml),您可以在下一步中导入该文件。

  4. 导入您的数据科学管道,如 导入数据科学管道 中所述。
  5. 调度管道运行,如 调度管道运行 中所述。
  6. 当管道运行完成后,确认它包含在触发的管道运行列表中,如 查看管道运行的详情 中所述。

验证

YAML 文件已创建,管道运行会完成且没有错误。

您可以查看运行详情,如 查看管道运行的详情 中所述。

要减少培训大型语言模型(LLM)所需的时间,您可以并行运行培训工作。在 Red Hat OpenShift AI 中,Kubeflow Training Operator 和 Kubeflow Training Operator Python Software Development Kit (training Operator SDK)简化了作业配置。

您可以使用 Training Operator 和 Training Operator SDK 以各种方式配置培训作业。例如,您可以每个节点使用多个 GPU,微调模型,或者将培训作业配置为使用远程直接内存访问(RDMA)。

您可以使用 Training Operator PyTorchJob API 配置 PyTorchJob 资源,以便培训作业在多个带有多个 GPU 的节点上运行。

您可以将 training 脚本存储在 ConfigMap 资源中,或者将其包含在自定义容器镜像中。

您可以创建一个 ConfigMap 资源来存储 Training Operator PyTorch training 脚本。

注意

或者,您可以使用 示例 Dockerfile 将培训脚本包含在自定义容器镜像中,如 创建自定义培训镜像 中所述。

先决条件

  • 您的集群管理员已安装了带有所需分布式培训组件的 Red Hat OpenShift AI,如 安装分布式工作负载组件 中所述。
  • 您可以访问安装 OpenShift AI 的集群的 OpenShift 控制台。

流程

  1. 登录 OpenShift 控制台。
  2. 创建 ConfigMap 资源,如下所示:

    1. Administrator 视角中,点 WorkloadsConfigMaps
    2. Project 列表中,选择您的项目。
    3. Create ConfigMap
    4. Configure via 部分中,选择 YAML view 选项。

      Create ConfigMap 页面将打开,默认的 YAML 代码会自动添加。

  3. 将默认 YAML 代码替换为您的 training-script 代码。

    有关培训脚本示例,请参阅 培训 Operator PyTorch 培训脚本示例

  4. Create

验证

  1. 在 OpenShift 控制台中,在 Administrator 视角中点 WorkloadsConfigMaps
  2. Project 列表中,选择您的项目。
  3. 点 ConfigMap 资源显示培训脚本详情。

4.1.2. 创建 Training Operator PyTorchJob 资源

您可以创建一个 PyTorchJob 资源来运行 Training Operator PyTorch training 脚本。

先决条件

  • 您可以使用支持的 NVIDIA GPU 或 AMD GPU 访问具有多个 worker 节点的 OpenShift 集群。
  • 集群管理员配置了集群,如下所示:

  • 您可以访问适合分布式培训的工作台,如 为分布式培训 创建工作台 中所述。
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。

流程

  1. 登录 OpenShift 控制台。
  2. 创建 PyTorchJob 资源,如下所示:

    1. Administrator 视角中,点击 Home → Search
    2. Project 列表中,选择您的项目。
    3. 单击 Resources 列表,然后在搜索字段中开始输入 PyTorchJob
    4. 选择 PyTorchJob,然后单击 Create PyTorchJob

      Create PyTorchJob 页面将打开,自动添加默认 YAML 代码。

  3. 更新元数据,将 namenamespace 值替换为您的环境的值,如下例所示:

    metadata:
      name: pytorch-multi-node-job
      namespace: test-namespace
    Copy to Clipboard Toggle word wrap
  4. 配置 master 节点,如下例所示:

    spec:
      pytorchReplicaSpecs:
        Master:
          replicas: 1
          restartPolicy: OnFailure
          template:
            metadata:
              labels:
                app: pytorch-multi-node-job
    Copy to Clipboard Toggle word wrap
    1. replicas 条目中,指定 1。只需要一个 master 节点。
    2. 要使用 ConfigMap 资源为 PyTorchJob pod 提供培训脚本,请添加 ConfigMap 卷挂载信息,如下例所示:

      从 ConfigMap 资源添加培训脚本

      Spec:
        pytorchReplicaSpecs:
          Master:
            ...
            template:
              spec:
                containers:
                - name: pytorch
                  image: quay.io/modh/training:py311-cuda124-torch251
                  command: ["python", "/workspace/scripts/train.py"]
                  volumeMounts:
                  - name: training-script-volume
                    mountPath: /workspace
                volumes:
                - name: training-script-volume
                  configMap:
                    name: training-script-configmap
      Copy to Clipboard Toggle word wrap

    3. 为您的环境添加适当的资源限制,如下例所示:

      添加资源 contraints

      SSpec:
        pytorchReplicaSpecs:
          Master:
            ...
            template:
              spec:
                containers: ...
                resources:
                  requests:
                        cpu: "4"
                        memory: "8Gi"
                        nvidia.com/gpu: 2    # To use GPUs (Optional)
                  limits:
                        cpu: "4"
                        memory: "8Gi"
                        nvidia.com/gpu: 2
      Copy to Clipboard Toggle word wrap

  5. PyTorchJob 资源的 Worker 部分中进行类似的编辑。

    1. 更新 replicas 条目,以指定 worker 节点的数量。

    有关 PyTorchJob 资源的完整示例,请参阅 multi-node 培训的 Training Operator PyTorchJob 资源示例

  6. Create

验证

  1. 在 OpenShift 控制台中,打开 Administrator 视角。
  2. Project 列表中,选择您的项目。
  3. Home → Search → PyTorchJob,并验证作业是否已创建。
  4. Workloads → Pods,验证请求的 head pod 和 worker pod 是否正在运行。

您可以使用 OpenShift 命令行界面(CLI)创建 PyTorchJob 资源,以运行 Training Operator PyTorch training 脚本。

先决条件

流程

  1. 登录到 OpenShift CLI,如下所示:

    登录到 OpenShift CLI

    oc login --token=<token> --server=<server>
    Copy to Clipboard Toggle word wrap

    有关如何查找服务器和令牌详情的详情,请参考使用集群服务器和令牌进行身份验证

  2. 创建名为 training .py 的文件,并使用您的培训脚本填充该文件,如下所示:

    创建培训脚本

    cat <<EOF > train.py
    <paste your content here>
    EOF
    Copy to Clipboard Toggle word wrap

    <paste your content here& gt; 替换为您的培训脚本内容。

    有关培训脚本示例,请参阅 培训 Operator PyTorch 培训脚本示例

  3. 创建 ConfigMap 资源来存储培训脚本,如下所示:

    创建 ConfigMap 资源

    oc create configmap training-script-configmap --from-file=train.py -n <your-namespace>
    Copy to Clipboard Toggle word wrap

    <your-namespace > 替换为项目的名称。

  4. 创建名为 pytorchjob.yaml 的文件来定义分布式培训作业设置,如下所示:

    定义分布式培训工作

    cat <<EOF > pytorchjob.py
    <paste your content here>
    EOF
    Copy to Clipboard Toggle word wrap

    <paste your content here > 替换为您的培训工作内容。

    有关示例培训作业,请参阅多节点培训培训 Operator PyTorchJob 资源示例

  5. 创建分布式培训工作,如下所示:

    创建分布式培训工作

    oc apply -f pytorchjob.yaml
    Copy to Clipboard Toggle word wrap

验证

  1. 监控正在运行的分布式培训作业,如下所示:

    监控分布式培训工作

    oc get pytorchjobs -n <your-namespace>
    Copy to Clipboard Toggle word wrap

    <your-namespace > 替换为项目的名称。

  2. 检查 pod 日志,如下所示:

    检查 pod 日志

    oc logs <pod-name> -n <your-namespace>
    Copy to Clipboard Toggle word wrap

    <your-namespace > 替换为项目的名称。

  3. 当您要删除作业时,运行以下命令:

    删除作业

    oc delete pytorchjobs/pytorch-multi-node-job -n <your-namespace>
    Copy to Clipboard Toggle word wrap

    <your-namespace > 替换为项目的名称。

4.1.4. 培训 Operator PyTorch 培训脚本示例

以下示例演示了如何为 NVIDIA Collective Communications Library (NCCL)、分布式数据并行(DDP)和 Fully Sharded Data Parallel (FSDP)培训工作配置 PyTorch 培训脚本。

注意

如果您有所需资源,可以在不编辑的情况下运行示例代码。

或者,您可以修改示例代码,以指定适合您的培训工作配置。

4.1.4.1. 培训 Operator PyTorch 培训脚本示例:NCCL

此 NVIDIA Collective Communications Library (NCCL)示例返回每个加速器的 rank 和 10sor 值。

import os
import torch
import torch.distributed as dist

def main():
    # Select backend dynamically: nccl for GPU, gloo for CPU
    backend = "nccl" if torch.cuda.is_available() else "gloo"

    # Initialize the process group
    dist.init_process_group(backend)

    # Get rank and world size
    rank = dist.get_rank()
    world_size = dist.get_world_size()

    # Select device dynamically
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    print(f"Running on rank {rank} out of {world_size} using {device} with backend {backend}.")

    # Initialize tensor on the selected device
    tensor = torch.zeros(1, device=device)

    if rank == 0:
        tensor += 1
        for i in range(1, world_size):
            dist.send(tensor, dst=i)
    else:
        dist.recv(tensor, src=0)

    print(f"Rank {rank}: Tensor value {tensor.item()} on {device}")

if name == "main":
    main()
Copy to Clipboard Toggle word wrap

backend 值会自动设置为以下值之一:

  • nccl :将 NVIDIA Collective Communications Library (NCCL)用于 NVIDIA GPU 或 ROCm communications Collectives Library (RCCL)用于 AMD GPU
  • gloo: 对 CPU 使用 Gloo
注意

为 NVIDIA GPU 和 AMD GPU 指定 backend="nccl"。

对于 AMD GPU,即使 backend 值设置为 nccl,ROCm 环境使用 RCCL 进行通信。

4.1.4.2. 培训 Operator PyTorch 培训脚本示例:DDP

本例演示了如何为分布式数据并行(DDP)培训作业配置培训脚本。

import os
import sys
import torch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
from torch import nn, optim

# Enable verbose logging
os.environ["TORCH_DISTRIBUTED_DEBUG"] = "INFO"

def setup_ddp():
    """Initialize the distributed process group dynamically."""
    backend = "nccl" if torch.cuda.is_available() else "gloo"
    dist.init_process_group(backend=backend)
    local_rank = int(os.environ["LOCAL_RANK"])
    world_size = dist.get_world_size()

    # Ensure correct device is set
    device = torch.device(f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu")
    torch.cuda.set_device(local_rank) if torch.cuda.is_available() else None

    print(f"[Rank {local_rank}] Initialized with backend={backend}, world_size={world_size}")
    sys.stdout.flush()  # Ensure logs are visible in Kubernetes
    return local_rank, world_size, device

def cleanup():
    """Clean up the distributed process group."""
    dist.destroy_process_group()

class SimpleModel(nn.Module):
    """A simple model with multiple layers."""
    def init(self):
        super(SimpleModel, self).init()
        self.layer1 = nn.Linear(1024, 512)
        self.layer2 = nn.Linear(512, 256)
        self.layer3 = nn.Linear(256, 128)
        self.layer4 = nn.Linear(128, 64)
        self.output = nn.Linear(64, 1)

    def forward(self, x):
        x = torch.relu(self.layer1(x))
        x = torch.relu(self.layer2(x))
        x = torch.relu(self.layer3(x))
        x = torch.relu(self.layer4(x))
        return self.output(x)

def log_ddp_parameters(model, rank):
    """Log model parameter count for DDP."""
    num_params = sum(p.numel() for p in model.parameters())
    print(f"[Rank {rank}] Model has {num_params} parameters (replicated across all ranks)")
    sys.stdout.flush()

def log_memory_usage(rank):
    """Log GPU memory usage if CUDA is available."""
    if torch.cuda.is_available():
        torch.cuda.synchronize()
        print(f"[Rank {rank}] GPU Memory Allocated: {torch.cuda.memory_allocated() / 1e6} MB")
        print(f"[Rank {rank}] GPU Memory Reserved: {torch.cuda.memory_reserved() / 1e6} MB")
        sys.stdout.flush()

def main():
    local_rank, world_size, device = setup_ddp()

    # Initialize model and wrap with DDP
    model = SimpleModel().to(device)
    model = DDP(model, device_ids=[local_rank] if torch.cuda.is_available() else None)

    print(f"[Rank {local_rank}] DDP Initialized")
    log_ddp_parameters(model, local_rank)
    log_memory_usage(local_rank)

    # Optimizer and criterion
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    criterion = nn.MSELoss()

    # Dummy dataset (adjust for real-world use case)
    x = torch.randn(32, 1024).to(device)
    y = torch.randn(32, 1).to(device)

    # Training loop
    for epoch in range(5):
        model.train()
        optimizer.zero_grad()

        # Forward pass
        outputs = model(x)
        loss = criterion(outputs, y)

        # Backward pass
        loss.backward()
        optimizer.step()

        print(f"[Rank {local_rank}] Epoch {epoch}, Loss: {loss.item()}")
        log_memory_usage(local_rank)  # Track memory usage

        sys.stdout.flush()  # Ensure logs appear in real-time

    cleanup()

if name == "main":
    main()
Copy to Clipboard Toggle word wrap
4.1.4.3. 培训 Operator PyTorch 培训脚本示例:FSDP

本例演示了如何为 Fully Sharded Data Parallel (FSDP)培训工作配置培训脚本。

import os
import sys
import torch
import torch.distributed as dist
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP, CPUOffload
from torch.distributed.fsdp.wrap import always_wrap_policy
from torch import nn, optim

# Enable verbose logging for debugging
os.environ["TORCH_DISTRIBUTED_DEBUG"] = "INFO"  # Enables detailed FSDP logs

def setup_ddp():
    """Initialize the distributed process group dynamically."""
    backend = "nccl" if torch.cuda.is_available() else "gloo"
    dist.init_process_group(backend=backend)
    local_rank = int(os.environ["LOCAL_RANK"])
    world_size = dist.get_world_size()

    # Ensure the correct device is set
    device = torch.device(f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu")
    torch.cuda.set_device(local_rank) if torch.cuda.is_available() else None

    print(f"[Rank {local_rank}] Initialized with backend={backend}, world_size={world_size}")
    sys.stdout.flush()  # Ensure logs are visible in Kubernetes
    return local_rank, world_size, device

def cleanup():
    """Clean up the distributed process group."""
    dist.destroy_process_group()

class SimpleModel(nn.Module):
    """A simple model with multiple layers."""
    def init(self):
        super(SimpleModel, self).init()
        self.layer1 = nn.Linear(1024, 512)
        self.layer2 = nn.Linear(512, 256)
        self.layer3 = nn.Linear(256, 128)
        self.layer4 = nn.Linear(128, 64)
        self.output = nn.Linear(64, 1)

    def forward(self, x):
        x = torch.relu(self.layer1(x))
        x = torch.relu(self.layer2(x))
        x = torch.relu(self.layer3(x))
        x = torch.relu(self.layer4(x))
        return self.output(x)

def log_fsdp_parameters(model, rank):
    """Log FSDP parameters and sharding strategy."""
    num_params = sum(p.numel() for p in model.parameters())
    print(f"[Rank {rank}] Model has {num_params} parameters (sharded across {dist.get_world_size()} workers)")
    sys.stdout.flush()

def log_memory_usage(rank):
    """Log GPU memory usage if CUDA is available."""
    if torch.cuda.is_available():
        torch.cuda.synchronize()
        print(f"[Rank {rank}] GPU Memory Allocated: {torch.cuda.memory_allocated() / 1e6} MB")
        print(f"[Rank {rank}] GPU Memory Reserved: {torch.cuda.memory_reserved() / 1e6} MB")
        sys.stdout.flush()

def main():
    local_rank, world_size, device = setup_ddp()

    # Initialize model and wrap with FSDP
    model = SimpleModel().to(device)
    model = FSDP(
        model,
        cpu_offload=CPUOffload(offload_params=not torch.cuda.is_available()),  # Offload if no GPU
        auto_wrap_policy=always_wrap_policy,  # Wrap all layers automatically
    )

    print(f"[Rank {local_rank}] FSDP Initialized")
    log_fsdp_parameters(model, local_rank)
    log_memory_usage(local_rank)

    # Optimizer and criterion
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    criterion = nn.MSELoss()

    # Dummy dataset (adjust for real-world use case)
    x = torch.randn(32, 1024).to(device)
    y = torch.randn(32, 1).to(device)

    # Training loop
    for epoch in range(5):
        model.train()
        optimizer.zero_grad()

        # Forward pass
        outputs = model(x)
        loss = criterion(outputs, y)

        # Backward pass
        loss.backward()
        optimizer.step()

        print(f"[Rank {local_rank}] Epoch {epoch}, Loss: {loss.item()}")
        log_memory_usage(local_rank)  # Track memory usage

        sys.stdout.flush()  # Ensure logs appear in real-time

    cleanup()

if name == "main":
    main()
Copy to Clipboard Toggle word wrap

您可以使用此示例 Dockerfile 将培训脚本包含在自定义培训镜像中。

FROM quay.io/modh/training:py311-cuda124-torch251
WORKDIR /workspace
COPY train.py /workspace/train.py
CMD ["python", "train.py"]
Copy to Clipboard Toggle word wrap

这个示例将培训脚本复制到默认的 PyTorch 镜像,并运行 脚本。

有关如何使用此 Dockerfile 在自定义容器镜像中包含培训脚本的更多信息,请参阅 创建自定义培训镜像

本例演示了如何创建在具有多个 GPU 的多个节点上运行的培训 Operator PyTorch 培训作业。

apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
  name: pytorch-multi-node-job
  namespace: test-namespace
spec:
  pytorchReplicaSpecs:
    Master:
      replicas: 1
      restartPolicy: OnFailure
      template:
        metadata:
          labels:
            app: pytorch-multi-node-job
        spec:
          containers:
          - name: pytorch
            image: quay.io/modh/training:py311-cuda124-torch251
            imagePullPolicy: IfNotPresent
            command: ["torchrun", "/workspace/train.py"]
            volumeMounts:
              - name: training-script-volume
                mountPath: /workspace
            resources:
              requests:
                cpu: "4"
                memory: "8Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "4"
                memory: "8Gi"
                nvidia.com/gpu: "2"
          volumes:
            - name: training-script-volume
              configMap:
                name: training-script-configmap
    Worker:
      replicas: 1
      restartPolicy: OnFailure
      template:
        metadata:
          labels:
            app: pytorch-multi-node-job
        spec:
          containers:
          - name: pytorch
            image: quay.io/modh/training:py311-cuda124-torch251
            imagePullPolicy: IfNotPresent
            command: ["torchrun", "/workspace/train.py"]
            volumeMounts:
              - name: training-script-volume
                mountPath: /workspace
            resources:
              requests:
                cpu: "4"
                memory: "8Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "4"
                memory: "8Gi"
                nvidia.com/gpu: "2"
          volumes:
            - name: training-script-volume
              configMap:
                name: training-script-configmap
Copy to Clipboard Toggle word wrap

您可以使用 Training Operator SDK 将分布式培训作业配置为在每个节点有多个加速器的多个节点上运行。

您可以配置 PyTorchJob 资源,以便培训作业在多个带有多个 GPU 的节点上运行。

4.2.1. 使用 Training Operator SDK 配置培训作业

在运行作业以培训模型之前,您必须配置培训工作。您必须设置培训参数,定义培训功能,并配置 training Operator SDK。

注意

此流程中的代码指定如何配置一个示例培训作业。如果您有指定的资源,可以在不编辑的情况下运行示例代码。

或者,您可以修改示例代码,以指定适合您的培训工作配置。

先决条件

  • 您可以使用支持的加速器访问具有足够 worker 节点的 OpenShift 集群,以运行您的培训或调优作业。
  • 您可以访问适合分布式培训的工作台,如 为分布式培训 创建工作台 中所述。
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。

流程

  1. 打开工作台,如下所示:

    1. 登录到 Red Hat OpenShift AI web 控制台。
    2. Data Science projects 并点您的项目。
    3. 单击 Workbenches 选项卡。
    4. 如果您的工作台还没有运行,请启动工作台。
    5. Open 链接在新窗口中打开 IDE。
  2. File → New → Notebook
  3. 创建培训功能,如下例所示:

    1. 使用以下内容创建单元:

      培训功能示例

      def train_func():
          import os
          import torch
          import torch.distributed as dist
      
          # Select backend dynamically: nccl for GPU, gloo for CPU
          backend = "nccl" if torch.cuda.is_available() else "gloo"
      
          # Initialize the process group
          dist.init_process_group(backend)
      
          # Get rank and world size
          rank = dist.get_rank()
          world_size = dist.get_world_size()
      
          # Select device dynamically
          device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
      
          # Log rank initialization
          print(f"Rank {rank}/{world_size} initialized with backend {backend} on device {device}.")
      
          # Initialize tensor on the selected device
          tensor = torch.zeros(1, device=device)
      
          if rank == 0:
              tensor += 1
              for i in range(1, world_size):
                  dist.send(tensor, dst=i)
          else:
              dist.recv(tensor, src=0)
      
          print(f"Rank {rank}: Tensor value {tensor.item()} on {device}")
      
          # Cleanup
          dist.destroy_process_group()
      Copy to Clipboard Toggle word wrap

      注意

      在本示例培训工作中,您不需要安装任何其他软件包或设置任何培训参数。

      有关如何添加其他软件包并设置培训参数的更多信息,请参阅配置调优作业

    2. 可选:编辑内容来为您的环境指定适当的值。
    3. 运行单元以创建培训功能。
  4. 配置 Training Operator SDK 客户端身份验证,如下所示:

    1. 使用以下内容创建单元:

      培训 Operator SDK 客户端身份验证示例

      from kubernetes import client
      from kubeflow.training import TrainingClient
      from kubeflow.training.models import V1Volume, V1VolumeMount, V1PersistentVolumeClaimVolumeSource
      
      api_server = "<API_SERVER>"
      token = "<TOKEN>"
      
      configuration = client.Configuration()
      configuration.host = api_server
      configuration.api_key = {"authorization": f"Bearer {token}"}
      # Un-comment if your cluster API server uses a self-signed certificate or an un-trusted CA
      #configuration.verify_ssl = False
      api_client = client.ApiClient(configuration)
      client = TrainingClient(client_configuration=api_client.configuration)
      Copy to Clipboard Toggle word wrap

    2. 编辑 api_servertoken 参数,以输入要向 OpenShift 集群进行身份验证的值。

      有关如何查找服务器和令牌详情的详情,请参考使用集群服务器和令牌进行身份验证

    3. 运行单元来配置 Training Operator SDK 客户端身份验证。
  5. File > Save Notebook As,输入适当的文件名,然后点 Save

验证

  1. 所有单元都成功运行。

4.2.2. 使用 Training Operator SDK 运行培训作业

当您运行培训作业来调优模型时,您必须指定所需的资源,并提供所需的任何授权凭证。

注意

此流程中的代码指定如何运行示例培训作业。如果您有指定的资源,可以在不编辑的情况下运行示例代码。

或者,您可以修改示例代码,以指定培训工作的适当详情。

先决条件

  • 您可以使用支持的加速器访问具有足够 worker 节点的 OpenShift 集群,以运行您的培训或调优作业。
  • 您可以访问适合分布式培训的工作台,如 为分布式培训 创建工作台 中所述。
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您已通过将 kueue.openshift.io/managed=true 标签应用到项目命名空间,为 Kueue.openshift.io/managed=true 标签启用了您的项目。
  • 您已为数据科学项目创建了资源类别、集群队列和本地队列 Kueue 对象。有关创建这些对象的更多信息,请参阅 为分布式工作负载配置配额管理
  • 您可以访问模型。
  • 您可以访问可用于培训模型的数据。
  • 您已配置了培训工作,如使用 training Operator SDK 配置培训作业 中所述。

流程

  1. 打开工作台,如下所示:

    1. 登录到 Red Hat OpenShift AI web 控制台。
    2. Data Science projects 并点您的项目。
    3. 单击 Workbenches 选项卡。如果您的工作台还没有运行,请启动工作台。
    4. Open 链接在新窗口中打开 IDE。
  2. File → Open,打开您用来配置培训作业的 Jupyter 笔记本。
  3. 创建单元来运行作业,并添加以下内容:

    from kubernetes import client
    
    # Start PyTorchJob with 2 Workers and 2 GPU per Worker (multi-node, multi-worker job).
    client.create_job(
       name="pytorch-ddp",
       train_func=train_func,
       base_image="quay.io/modh/training:py311-cuda124-torch251",
       num_workers=2,
       resources_per_worker={"nvidia.com/gpu": "2"},
       packages_to_install=["torchvision==0.19.0"],
       env_vars={"NCCL_DEBUG": "INFO", "TORCH_DISTRIBUTED_DEBUG": "DETAIL"},
       labels={
            "kueue.x-k8s.io/queue-name": "<local-queue-name>",
            "key": "value"
        },
       annotations={"key": "value"}
    )
    Copy to Clipboard Toggle word wrap
  4. 编辑内容以指定环境的适当值,如下所示:

    1. 编辑 num_workers 值,以指定 worker 节点的数量。
    2. 根据作业要求和可用资源更新 resources_per_worker 值。
    3. 编辑 kueue.x-k8s.io/queue-name 标签的值,以匹配目标 LocalQueue 的名称。
    4. 提供的示例是 NVIDIA GPU。如果使用 AMD 加速器,请进行以下额外更改:

      • resources_per_worker 条目中,将 nvidia.com/gpu 改为 amd.com/gpu
      • base_image 值更改为 quay.io/modh/ training:py311-rocm62-torch251
      • 删除 NCCL_DEBUG 条目

如果没有显式设置 job_kind 值,则 TrainingClient API 会自动将 job_kind 值设置为 PyTorchJob

  1. 运行单元以运行该作业。

验证

查看作业的进度,如下所示:

  1. 使用以下内容创建单元:

    client.get_job_logs(
        name="pytorch-ddp",
        job_kind="PyTorchJob",
        follow=True,
    )
    Copy to Clipboard Toggle word wrap
  2. 运行单元以查看作业进度。

4.3. 使用 Kubeflow 培训微调模型

Supervised fine-tuning (SFT)是通过使用标记的数据为特定任务自定义大型语言模型(LLM)的过程。在本例中,您可以使用 Kubeflow Training Operator 和 Kubeflow Training Operator Python Software Development Kit (learning Operator SDK)在 Red Hat OpenShift AI 中使用 Hugging Face SFT Trainer 来增强微调 LLM。

另外,您可以使用 Low-Rank Adaptation (LoRA)高效地微调大型语言模型。LORA 优化计算要求并减少内存占用,使您能够微调消费者级 GPU。通过 SFT,您可以组合 PyTorch Fully Sharded Data Parallel (FSDP)和 LoRA,以便实现可扩展、经济型模型培训和推测,从而提高 OpenShift 环境中 AI 工作负载的灵活性和性能。

4.3.1. 配置微调作业

在您可以使用培训工作来微调模型之前,您必须配置培训工作。您必须设置培训参数,定义培训功能,并配置 training Operator SDK。

注意

此流程中的代码指定如何配置一个示例微调作业。如果您有指定的资源,可以在不编辑的情况下运行示例代码。

或者,您可以修改示例代码,为微调任务指定适当的配置。

先决条件

  • 您可以使用支持的加速器访问具有足够 worker 节点的 OpenShift 集群,以运行您的培训或调优作业。

    微调作业示例需要 8 个 worker 节点,每个 worker 节点都有 64 GiB 内存、4 个 CPU 和 1 NVIDIA GPU。

  • 您可以访问适合分布式培训的工作台,如 为分布式培训 创建工作台 中所述。
  • 您可以访问支持 ReadWriteMany (RWX)持久性卷声明(PVC)置备的动态存储置备程序,如 Red Hat OpenShift Data Foundation
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。

流程

  1. 打开工作台,如下所示:

    1. 登录到 Red Hat OpenShift AI web 控制台。
    2. Data Science projects 并点您的项目。
    3. 单击 Workbenches 选项卡。
    4. 确保工作台使用具有 RWX 功能的存储类。
    5. 如果您的工作台还没有运行,请启动工作台。
    6. Open 链接在新窗口中打开 IDE。
  2. File → New → Notebook
  3. 安装运行培训或调优作业所需的任何其他软件包。

    1. 在笔记本单元中,添加代码来安装其他软件包,如下所示:

      安装依赖项的代码

      # Install the yamlmagic package
      !pip install yamlmagic
      %load_ext yamlmagic
      
      !pip install git+https://github.com/kubeflow/trainer.git@release-1.9#subdirectory=sdk/python
      Copy to Clipboard Toggle word wrap

    2. 选择单元,然后点 Run > Run selected cell

      已安装其他软件包。

  4. 设置培训参数,如下所示:

    1. 使用以下内容创建单元:

      %%yaml parameters
      
      # Model
      model_name_or_path: Meta-Llama/Meta-Llama-3.1-8B-Instruct
      model_revision: main
      torch_dtype: bfloat16
      attn_implementation: flash_attention_2
      
      # PEFT / LoRA
      use_peft: true
      lora_r: 16
      lora_alpha: 8
      lora_dropout: 0.05
      lora_target_modules: ["q_proj", "v_proj", "k_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]
      lora_modules_to_save: []
      init_lora_weights: true
      
      # Quantization / BitsAndBytes
      load_in_4bit: false                       # use 4 bit precision for the base model (only with LoRA)
      load_in_8bit: false                       # use 8 bit precision for the base model (only with LoRA)
      
      # Datasets
      dataset_name: gsm8k                       # id or path to the dataset
      dataset_config: main                      # name of the dataset configuration
      dataset_train_split: train                # dataset split to use for training
      dataset_test_split: test                  # dataset split to use for evaluation
      dataset_text_field: text                  # name of the text field of the dataset
      dataset_kwargs:
        add_special_tokens: false               # template with special tokens
        append_concat_token: false              # add additional separator token
      
      # SFT
      max_seq_length: 1024                      # max sequence length for model and packing of the dataset
      dataset_batch_size: 1000                  # samples to tokenize per batch
      packing: false
      use_liger: false
      
      # Training
      num_train_epochs: 10                      # number of training epochs
      
      per_device_train_batch_size: 32           # batch size per device during training
      per_device_eval_batch_size: 32            # batch size for evaluation
      auto_find_batch_size: false               # find a batch size that fits into memory automatically
      eval_strategy: epoch                      # evaluate every epoch
      
      bf16: true                                # use bf16 16-bit (mixed) precision
      tf32: false                               # use tf32 precision
      
      learning_rate: 1.0e-4                     # initial learning rate
      warmup_steps: 10                          # steps for a linear warmup from 0 to `learning_rate`
      lr_scheduler_type: inverse_sqrt           # learning rate scheduler (see transformers.SchedulerType)
      
      optim: adamw_torch_fused                  # optimizer (see transformers.OptimizerNames)
      max_grad_norm: 1.0                        # max gradient norm
      seed: 42
      
      gradient_accumulation_steps: 1            # number of steps before performing a backward/update pass
      gradient_checkpointing: false             # use gradient checkpointing to save memory
      gradient_checkpointing_kwargs:
        use_reentrant: false
      
      # FSDP
      fsdp: "full_shard auto_wrap offload"      # remove offload if enough GPU memory
      fsdp_config:
        activation_checkpointing: true
        cpu_ram_efficient_loading: false
        sync_module_states: true
        use_orig_params: true
        limit_all_gathers: false
      
      # Checkpointing
      save_strategy: epoch                      # save checkpoint every epoch
      save_total_limit: 1                       # limit the total amount of checkpoints
      resume_from_checkpoint: false             # load the last checkpoint in output_dir and resume from it
      
      # Logging
      log_level: warning                        # logging level (see transformers.logging)
      logging_strategy: steps
      logging_steps: 1                          # log every N steps
      report_to:
      - tensorboard                             # report metrics to tensorboard
      
      output_dir: /mnt/shared/Meta-Llama-3.1-8B-Instruct
      Copy to Clipboard Toggle word wrap
    2. 可选:如果您指定不同的模型或数据集,请编辑参数以适应模型、数据集和资源。如有必要,更新前面的单元以指定培训或调优作业的依赖项。
    3. 运行单元来设置培训参数。
  5. 创建培训功能,如下所示:

    1. 使用以下内容创建单元:

      def main(parameters):
          import random
      
          from datasets import load_dataset
          from transformers import (
              AutoTokenizer,
              set_seed,
          )
      
          from trl import (
              ModelConfig,
              ScriptArguments,
              SFTConfig,
              SFTTrainer,
              TrlParser,
              get_peft_config,
              get_quantization_config,
              get_kbit_device_map,
          )
      
          parser = TrlParser((ScriptArguments, SFTConfig, ModelConfig))
          script_args, training_args, model_args = parser.parse_dict(parameters)
      
          # Set seed for reproducibility
          set_seed(training_args.seed)
      
          # Model and tokenizer
          quantization_config = get_quantization_config(model_args)
          model_kwargs = dict(
              revision=model_args.model_revision,
              trust_remote_code=model_args.trust_remote_code,
              attn_implementation=model_args.attn_implementation,
              torch_dtype=model_args.torch_dtype,
              use_cache=False if training_args.gradient_checkpointing or
                                 training_args.fsdp_config.get("activation_checkpointing",
                                                               False) else True,
              device_map=get_kbit_device_map() if quantization_config is not None else None,
              quantization_config=quantization_config,
          )
          training_args.model_init_kwargs = model_kwargs
          tokenizer = AutoTokenizer.from_pretrained(
              model_args.model_name_or_path, trust_remote_code=model_args.trust_remote_code, use_fast=True
          )
          if tokenizer.pad_token is None:
              tokenizer.pad_token = tokenizer.eos_token
      
          # You can override the template here according to your use case
          # tokenizer.chat_template = ...
      
          # Datasets
          train_dataset = load_dataset(
              path=script_args.dataset_name,
              name=script_args.dataset_config,
              split=script_args.dataset_train_split,
          )
          test_dataset = None
          if training_args.eval_strategy != "no":
              test_dataset = load_dataset(
                  path=script_args.dataset_name,
                  name=script_args.dataset_config,
                  split=script_args.dataset_test_split,
              )
      
          # Templatize datasets
          def template_dataset(sample):
              # return{"text": tokenizer.apply_chat_template(examples["messages"], tokenize=False)}
              messages = [
                  {"role": "user", "content": sample[question]},
                  {"role": "assistant", "content": sample[answer]},
              ]
              return {"text": tokenizer.apply_chat_template(messages, tokenize=False)}
      
          train_dataset = train_dataset.map(template_dataset, remove_columns=["question", "answer"])
          if training_args.eval_strategy != "no":
              # test_dataset = test_dataset.map(template_dataset, remove_columns=["messages"])
              test_dataset = test_dataset.map(template_dataset, remove_columns=["question", "answer"])
      
          # Check random samples
          with training_args.main_process_first(
              desc="Log few samples from the training set"
          ):
              for index in random.sample(range(len(train_dataset)), 2):
                  print(train_dataset[index]["text"])
      
          # Training
          trainer = SFTTrainer(
              model=model_args.model_name_or_path,
              args=training_args,
              train_dataset=train_dataset,
              eval_dataset=test_dataset,
              peft_config=get_peft_config(model_args),
              tokenizer=tokenizer,
          )
      
          if trainer.accelerator.is_main_process and hasattr(trainer.model, "print_trainable_parameters"):
              trainer.model.print_trainable_parameters()
      
          checkpoint = None
          if training_args.resume_from_checkpoint is not None:
              checkpoint = training_args.resume_from_checkpoint
      
          trainer.train(resume_from_checkpoint=checkpoint)
      
          trainer.save_model(training_args.output_dir)
      
          with training_args.main_process_first(desc="Training completed"):
              print(f"Training completed, model checkpoint written to {training_args.output_dir}")
      Copy to Clipboard Toggle word wrap
    2. 可选:如果您指定不同的模型或数据集,请编辑 tokenizer.chat_template 参数,为您的 model 和 dataset 指定适当的值。
    3. 运行单元以创建培训功能。
  6. 配置 Training Operator SDK 客户端身份验证,如下所示:

    1. 使用以下内容创建单元:

      from kubernetes import client
      from kubeflow.training import TrainingClient
      from kubeflow.training.models import V1Volume, V1VolumeMount, V1PersistentVolumeClaimVolumeSource
      
      api_server = "<API_SERVER>"
      token = "<TOKEN>"
      
      configuration = client.Configuration()
      configuration.host = api_server
      configuration.api_key = {"authorization": f"Bearer {token}"}
      # Un-comment if your cluster API server uses a self-signed certificate or an un-trusted CA
      #configuration.verify_ssl = False
      api_client = client.ApiClient(configuration)
      client = TrainingClient(client_configuration=api_client.configuration)
      Copy to Clipboard Toggle word wrap
    2. 编辑 api_servertoken 参数,以输入要向 OpenShift 集群进行身份验证的值。

      有关如何查找服务器和令牌详情的详情,请参考使用集群服务器和令牌进行身份验证

    3. 运行单元来配置 Training Operator SDK 客户端身份验证。
  7. File > Save Notebook As,输入适当的文件名,然后点 Save

验证

  1. 所有单元都成功运行。

4.3.2. 运行微调任务

当您运行培训作业来调优模型时,您必须指定所需的资源,并提供所需的任何授权凭证。

注意

此流程中的代码指定如何运行微调作业示例。如果您有指定的资源,可以在不编辑的情况下运行示例代码。

或者,您可以修改示例代码,以指定微调作业的适当详情。

先决条件

  • 您可以使用支持的加速器访问具有足够 worker 节点的 OpenShift 集群,以运行您的培训或调优作业。

    微调作业示例需要 8 个 worker 节点,每个 worker 节点都有 64 GiB 内存、4 个 CPU 和 1 NVIDIA GPU。

  • 您可以访问适合分布式培训的工作台,如 为分布式培训 创建工作台 中所述。
  • 具有数据科学项目的管理员访问权限。

    • 如果创建项目,则会自动具有管理员访问权限。
    • 如果没有创建项目,您的集群管理员必须授予管理员访问权限。
  • 您可以访问模型。
  • 您可以访问可用于培训模型的数据。
  • 您已配置了微调作业,如 配置调优作业 中所述。
  • 您可以访问支持 ReadWriteMany (RWX)持久性卷声明(PVC)置备的动态存储置备程序,如 Red Hat OpenShift Data Foundation
  • 名为 shared with RWX 访问模式的 PersistentVolumeClaim 资源会附加到您的工作台中。
  • 您有一个 Hugging Face 帐户和访问令牌。如需更多信息,请参阅 Hugging Face 文档中的 "用户访问令牌"。

流程

  1. 打开工作台,如下所示:

    1. 登录到 Red Hat OpenShift AI web 控制台。
    2. Data Science projects 并点您的项目。
    3. 单击 Workbenches 选项卡。如果您的工作台还没有运行,请启动工作台。
    4. Open 链接在新窗口中打开 IDE。
  2. File → Open,打开您用来配置微调作业的 Jupyter 笔记本。
  3. 创建单元来运行作业,并添加以下内容:

    client.create_job(
        job_kind="PyTorchJob",
        name="sft",
        train_func=main,
        num_workers=8,
        num_procs_per_worker="1",
        resources_per_worker={
            "nvidia.com/gpu": 1,
            "memory": "64Gi",
            "cpu": 4,
        },
        base_image="quay.io/modh/training:py311-cuda124-torch251",
        env_vars={
            # Hugging Face
            "HF_HOME": "/mnt/shared/.cache",
            "HF_TOKEN": "",
            # CUDA
            "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True",
            # NCCL
            "NCCL_DEBUG": "INFO",
            "NCCL_ENABLE_DMABUF_SUPPORT": "1",
        },
        packages_to_install=[
            "tensorboard",
        ],
        parameters=parameters,
        volumes=[
            V1Volume(name="shared",
                persistent_volume_claim=V1PersistentVolumeClaimVolumeSource(claim_name="shared")),
        ],
        volume_mounts=[
            V1VolumeMount(name="shared", mount_path="/mnt/shared"),
        ],
    )
    Copy to Clipboard Toggle word wrap
  4. 编辑 HF_TOKEN 值,以指定您的 Hugging Face 访问令牌。

    可选: 如果您指定了不同的模型,且您的模型不是 Hugging Face Hub 的控制模型,请删除 HF_HOMEHF_TOKEN 条目。

  5. 可选:编辑其他内容来为您的环境指定适当的值,如下所示:

    1. 编辑 num_workers 值,以指定 worker 节点的数量。
    2. 根据作业要求和可用资源更新 resources_per_worker 值。
    3. 提供的示例是 NVIDIA GPU。如果使用 AMD 加速器,请进行以下额外更改:

      • resources_per_worker 条目中,将 nvidia.com/gpu 改为 amd.com/gpu
      • base_image 值更改为 quay.io/modh/ training:py311-rocm62-torch251
      • 删除 CUDANCCL 条目
    4. 如果附加到工作台的 RWX PersistentVolumeClaim 资源具有不同的名称而不是 共享,请更新以下值以用 PVC 名称替换 共享

      • 在此单元中,更新 HF_HOME 值。
      • 在这个单元中,在 volumes 条目中更新 PVC 详情:

        • V1Volume 条目中,更新 nameclaim_name 值。
        • volume_mounts 条目中,更新 namemount_path 值。
      • 在设置 training 参数的单元中,更新 output_dir 值。

        有关设置培训参数的更多信息,请参阅配置调优作业

  6. 运行单元以运行该作业。

验证

查看作业的进度,如下所示:

  1. 使用以下内容创建单元:

    client.get_job_logs(
        name="sft",
        job_kind="PyTorchJob",
        follow=True,
    )
    Copy to Clipboard Toggle word wrap
  2. 运行单元以查看作业进度。

4.3.3. 删除微调作业

当您不再需要微调作业时,请删除作业来释放资源。

注意

此流程中的代码指定如何删除示例微调作业。如果您创建了名为 sft 的示例微调作业,您可以在不编辑的情况下运行示例代码。

或者,您可以修改此示例代码来指定微调作业的名称。

先决条件

流程

  1. 打开工作台,如下所示:

    1. 登录到 Red Hat OpenShift AI web 控制台。
    2. Data Science projects 并点您的项目。
    3. 单击 Workbenches 选项卡。如果您的工作台还没有运行,请启动工作台。
    4. Open 链接在新窗口中打开 IDE。
  2. File → Open,打开您用来配置和运行示例微调作业的 Jupyter 笔记本。
  3. 使用以下内容创建单元:

    client.delete_job(name="sft")
    Copy to Clipboard Toggle word wrap
  4. 可选:如果要删除其他作业,请编辑内容,将 sft 替换为作业的名称。
  5. 运行单元以删除作业。

验证

  1. 在 OpenShift 控制台中,在 Administrator 视角中点 Workloads → Jobs
  2. Project 列表中,选择您的项目。
  3. 验证指定的作业没有被列出。

4.4. 使用 RDMA 创建多节点首选培训作业

NVIDIA GPUDirect RDMA 使用远程直接内存访问(RDMA)提供直接 GPU 互连,使外设设备能够直接访问远程系统中的 NVIDIA GPU 内存。RDMA 改进了培训作业性能,因为它消除了使用操作系统 CPU 和内存的开销。在使用多个 GPU 的多个节点上运行培训作业可显著减少完成时间。

在 Red Hat OpenShift AI 中,Nvidia GPU 可通过以下类型的网络使用 GPUDirect RDMA 来直接通信:

  • 以太网:通过融合以太网的 RDMA (RoCE)
  • InfiniBand

在为 RDMA 配置的集群中创建 PyTorch 培训作业前,您必须配置该作业以使用高速网络接口。

先决条件

流程

  1. 登录 OpenShift 控制台。
  2. 创建 PyTorchJob 资源,如下所示:

    1. Administrator 视角中,点击 Home → Search
    2. Project 列表中,选择您的项目。
    3. 单击 Resources 列表,然后在搜索字段中开始输入 PyTorchJob
    4. 选择 PyTorchJob,然后单击 Create PyTorchJob

      Create PyTorchJob 页面将打开,自动添加默认 YAML 代码。

  3. 将高速网络接口附加到 PyTorchJob pod,如下所示:

    1. 编辑 PyTorchJob 资源 YAML 代码,使其包含将 pod 添加到额外网络的注解,如下例所示:

      将网络接口附加到 pod 的注解示例

      spec:
        pytorchReplicaSpecs:
          Master:
            replicas: 1
            restartPolicy: OnFailure
            template:
              metadata:
                annotations:
                  k8s.v1.cni.cncf.io/networks: "example-net"
      Copy to Clipboard Toggle word wrap

    2. 将示例网络名称 example-net 替换为您的配置的适当值。
  4. 将作业配置为使用 NVIDIA Collective Communications Library (NCCL)接口,如下所示:

    1. 编辑 PyTorchJob 资源 YAML 代码,以添加以下环境变量:

      环境变量示例

              spec:
                containers:
                - command:
                  - /bin/bash
                  - -c
                  - "your container command"
                  env:
                  - name: NCCL_SOCKET_IFNAME
                    value: "net1"
                  - name: NCCL_IB_HCA
                    value: "mlx5_1"
      Copy to Clipboard Toggle word wrap

    2. 将 example environment-variable 值替换为您的配置的适当值:

      1. 设置 *NCCL_SOCKET_IFNAME* 环境变量,以指定用于通信的 IP 接口。
      2. [可选] 要明确指定 NCCL 应使用的 Host Channel Adapter (HCA),请设置 *NCCL_IB_HCA* 环境变量。
  5. 指定基本培训镜像名称,如下所示:

    1. 编辑 PyTorchJob 资源 YAML 代码,以添加以下文本:

      基本培训镜像示例

      image: quay.io/modh/training:py311-cuda124-torch251
      Copy to Clipboard Toggle word wrap

    2. 如果要使用其他基本培训镜像,请相应地替换镜像名称。

      有关支持的培训镜像列表,请参阅 Red Hat OpenShift AI: 支持的配置

  6. 指定网络接口资源的请求和限值。

    资源名称因 NVIDIA Network Operator 配置而异。资源名称可能依赖于部署模式,并在 NicClusterPolicy 资源中指定。

    注意

    您必须使用与您的配置匹配的资源名称。名称必须与集群节点上 NVIDIA Network Operator 公告的值对应。

    以下示例是 RDMA over Converged Ethernet (RoCE),其中以太网 RDMA 设备使用 RDMA 共享设备模式。

    1. 查看 NicClusterPolicy 资源,以识别 resourceName 值。

      NicClusterPolicy 示例

      apiVersion: mellanox.com/v1alpha1
      kind: NicClusterPolicy
      spec:
      rdmaSharedDevicePlugin:
        config: |
          {
            "configList": [
              {
                "resourceName": "rdma_shared_device_eth",
                "rdmaHcaMax": 63,
                "selectors": {
                  "ifNames": ["ens8f0np0"]
                }
              }
            ]
          }
      Copy to Clipboard Toggle word wrap

      在本例中,resourceName 资源是 rdma_shared_device_eth

    2. 编辑 PyTorchJob 资源 YAML 代码,以添加以下文本:

      网络接口资源的请求和限值示例

                  resources:
                    limits:
                      nvidia.com/gpu: "1"
                      rdma/rdma_shared_device_eth: "1"
                    requests:
                      nvidia.com/gpu: "1"
                      rdma/rdma_shared_device_eth: "1"
      Copy to Clipboard Toggle word wrap

    3. limitsrequests 部分中,将资源名称替换为 NicClusterPolicy 资源中的资源名称(本例中为 rdma_shared_device_eth)。
    4. 将指定值 1 替换为您需要的数字。确保 OpenShift 集群中提供了指定数量。
  7. 重复上述步骤,在 PyTorchJob YAML 代码的 Worker 部分中进行相同的编辑。
  8. Create

您已创建了一个配置为使用 RDMA 运行的多节点 PyTorch 培训作业。

您可以在 配置为使用 RDMA 运行的示例 Training Operator PyTorchJob 资源中看到此示例 PyTorchJob 资源的 整个 YAML 代码。

验证

  1. 在 OpenShift 控制台中,打开 Administrator 视角。
  2. Project 列表中,选择您的项目。
  3. Home → Search → PyTorchJob,并验证作业是否已创建。
  4. Workloads → Pods,验证请求的 head pod 和 worker pod 是否正在运行。

本例演示了如何创建配置为使用 Remote Direct Memory Access (RDMA)运行的 Training Operator PyTorch training 作业。

apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
  name: job
spec:
  pytorchReplicaSpecs:
    Master:
      replicas: 1
      restartPolicy: OnFailure
      template:
        metadata:
          annotations:
            k8s.v1.cni.cncf.io/networks: "example-net"
        spec:
          containers:
          - command:
            - /bin/bash
            - -c
            - "your container command"
            env:
            - name: NCCL_SOCKET_IFNAME
              value: "net1"
            - name: NCCL_IB_HCA
              value: "mlx5_1"
            image: quay.io/modh/training:py311-cuda124-torch251
            name: pytorch
            resources:
              limits:
                nvidia.com/gpu: "1"
                rdma/rdma_shared_device_eth: "1"
              requests:
                nvidia.com/gpu: "1"
                rdma/rdma_shared_device_eth: "1"
    Worker:
      replicas: 3
      restartPolicy: OnFailure
      template:
        metadata:
          annotations:
            k8s.v1.cni.cncf.io/networks: "example-net"
        spec:
          containers:
          - command:
            - /bin/bash
            - -c
            - "your container command"
            env:
            - name: NCCL_SOCKET_IFNAME
              value: "net1"
            - name: NCCL_IB_HCA
              value: "mlx5_1"
            image: quay.io/modh/training:py311-cuda124-torch251
            name: pytorch
            resources:
              limits:
                nvidia.com/gpu: "1"
                rdma/rdma_shared_device_eth: "1"
              requests:
                nvidia.com/gpu: "1"
                rdma/rdma_shared_device_eth: "1"
Copy to Clipboard Toggle word wrap

第 5 章 监控分布式工作负载

在 OpenShift AI 中,您可以查看分布式工作负载的项目指标,并查看所选项目中所有分布式工作负载的状态。您可以使用这些指标来监控分布式工作负载使用的资源,评估项目资源是否已正确分配,跟踪分布式工作负载的进度,并在需要时识别正确的操作。

注意

数据科学管道工作负载不由分布式工作负载功能管理,不包含在分布式工作负载指标中。

5.1. 查看分布式工作负载的项目指标

在 OpenShift AI 中,您可以查看分布式工作负载的以下项目指标:

  • CPU - 当前被所选项目中所有分布式工作负载使用的 CPU 内核数。
  • memory- 以 gibibytes (GiB)为单位的内存量,供所选项目中的所有分布式工作负载使用。

您可以使用这些指标来监控分布式工作负载使用的资源,并评估项目资源是否已正确分配。

先决条件

  • 已安装 Red Hat OpenShift AI。
  • 在安装 OpenShift AI 的 OpenShift 集群上,启用了用户工作负载监控。
  • 您已登陆到 Red Hat OpenShift AI。
  • 您的数据科学项目包含分布式工作负载。

流程

  1. 在 OpenShift AI left 导航窗格中,单击 Distributed workload
  2. Project 列表中,选择包含您要监控的分布式工作负载的项目。
  3. Project metrics 选项卡。
  4. 可选: 在 Refresh interval 列表中,选择一个值来指定指标页面上图形的频率,以显示最新的数据。

    您可以选择以下值之一:15 秒 ,30 , 1 分钟,5 分钟 ,15 分钟,30 分钟 ,1 小时,2 小时, 或 1 天

  5. Requested resources 部分中,查看 CPUMemory 图形,以识别分布式工作负载请求的资源,如下所示:

    • 所选项目请求
    • 由所有项目请求,包括无法访问的所选项目和项目
    • 所有项目的共享配额,如集群队列提供

    对于每个资源类型(CPU 和内存),从 Total shared quota 值中减去 所有 projects 值的 Requested,以计算没有请求并可用于所有项目的资源配额量。

  6. 向下滚动到 Top 资源耗时的分布式工作负载 部分,以查看以下图形:

    • 消耗最多 CPU 资源的 5 个分布式工作负载
    • 消耗最多内存的 5 个分布式工作负载

    您还可以识别每个情况下使用的 CPU 或内存量。

  7. 向下滚动以查看 分布式工作负载资源指标表,它列出了所选项目中的所有分布式工作负载,并指示当前资源使用量和每个分布式工作负载的状态。

    在每个表条目中,进度条指示此分布式工作负载当前正在使用请求的 CPU 和内存量。要查看实际使用量和请求 CPU 使用量的数字值(以内核数表示)和内存(以 GiB 为单位),请将光标悬停到每个进度栏上。将实际使用量与请求的使用量进行比较,以评估分布式工作负载配置。如有必要,重新配置分布式工作负载,以减少或增加请求的资源。

验证

Project metrics 选项卡中,图形和表为所选项目中的分布式工作负载提供资源使用数据。

5.2. 查看分布式工作负载的状态

在 OpenShift AI 中,您可以查看所选项目中所有分布式工作负载的状态。您可以跟踪分布式工作负载的进度,并在需要时识别正确的操作。

先决条件

  • 已安装 Red Hat OpenShift AI。
  • 在安装 OpenShift AI 的 OpenShift 集群上,启用了用户工作负载监控。
  • 您已登陆到 Red Hat OpenShift AI。
  • 您的数据科学项目包含分布式工作负载。

流程

  1. 在 OpenShift AI left 导航窗格中,单击 Distributed workload
  2. Project 列表中,选择包含您要监控的分布式工作负载的项目。
  3. Distributed workload status 选项卡。
  4. 可选: 在 Refresh interval 列表中,选择一个值来指定指标页面上图形的频率,以显示最新的数据。

    您可以选择以下值之一:15 秒 ,30 , 1 分钟,5 分钟 ,15 分钟,30 分钟 ,1 小时,2 小时, 或 1 天

  5. Status overview 部分中,查看所选项目中所有分布式工作负载的状态摘要。

    状态可以是 Pending,Inadmissible, Admitted, Running,Evicted,Succeeded, 或 Failed

  6. 向下滚动以查看 分布式工作负载 表,该表列出了所选项目中的所有分布式工作负载。表为每个分布式工作负载提供优先级、状态、创建日期和最新消息。

    最新消息提供有关分布式工作负载当前状态的更多信息。查看最新的消息,以确定所需的任何纠正操作。例如,分布式工作负载可能 不可避免,因为请求的资源超过可用资源。在这种情况下,您可以重新配置分布式工作负载来减少请求的资源,或者重新配置项目的集群队列,以提高资源配额。

验证

分布式工作负载状态 选项卡中,图提供了所选项目中所有分布式工作负载状态的总结视图,表提供了有关每个分布式工作负载状态的更多详情。

5.3. 查看分布式工作负载的 Kueue 警报

在 OpenShift AI 中,您可以查看集群的 Kueue 警报。每个警报都提供一个指向 runbook 的链接。runbook 提供了如何解决触发警报的说明。

先决条件

  • 已使用 cluster-admin 角色登录 OpenShift。
  • 您可以访问配置为运行分布式工作负载的数据科学项目,如 管理分布式工作负载 中所述。
  • 您可以访问包含工作台的数据科学项目,工作台正在运行包含 CodeFlare SDK 的默认工作台镜像,如 Standard Data Science workbench。有关项目和工作台 的详情,请参考使用数据科学项目
  • 您已登陆到 Red Hat OpenShift AI。
  • 您的数据科学项目包含分布式工作负载。

流程

  1. 在 OpenShift 控制台中,在 Administrator 视角中点 ObserveAlerting
  2. 单击 Alerting rules 选项卡,以查看 default 和用户定义的项目的警报规则列表。

    • Severity 列指示警报是否为 informational、警告还是 critical。
    • Alert state 列指示规则当前是否触发。
  3. 点警报规则的名称查看更多详情,如触发该警报的条件。下表总结了 Kueue 资源的警报规则。

    Expand
    表 5.1. Kueue 资源的警报规则
    重要性Name报警条件

    Critical

    KueuePodDown

    Kueue pod 未就绪,持续 5 分钟。

    info

    LowClusterQueueResourceUsage

    集群队列中的资源使用量低于其在 1 天以上的 nominal 配额的 20%。资源使用情况指的是集群队列中列出的任何资源,如 CPU、内存等。

    info

    ResourceReservationExceedsQuota

    资源保留是集群队列中可用配额的 10 倍。资源保留指的是集群队列中列出的任何资源,如 CPU、内存等。

    info

    PendingWorkloadPods

    一个 pod 处于 Pending 状态超过 3 天。

  4. 如果警报规则的 Alert 状态 被设置为 Firing,请完成以下步骤:

    1. ObserveAlerting,然后点 Alerts 选项卡。
    2. 点触发规则的每个警报查看更多详情。请注意,针对受警报规则影响的每个资源类型触发单独的警报。
    3. 在警报详情页面的 Runbook 部分中,单击链接以打开提供故障排除信息的 GitHub 页面。
    4. 完成 runbook 步骤以确定警报的原因并解决这种情况。

验证

在解决警报原因后,警报规则将停止触发。

如果您在 Red Hat OpenShift AI 中遇到与分布式工作负载相关的错误,请阅读本节以了解造成此问题的原因,以及如何解决这个问题。

如果此处或发行注记中没有记录这个问题,请联系红帽支持团队。

6.1. 我的 Ray 集群处于暂停状态

问题

集群队列配置中指定的资源配额可能不足,或者资源类别可能尚未创建。

诊断

Ray 集群头 pod 或 worker pod 处于暂停状态。

解决方案

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 检查工作负载资源:

    1. 单击 Search,然后从 Resources 列表中选择 Workload
    2. 选择使用 Ray 集群资源创建的工作负载资源,然后点 YAML 选项卡。
    3. 检查 status.conditions.message 字段中的文本,它提供暂停状态的原因,如下例所示:

      status:
       conditions:
         - lastTransitionTime: '2024-05-29T13:05:09Z'
           message: 'couldn''t assign flavors to pod set small-group-jobtest12: insufficient quota for nvidia.com/gpu in flavor default-flavor in ClusterQueue'
      Copy to Clipboard Toggle word wrap
  3. 检查 Ray 集群资源:

    1. 单击 Search,然后从 Resources 列表中选择 RayCluster
    2. 选择 Ray 集群资源,然后点 YAML 选项卡。
    3. 检查 status.conditions.message 字段中的文本。
  4. 检查集群队列资源:

    1. 单击 Search,然后从 Resources 列表中选择 ClusterQueue
    2. 检查集群队列配置,以确保您请求的资源在为项目定义的限值内。
    3. 减少请求的资源,或联系您的管理员请求更多资源。

6.2. 我的 Ray 集群处于失败状态

问题

您可能没有足够的资源。

诊断

Ray 集群 head pod 或 worker pod 没有运行。创建 Ray 集群时,它最初会进入 失败状态。这个失败状态通常在协调过程完成并且 Ray 集群 pod 正在运行后解决。

解决方案

如果失败的状态仍然存在,请完成以下步骤:

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 单击 Search,然后从 Resources 列表中选择 Pod
  3. 点 pod 名称打开 Pod 详情页面。
  4. Events 选项卡,并查看 pod 事件以确定问题的原因。
  5. 如果您无法解决这个问题,请联系您的管理员以请求帮助。

问题

运行 cluster.apply () 命令后,会显示以下错误:

ApiException: (500)
Reason: Internal Server Error
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Internal error occurred: failed calling webhook \"mraycluster.ray.openshift.ai\": failed to call webhook: Post \"https://codeflare-operator-webhook-service.redhat-ods-applications.svc:443/mutate-ray-io-v1-raycluster?timeout=10s\": no endpoints available for service \"codeflare-operator-webhook-service\"","reason":"InternalError","details":{"causes":[{"message":"failed calling webhook \"mraycluster.ray.openshift.ai\": failed to call webhook: Post \"https://codeflare-operator-webhook-service.redhat-ods-applications.svc:443/mutate-ray-io-v1-raycluster?timeout=10s\": no endpoints available for service \"codeflare-operator-webhook-service\""}]},"code":500}
Copy to Clipboard Toggle word wrap

诊断

CodeFlare Operator pod 可能没有运行。

解决方案

请联系您的管理员以请求帮助。

问题

运行 cluster.apply () 命令后,会显示以下错误:

ApiException: (500)
Reason: Internal Server Error
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Internal error occurred: failed calling webhook \"mraycluster.kb.io\": failed to call webhook: Post \"https://kueue-webhook-service.redhat-ods-applications.svc:443/mutate-ray-io-v1-raycluster?timeout=10s\": no endpoints available for service \"kueue-webhook-service\"","reason":"InternalError","details":{"causes":[{"message":"failed calling webhook \"mraycluster.kb.io\": failed to call webhook: Post \"https://kueue-webhook-service.redhat-ods-applications.svc:443/mutate-ray-io-v1-raycluster?timeout=10s\": no endpoints available for service \"kueue-webhook-service\""}]},"code":500}
Copy to Clipboard Toggle word wrap

诊断

Kueue pod 可能没有运行。

解决方案

请联系您的管理员以请求帮助。

6.5. 我的 Ray 集群没有启动

问题

运行 cluster.apply () 命令后,在运行 cluster.details () 命令或 cluster.status () 命令时,Ray 集群会保持 Starting 状态,而不是更改为 Ready 状态。没有创建 pod。

诊断

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 检查工作负载资源:

    1. 单击 Search,然后从 Resources 列表中选择 Workload
    2. 选择使用 Ray 集群资源创建的工作负载资源,然后点 YAML 选项卡。
    3. 检查 status.conditions.message 字段中的文本,它提供 Starting 状态下的原因。
  3. 检查 Ray 集群资源:

    1. 单击 Search,然后从 Resources 列表中选择 RayCluster
    2. 选择 Ray 集群资源,然后点 YAML 选项卡。
    3. 检查 status.conditions.message 字段中的文本。

解决方案

如果您无法解决这个问题,请联系您的管理员以请求帮助。

问题

运行 cluster.apply () 命令后,会显示以下错误:

Default Local Queue with kueue.x-k8s.io/default-queue: true annotation not found please create a default Local Queue or provide the local_queue name in Cluster Configuration.
Copy to Clipboard Toggle word wrap

诊断

没有定义默认本地队列,且集群配置中没有指定本地队列。

解决方案

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 单击 Search,然后从 Resources 列表中选择 LocalQueue
  3. 使用以下方法之一解决这个问题:

    • 如果本地队列存在,将其添加到集群配置中,如下所示:

      local_queue="<local_queue_name>"
      Copy to Clipboard Toggle word wrap
    • 如果没有本地队列,请联系您的管理员请求协助。

问题

运行 cluster.apply () 命令后,会显示以下错误:

local_queue provided does not exist or is not in this namespace. Please provide the correct local_queue name in Cluster Configuration.
Copy to Clipboard Toggle word wrap

诊断

为集群配置中的本地队列指定不正确的值,或者定义了不正确的默认本地队列。指定的本地队列不存在,或者存在于不同的命名空间中。

解决方案

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 单击 Search,然后从 Resources 列表中选择 LocalQueue
  3. 使用以下方法之一解决这个问题:

    • 如果存在本地队列,请确保在集群配置中正确拼写本地队列名称,并且集群配置中的 namespace 值与您的项目名称匹配。如果您没有在集群配置中 指定命名空间 值,则会在当前项目中创建 Ray 集群。
    • 如果没有本地队列,请联系您的管理员请求协助。

6.8. 我无法创建 Ray 集群或提交作业

问题

运行 cluster.apply () 命令后,会显示类似于以下错误的错误:

RuntimeError: Failed to get RayCluster CustomResourceDefinition: (403)
Reason: Forbidden
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"rayclusters.ray.io is forbidden: User \"system:serviceaccount:regularuser-project:regularuser-workbench\" cannot list resource \"rayclusters\" in API group \"ray.io\" in the namespace \"regularuser-project\"","reason":"Forbidden","details":{"group":"ray.io","kind":"rayclusters"},"code":403}
Copy to Clipboard Toggle word wrap

诊断

笔记本代码的 TokenAuthentication 部分中没有指定正确的 OpenShift 登录凭证。

解决方案

  1. 找出正确的 OpenShift 登录凭证,如下所示:

    1. 在 OpenShift 控制台标头中,单击您的用户名,再单击 Copy login command
    2. 在打开的新标签页中,以您要使用的凭据的用户身份登录。
    3. 单击 Display Token
    4. 带有此令牌部分的 Log in 中,复制 tokenserver 值。
  2. 在笔记本代码中,指定复制的 令牌和 服务器 值,如下所示:

    auth = TokenAuthentication(
        token = "<token>",
        server = "<server>",
        skip_tls=False
    )
    auth.login()
    Copy to Clipboard Toggle word wrap

6.9. Kueue 置备的 pod 在拉取前终止

问题

在将所有工作负载 pod 标记为置备并运行前,Kueue 会等待一段时间。默认情况下,Kue 会等待 5 分钟。如果 pod 镜像非常大,且仍然在 5 分钟等待期限后被拉取,Kue 会失败并终止相关的 pod。

诊断

  1. 在 OpenShift 控制台中,从 Project 列表中选择您的项目。
  2. 单击 Search,然后从 Resources 列表中选择 Pod
  3. 单击 Ray head pod 名称,以打开 pod 详情页面。
  4. Events 选项卡,并查看 pod 事件来检查镜像拉取是否已成功完成。

解决方案

如果 pod 需要超过 5 分钟才能拉取镜像,请联系您的管理员请求协助。

法律通告

Copyright © 2025 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部