3. 集群用户指南#

本指南旨在为集群用户提供在 NVIDIA DGX™ Cloud 上运行作业和开发工作流程所需的信息。

集群所有者和管理员的信息可以在NVIDIA DGX Cloud Slurm 集群管理指南中找到

NVIDIA DGX Cloud Slurm 入门快速入门指南为集群所有者、集群管理员和集群用户提供了开始使用 DGX Cloud 集群所需的信息。

3.1. NVIDIA DGX Cloud 概述#

NVIDIA DGX Cloud 是一个面向企业开发人员的 AI 平台,针对生成式 AI 的需求进行了优化。

DGX Cloud Stack Diagram

DGX Cloud 提供了一个集成的、全栈的解决方案,与领先的云合作伙伴共同设计,将其一流的架构与最新的 NVIDIA AI 技术(跨加速计算、网络结构和软件)集成,并提供直接访问 NVIDIA AI 专家的途径。

DGX Cloud 包括 NVIDIA AI Enterprise,提供加速数据科学库、优化的框架和预训练模型,使开发人员能够快速轻松地交付生产就绪的 AI。

3.2. 您的集群概述#

DGX Cloud 集群包括以下已配置和配置好的组件以供使用

  • 头(管理)节点

  • 登录节点

  • CPU 工作节点

  • GPU 工作节点

  • 共享 NFS 存储

  • 共享高性能 Lustre 存储

DGX Cloud Slurm Architecture Diagram

每个可用组件的确切配置和容量是根据入门流程中指定的具体要求定制的。

Slurm 工作负载管理工具作为集群的主要界面提供给熟悉 HPC 调度程序并希望直接访问底层系统的用户。

Slurm 实施由 NVIDIA Base Command Manager 部署和配置,并利用 PyxisEnroot 作为容器插件和运行时。

客户可以进一步修改和定制通过 Base Command Manager (BCM) 进行的集群配置和 Slurm 配置,以满足特定的用例。

有关 BCM 的更多信息,请参阅 BCM 文档

有关 Slurm 的更多信息,请参阅 Slurm 快速入门指南

3.3. 访问您的 DGX Cloud 集群#

注意

以下部分假设您的集群管理员已与您合作创建了集群用户。如果您还没有用于登录集群的管理员用户和 SSH 密钥对,请联系您的集群管理员以开始使用。

3.3.1. DGX Cloud 访问方法#

作为用户,有两种连接选项可用于访问 DGX Cloud 环境。集群仅公开端口 22 访问,因此端口 22 以外的所有端口访问均通过 SSH 端口转发完成。

  • 登录节点:两个登录节点可通过公共互联网从您的集群管理员定义的网络地址访问,使用已在 DGX Cloud 部署中为您配置的用户帐户注册的公共 SSH 密钥。

  • 用户门户:可通过 SSH 隧道连接到端口 8081 以连接到任一登录节点的 Web 界面,称为用户门户。访问用户门户的说明可以在本指南的用户门户部分找到。

注意

访问登录节点的地址应由您的集群管理员提供给您。

3.3.2. 访问登录节点#

注意

非 root 用户不允许 SSH 连接到头节点 - 他们只能 SSH 连接到集群的 Slurm 登录节点。

要访问 Slurm 登录节点,您需要创建一个用户帐户,并在您的系统中拥有与该用户关联的匹配的公共 SSH 密钥对。您的集群管理员或所有者需要为您创建此用户帐户并附加您的 SSH 密钥对。

有关创建 SSH 密钥对的说明,请参见下面的创建 SSH 密钥对以发送给您的管理员进行用户创建部分。 更多信息,请参阅NVIDIA DGX Cloud 集群管理指南

3.3.2.1. 使用 SSH 密钥登录#

集群用户将拥有对登录节点的 SSH 访问权限。 集群用户还可以从登录节点访问用户门户。

要访问登录节点,请按照以下步骤操作

  1. 从您的集群管理员处获取登录节点地址。

  2. 使用集群管理员创建的用户帐户登录

    ssh -i /path/to/ssh_cert <cluster-user>@ip-addr-of-login-node
    

3.3.2.2. 更新密码#

您将使用 SSH 密钥访问登录节点。但是,要访问用户门户的 Web 界面,您将使用密码。

您的集群管理员应该已为您提供了一个默认帐户密码。要在使用 SSH 密钥登录后更改密码,请使用 passwd 命令

passwd

记下您的新密码。如果您不记得密码,请咨询集群管理员以重置密码。

3.3.2.3. 创建 SSH 密钥对以发送给您的管理员进行用户创建#

为了让集群管理员或所有者创建您的用户帐户,您需要创建一个 SSH 密钥对并将公钥发送给管理员。请按照以下步骤操作。

  1. 打开 Linux 终端,然后运行以下命令,确保将 <cluster-user>your_email@example.com 更改为您自己的特定信息

    ssh-keygen -t ed25519 -b 4096 -f ~/.ssh/<cluster-user>-ed25519-dgxc -C "your_email@example.com"
    
  2. 运行以下命令以输出公钥的内容。复制运行此命令的输出,并将其发送给您的集群管理员或所有者

    cat ~/.ssh/<cluster-user>-ed25519-dgxc.pub
    

3.4. 在您的 DGX Cloud 集群中工作概述#

3.4.1. 主目录#

您的主目录是您登录 DGX Cloud Slurm 集群时的默认文件路径。其形式为 /home/demo-user

在 DGX Cloud Slurm 集群中,所有用户主目录都位于网络文件系统 (NFS) 上。这使得集群中的所有节点在您运行作业时可以同时访问相同的数据。

网络文件系统意味着您可以

  • 编写一次脚本并在多个节点上同时运行。

  • 从存储库克隆一次,并使存储库在整个集群上可用

  • 使用共享目录来记录来自多个生产者的作业输出

  • 在任何可用的系统上运行您的代码 - 数据可用性不依赖于任何一个系统。

所有用户数据都通过文件系统权限隔离,这意味着 user-a 只能读取和写入 /home/user-a 中的数据,而不能读取和写入 /home/user-b 中的数据。但是,如果主文件系统负载过重,用户可以相互影响。

3.4.1.1. 主目录的最佳实践#

在使用主目录时,需要牢记一些最佳实践

  • 主目录存储非常适合少量数据,尤其是代码、脚本和配置文件。

  • 主目录存储也可以接受用于日志文件,但对于将增长到很大的日志文件和/或经常写入的日志文件,应考虑替代存储。

  • 主目录存储为您的主目录配置了配额 - 如果您的管理员没有与您的 NVIDIA TAM 协作指定不同的配额,则默认的每用户配额为 10 GB。

对于数据集和更密集的存储 IO 用例,提供了并行文件系统。以下部分讨论了关键信息。

3.4.1.2. 主目录配额管理#

您可能会耗尽配额 - 发生这种情况时,类似以下消息将出现在日志文件或您的终端中

disk quota exceeded

要将任何其他数据写入您的主目录,您必须删除数据或将数据移动到 Lustre(这将在以下部分中进一步讨论)。

要调查您的主目录使用情况,可以将 du 命令与 sort 命令结合使用,以通过从最小到最大排序来识别主目录中的大文件。

1$ du -sh /home/demo-user/* | sort -h
24.0K        /home/demo-user/a-script.sh
34.0K        /home/demo-user/an-sbatch-file
48.0K        /home/demo-user/log.out
5226M        /home/demo-user/an-executable
67G          /home/demo-user/a-big-file

在上面显示的示例中,a-big-file 可能会导致默认配额为 10 GB 的配额问题。

要删除不再需要的文件,请使用 rm 命令。

rm a-big-file

要改为移动它,请使用 mv 命令。第二个参数是目标路径,在本例中是 demo-user Lustre 暂存目录。

mv a-big-file /lustre/fs0/scratch/demo-user/

3.4.2. Lustre 共享文件系统目录#

作为 DGX Cloud 集群一部分提供的并行文件系统是 Lustre。在 DGX Cloud 集群中,Lustre 文件系统将挂载在 /lustre/fs0。这可以通过使用 df 命令并在 Mounted on 列中查找 /lustre/fs0 路径来查看

 1df -h
 2
 3Filesystem                Size  Used Avail Use% Mounted on
 4tmpfs                      63G  1.3M   63G   1% /run
 5/dev/sda1                 199G   14G  186G   7% /
 6tmpfs                      63G     0   63G   0% /dev/shm
 7tmpfs                     5.0M     0  5.0M   0% /run/lock
 8tmpfs                     4.0M     0  4.0M   0% /sys/fs/cgroup
 9/dev/sdb3                 4.4G  4.0G  404M  91% /cm/node-installer-ebs
1010.14.1.4:/bcm-cm-shared  1.0T  2.5G 1022G   1% /cm/shared
1110.14.1.4:/bcm-home       1.0T  308M  1.0T   1% /home
1210.14.2.9@tcp:/lustrefs    79T   87G   75T   1% /lustre/fs0
13tmpfs                      13G  4.0K   13G   1% /run/user/0

默认情况下,用户无法在 Lustre 文件系统内创建文件或目录 - 管理员必须创建一个用户有权访问的专用目录,这通常称为暂存目录。DGX Cloud 文档建议将 /lustre/fs0/scratch 目录用于这些用户特定的目录。

您可以使用 ls 命令检查集群管理员是否已为您的用户创建此目录,目标是 lustre/fs0/scratch 目录。

1ls /lustre/fs0/scratch/
2
3charlie  demo-user  alice  bob

如果您的用户名未出现在此目录中,或者没有将替代路径告知您,请联系您的集群管理员。

3.4.2.1. 访问共享目录#

此 Lustre 文件系统路径,类似于 NFS 主目录,将在 DGX Cloud Slurm 集群的所有登录节点、CPU 节点和 GPU 节点上的相同位置 (/lustre/fs0) 可用。

3.4.2.2. 共享目录权限#

重要的是要理解,默认情况下,写入共享暂存目录的数据可能是公开可见的。您可以使用 ls -l 命令确认这一点。

1ls -l /lustre/fs0/scratch/
2total 40
3...
4drwxr-xr-x 9 demo-user      demo-user      4096 Apr 22 10:25 demo-user
5...

此输出指示有关 /lustre/fs0/scratch/demo-user 目录的以下信息

  • 拥有该目录的用户(在本例中为 demo-user)对其具有读取、写入和执行权限。

  • 拥有该目录的组(demo-user 组)对其具有读取和执行权限。

  • 任何有权访问 Lustre 文件系统的用户都对其具有读取和执行权限。

3.4.2.3. 限制文件和目录权限#

敏感信息应具有更严格的权限。虽然应用程序可以管理这一点,但您也可以使用 chmod 工具调整权限。

要撤销 /lustre/fs0/scratch/demo-user 目录中给定文件的其他用户的读取和写入权限,demo-user 可以执行以下操作

chmod o-rw /lustre/fs0/scratch/demo-user/example-file

其中 o 指的是其他用户,- 表示应删除这些权限。这将导致最终的权限集完全为空,表明任意用户缺乏读取、写入和执行权限。

1ls -l /lustre/fs0/scratch/demo-user/example-file
2-rw-rw---- 1 demo-user demo-user 0 Apr 29 14:44 /lustre/fs0/scratch/demo-user/example-file

要限制对整个目录的访问,请使用相同的策略

chmod o-rw /lustre/fs0/scratch/demo-user/private

此操作会为目录生成类似的输出。

1ls -l /lustre/fs0/scratch/demo-user/
2total 1024
3...
4drwxrwx---  2 demo-user demo-user   4096 Apr 29 14:47 private
5...

3.4.2.4. 查看配额#

管理员可以在特定目录(例如用户的专用暂存目录)中设置用户配额。用户可以使用 lfs quota 命令检查自己的配额

 1lfs quota -u demo-user -v /lustre/fs0/scratch/demo-user
 2
 3Disk quotas for usr demo-user (uid 1004):
 4    Filesystem  kbytes   quota   limit   grace   files   quota   limit   grace
 5  /lustre/fs0/scratch/demo-user/
 6                      4  104857600 104857600       -       1   10000   11000       -
 7  lustrefs-MDT0000_UUID
 8                      4*      -       4       -       1*      -       1       -
 9  lustrefs-OST0000_UUID
10                      0       -       0       -       -       -       -       -
11  lustrefs-OST0001_UUID
12                      0       -       0       -       -       -       -       -
13  lustrefs-OST0002_UUID
14                      0       -       0       -       -       -       -       -
15  lustrefs-OST0003_UUID
16                      0       -       0       -       -       -       -       -
17  lustrefs-OST0004_UUID
18                      0       -       0       -       -       -       -       -

3.4.2.5. 最佳实践#

使用 Lustre 时,您应注意以下最佳实践

  • 尽可能避免访问文件系统元数据。诸如 ls -l 之类的命令应以特定文件而不是整个目录为目标,以最大程度地减少 Lustre 元数据目标的负载。

  • 避免在单个目录中拥有大量文件(大约 1000 个或更多)。将它们拆分为多个子目录以最大程度地减少目录争用。

  • 避免访问 Lustre 上的小文件(1 MB 或更小)- 尽可能将小型配置文件保留在您的 /home 目录中,将许多小文件聚合到一个较大的文件中,或在计算作业期间在 GPU 系统上本地缓存小文件(注意缓存到这些系统的数据在作业完成后将不会持久存在)。

  • 尽可能避免访问 Lustre 上的可执行文件 - 如果 Lustre 文件系统遇到高负载,则可执行文件可能会暂时不可用,从而导致损坏。

3.4.3. 用户门户#

DGX Cloud 用户门户是一个 GUI,它向您显示集群中工作负载的仪表板。在门户中,您可以查看有关作业队列、作业历史记录和集群节点状态的信息。

3.4.3.1. 登录用户门户#

您可以使用以下步骤登录用户门户。

  1. 使用此命令创建返回到本地桌面主机的 SSH 隧道

    ssh <cluster-user>@ip-addr-of-login-node -L 8081:master:8081
    
  2. 从您的 Web 浏览器导航到 https://127.0.0.1:8081/userportal/

  3. 在浏览器中,添加您的集群用户名和密码以登录用户门户。

    注意

    这与您在访问登录节点部分中用于通过 SSH 连接的用户相同。

    Portal Login Page

    注意

    首次使用浏览器登录集群门户时,默认集群配置中会显示有关站点证书不受信任的警告。可以安全地接受此警告。

3.4.3.3. 监控#

在用户门户的右上角,用户可以访问“监控”页面,该页面最初在页面的仪表板部分显示两个空白绘图面板。可以将可测量项从页面左侧的可测量项导航树拖放到面板中。树可以部分或完全展开。

可以使用过滤器从可见的可测量项中进行选择。例如,展开树后,可以通过在过滤器中使用关键字“occupation”来查找集群占用率的可测量项。然后可以将可测量项从仍然可见的选项中拖出。

可以通过单击仪表板页面面板部分中的“添加新小部件”选项(+ 按钮)将额外的绘图面板小部件添加到页面。可以通过单击页面仪表板选项卡部分中的“添加新仪表板”选项(+ 按钮)将新的仪表板选项卡添加到页面。

Monitoring Page

3.4.3.4. 核算和报告#

在用户门户的右上角,用户可以访问“核算和报告”页面,该页面可用于通过使用 PromQL 查询来显示资源使用情况。向导允许创建每个用户和每个帐户的资源报告,然后可以将这些报告分组并组织到各个选项卡中。报告可以保存并导出为 CSV 或 Microsoft Excel 格式的下载。

Account-Report

3.5. 设置以运行作业#

3.5.1. 加载 Slurm 模块#

您的集群管理员应已配置您的用户帐户以在登录时自动加载 Slurm 模块。但是,如果您需要手动加载 Slurm 模块,请在继续操作并运行任何 Slurm 命令之前,运行以下命令。

module load slurm

要配置您的用户帐户以自动加载 Slurm 模块,请运行以下命令,然后注销,然后重新登录到登录节点。

module initadd slurm

3.5.2. 基本 Slurm 命令#

本节介绍一些常用命令,这些命令可用于与 DGX Cloud 集群上的 Slurm 进行交互。

3.5.2.1. sinfo#

要查看集群中的所有节点及其当前状态,请 SSH 连接到集群的 Slurm 登录节点并运行 sinfo 命令

1sinfo
2
3PARTITION  AVAIL  TIMELIMIT  NODES  STATE  NODELIST
4cpuq       up     infinite    2     idle   cpu[001-002]
5defq*      up     infinite   64     idle   gpu[001-064]

在此示例中,有 64 个可用节点,全部处于 idle 状态。

当节点在使用中时,其状态将从 idle 更改为 alloc

1sinfo
2
3PARTITION  AVAIL  TIMELIMIT  NODES  STATE  NODELIST
4cpuq       up     infinite    2     idle   cpu[001-002]
5defq*      up     infinite   1      alloc  gpu001
6defq*      up     infinite   63     idle   gpu[002-064]

其他可能的节点状态包括 drain(表示节点当前已关闭)、mix(表示节点部分使用中)和 maint(表示节点因维护而关闭)。

注意

根据您的集群配置的详细信息,您的特定分区可能会有所不同。例如,CPU 节点可能与 GPU 节点位于相同的 defq 分区中,或者可能存在和/或已创建其他分区。

3.5.2.2. srun#

在 Slurm 上运行作业的最简单方法是使用 srun 并指定节点数和参数以运行作业。以下命令在两个节点上运行作业并打印出每个节点的主机名

1srun --nnodes=2 --nproc-per-node=1 hostname
2
3gpu001
4gpu002

srun 是一个阻塞命令,它阻止用户在当前终端会话中运行其他命令,直到作业完成或取消。

3.5.2.3. sbatch#

要运行在后台排队和运行的非阻塞作业,可以使用 sbatch 脚本。sbatch 脚本是一个 bash 脚本,它允许将其他功能和代码包装在作业提交周围。所有 sbatch 脚本必须至少有一个 srun 命令,该命令在文件中启动作业。以下是 sbatch 脚本的示例

1#!/bin/bash
2#SBATCH --exclusive
3#SBATCH --gpus-per-node=8
4#SBATCH --nodes=2
5#SBATCH --ntasks-per-node=4
6
7srun python3 trainer.py

要运行脚本,请使用 sbatch <filename>,其中 <filename> 是上面 bash 文件的名称。此作业将在每个节点上运行 python3 trainer.py,并分配 2 个节点,每个节点运行 8 个 GPU 来运行作业。

3.5.2.4. squeue#

要查看集群中当前正在运行和在队列中的所有作业,请运行 squeue。以下示例显示了一个 id 1234 的作业,该作业在 64 个节点上运行 30 分钟,节点为 gpu001-gpu064。其他两个作业 12351236 当前在队列中等待可用资源。一旦作业 1234 完成并释放资源,两个待处理的作业都应该被分配

1squeue
2
3JOBID  PARTITION      NAME       USER  ST  TIME   NODES  NODELIST(REASON)
41235   defq       llm-train   demo-use PD   0:00   2     (Dependency)
51236   defq       llm-ft      demo-use PD   0:00   2     (Dependency)
61234   defq       trainer     demo-use  R  30:00   64    gpu[001-064]

3.5.2.5. scancel#

要取消正在运行的作业,请运行 scancel,后跟作业 ID。这将向作业发送信号以终止,并且它将有一段时间来正常退出。

要取消 ID 为 1234 的作业,您将运行

scancel 1234

要验证它是否已取消,请检查队列。CG 的状态表示作业正在完成

1squeue
2
3JOBID  PARTITION      NAME       USER  ST  TIME   NODES  NODELIST(REASON)
41235   defq       llm-train   demo-use PD   0:00   2     (Dependency)
51236   defq       llm-ft      demo-use PD   0:00   2     (Dependency)
61234   defq       trainer     demo-use CG  30:00   64    gpu[001-064]

3.5.2.6. scontrol show#

scontrol show 命令允许您查看 Slurm 集群不同部分的更多详细信息。一些更常见的领域是显示有关特定节点或作业详细信息的更多信息。

要查看有关特定节点的信息,例如当前状态、可用资源、正常运行时间等,请运行 scontrol show node <node name>

 1scontrol show node gpu001
 2
 3NodeName=gpu001 Arch=x86_64 CoresPerSocket=62
 4CPUAlloc=0 CPUEfctv=248 CPUTot=248 CPULoad=2.55
 5AvailableFeatures=location=us-chicago-1
 6ActiveFeatures=location=us-chicago-1
 7Gres=gpu:8(S:0-1)
 8NodeAddr=gpu001 NodeHostName=gpu001 Version=23.02.5
 9OS=Linux 5.15.0-1032-oracle #38~20.04.1-Ubuntu SMP Thu Mar 23 20:47:49 UTC 2023
10RealMemory=1878738 AllocMem=0 FreeMem=1945682 Sockets=2 Boards=1
11State=IDLE ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
12Partitions=batch
13BootTime=2024-02-21T12:31:03 SlurmdStartTime=2024-03-08T09:28:09
14LastBusyTime=2024-03-08T13:37:46 ResumeAfterTime=None
15CfgTRES=cpu=248,mem=1878738M,billing=60,gres/gpu=8
16AllocTRES=
17CapWatts=n/a
18CurrentWatts=0 AveWatts=0
19ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s

此外,使用 scontrol show job <job ID> 查看特定作业的详细信息,包括当前状态和状态原因、提交时间、日志文件和请求

 1scontrol show job 1234
 2
 3JobId=1234 JobName=trainer
 4UserId=jdoe(1004) GroupId=jdoe(30) MCS_label=N/A
 5Priority=50 Nice=0 Account=general QOS=normal
 6JobState=RUNNING Reason=None Dependency=(null)
 7Requeue=1 Restarts=0 BatchFlag=1 Reboot=0 ExitCode=0:0
 8RunTime=00:24:15 TimeLimit=04:00:00 TimeMin=N/A
 9SubmitTime=2024-03-08T13:17:23 EligibleTime=2024-03-08T13:17:23
10AccrueTime=2024-03-08T13:17:23
11StartTime=2024-03-08T13:20:39 EndTime=2024-03-08T17:20:39 Deadline=N/A
12SuspendTime=None SecsPreSuspend=0 LastSchedEval=2024-03-08T13:20:39 Scheduler=Main
13Partition=defq AllocNode:Sid=login-01
14ReqNodeList=(null) ExcNodeList=(null)
15NodeList=gpu[001-064]
16BatchHost=gpu[001-064]
17NumNodes=64 NumCPUs=64 NumTasks=4 CPUs/Task=16 ReqB:S:C:T=0:0:*:*
18ReqTRES=cpu=64,mem=1000G,node=1,billing=25,gres/gpu=8
19AllocTRES=cpu=64,mem=1000G,node=1,billing=25,gres/gpu=8
20Socks/Node=* NtasksPerN:B:S:C=4:0:*:* CoreSpec=*
21MinCPUsNode=64 MinMemoryNode=1000G MinTmpDiskNode=0
22Features=(null) DelayBoot=00:00:00
23OverSubscribe=OK Contiguous=0 Licenses=(null) Network=(null)
24Command=trainer.sh
25WorkDir=/lustre/fs0/scratch/demo-user
26StdErr=/lustre/fs0/scratch/demo-user/slurm-%N-%J.out
27StdIn=/dev/null
28StdOut=/lustre/fs0/scratch/demo-user/slurm-%N-%J.out
29Power=
30TresPerNode=gres:gpu:4
31MailUser=

3.5.3. 设置 NGC 集成#

3.5.3.1. 访问您的 NGC 组织#

作为 DGX Cloud 订阅的一部分,您的组织已获得 NVIDIA NGC 的访问权限,并启用了私有注册表和 NVIDIA AI Enterprise 订阅。

您的集群所有者将能够邀请您加入 NGC。收到邀请后,请按照电子邮件中的说明设置您的帐户。

3.5.3.2. 设置您的 NGC API 密钥#

要生成您的 NGC API 密钥,请按照以下步骤操作

  1. 转到 ngc.nvidia.com 并登录。

  2. 单击屏幕右上角的个人资料,然后单击“设置”按钮。

  3. 单击“生成个人密钥”,并在打开的新表单中生成密钥。将显示的密钥保存在安全的地方,因为密钥只会显示一次,并且是未来步骤所必需的。

3.5.3.3. 设置您的 Enroot 配置文件#

生成 NGC API 密钥后,您必须将密钥放入配置文件中。当您运行作业时,这将用于通过 Enroot 进行身份验证。

按照以下步骤将您的 NGC API 密钥保存到配置文件中

  1. 在登录节点上运行以下命令

    1mkdir -p ~/.config/enroot
    2touch ~/.config/enroot/.credentials
    
  2. 打开 ~/.config/enroot/.credentials 并在文件中输入以下内容,将 <API KEY> 替换为您的 NGC 密钥。

    machine nvcr.io login $oauthtoken password <API KEY>
    
  3. 保存文件。

3.5.3.4. 安装 NGC CLI#

NGC CLI 通过提供上传和下载各种工件(例如训练的模型)的命令,简化了与 DGX Cloud 私有注册表的交互。

要访问最新版本的 NGC CLI,请导航到 CLI 安装页面。以下文档基于 3.41.4 版本。

  1. 从登录节点,通过 wget 下载 NGC CLI 工具。

    wget --content-disposition https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions/3.41.4/files/ngccli_linux.zip -O ngccli_linux.zip && unzip ngccli_linux.zip
    
  2. 检查二进制文件的 md5 哈希值,以确保其未损坏。

    find ngc-cli/ -type f -exec md5sum {} + | LC_ALL=C sort | md5sum -c ngc-cli.md5
    
  3. 您还可以检查二进制文件的 SHA256 哈希值。

    sha256sum ngccli_linux.zip
    

    对于 3.41.4 版本,应返回以下值。

    2c86681048ab8e2980bdd6aa6c17f086eff988276ad90a28f1307b69fdb50252
    
  4. 当确认该工具已准备好使用时,使 NGC CLI 可执行并将其添加到用户的 PATH

    chmod u+x ngc-cli/ngc; echo "export PATH=\"\$PATH:$(pwd)/ngc-cli\"" >> ~/.bash_profile && source ~/.bash_profile
    
  5. 配置 NGC CLI。

    ngc config set
    

    在每个步骤输入请求的信息。最重要的字段是请求的 API 密钥,它与用于 Enroot 配置的值相同。

    Enter API key [no-apikey]. Choices: [<VALID_APIKEY>, 'no-apikey']: <API KEY>
    

完成这些步骤后,您可以使用来自登录节点或 Slurm 作业的 NGC CLI 上传和下载来自您的私有注册表的工件。

3.5.3.5. 运行 Hello World 作业#

将 NGC 密钥添加到 Enroot 配置文件后,即可使用 NGC 容器运行简单的作业。以下命令将针对 PyTorch 容器启动单节点作业,并在容器内打印 PyTorch 版本。

srun --container-image nvcr.io/nvidia/pytorch:24.09-py3 -N1 bash -c "python3 -c 'import torch; print(torch.__version__)'"

3.5.4. 将容器下载到集群上#

在您的 DGX Cloud 集群中,您可以将容器镜像保存到 Lustre 共享存储目录中,以避免重复下载相同的镜像。当处理大型多节点作业或重复性作业运行时,这尤其有用。

DGX Cloud 集群使用 Enroot 作为容器运行时,它可以将容器镜像保存为 squash 文件。

3.5.4.1. 从 NGC 容器创建 Squash 文件#

Squash 文件是 Enroot 使用的 NGC 容器的压缩表示形式。

以下步骤从 NGC 容器创建 squash 文件

  1. 在您的 Lustre 目录中,创建一个用于存放 squash 文件的目录(如果尚不存在),然后进入该目录。

    1mkdir /lustre/fs0/scratch/demo-user/sqsh-files
    2cd /lustre/fs0/scratch/demo-user/sqsh-files
    
  2. 在终端中,运行以下命令

    srun -N 1 --pty --partition cpuq --exclusive --job-name "enroot-import:interactive" bash
    

    您现在应该在 CPU 节点上运行,位于新创建的 sqsh-files 目录中。Shell 提示符将指示这一点

    demo-user@cpu001:/lustre/fs0/scratch/demo-user/sqsh-files$
    
  3. 使用 enroot 导入目标容器 - 在本例中,我们从 NGC 导入 NeMo Framework 容器。

    enroot import 'docker://$oauthtoken@nvcr.io#nvidia/nemo:24.01.framework'
    

    以下是具有 32 个核心的 CPU 节点的输出 - 输出可能因部署而略有不同。

     1[INFO] Querying registry for permission grant
     2[INFO] Authenticating with user: $oauthtoken
     3[INFO] Using credentials from file: /home/demo-user/.config/enroot/.credentials
     4[INFO] Authentication succeeded
     5[INFO] Fetching image manifest list
     6[INFO] Fetching image manifest
     7[INFO] Downloading 74 missing layers... 100% 74:0=0s 9ee9f649846387c87376a6ed73d7938fb7ebc0de62ae5e6b5285643682dc12c2
     8[INFO] Extracting image layers... 100% 78:0=0s a486411936734b0d1d201c8a0ed8e9d449a64d5033fdc33411ec95bc26460efb
     9[INFO] Converting whiteouts... 100% 78:0=0s a486411936734b0d1d201c8a0ed8e9d449a64d5033fdc33411ec95bc26460efb
    10[INFO] Creating squashfs filesystem... Parallel mksquashfs: Using 32 processors Creating 4.0 filesystem on /lustre/fs0/scratch/demo-user/sqsh-files-cpu/nvidia+nemo+24.01.framework.sqsh, block size 131072.
    11[=============================================================================================================================================================================================\] 594940/594940 100% Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
    12uncompressed data, uncompressed metadata, uncompressed fragments,         uncompressed xattrs, uncompressed ids   duplicates are not removed Filesystem size 34918700.97 Kbytes (34100.29 Mbytes)
    1399.98% of uncompressed filesystem size (34924117.67 Kbytes) Inode table size 13604323 bytes (13285.47 Kbytes)     100.00% of uncompressed inode table size (13604323 bytes) Directory table size 12122240 bytes (11838.12 Kbytes)
    14100.00% of uncompressed directory table size (12122240 bytes) No duplicate files removed Number of inodes 387307 Number of files 345979 Number of fragments 21833 Number of symbolic links 1737 Number of device nodes 0 Number of fifo nodes 0 Number of socket nodes 0 Number of directories 39591
    15Number of ids (unique uids + gids) 1 Number of uids 1     root (0) Number of gids 1       root (0)
    
  4. 结束交互式作业。

    exit
    

后续的 srun 命令现在可以使用此 squash 文件,而不是从 NGC 拉取容器。此示例修改了一个交互式作业以使用刚刚下载的 squash 文件

srun -N 1 --pty --gpus 8 --container-image /lustre/fs0/scratch/demo-user/sqsh-files/nvidia+nemo+24.01.framework.sqsh --exclusive --job-name "use-squash-file:interactive" bash

3.6. 运行示例作业#

3.6.1. 示例单节点批处理作业#

本节更详细地介绍了如何在 DGX Cloud 上使用 Slurm 运行单节点批处理作业。示例作业在单个节点内的多个 GPU 上运行。

3.6.1.1. 基本 srun 命令#

使用 Pyxis 和 Enroot 来利用 NGC 容器的 Slurm srun 命令具有以下结构

srun --nodes 1 --job-name example-srun-job --exclusive --gpus-per-node 8 --mpi=pmix --container-mounts /lustre/fs0 --container-mount-home --container-mounts /cm/shared --container-image nvcr.io/nvidia/pytorch:24.09-py3 --partition defq <command>

其中参数为

  • nodes - 为支持此作业而启动的节点数。

  • job-name - 定义作业名称的任意字符串。

  • exclusive - 请求对 Slurm 为此作业提供的节点的独占访问权限。在此作业的持续时间内,提供的节点上不会运行其他作业。

  • gpus-per-node - 从每个提供的节点请求的 GPU 数量。

  • mpi - 指定此作业要使用的 MPI 版本。 pmix 值通常是正确的值 - 要了解有关可用选项的更多信息,请访问 SchedMD 文档。

  • container-mounts - 指定要从主机映射到作为该作业一部分的每个节点上的作业中的路径。可以指定此标志的多个实例 - 每个期望的路径一个。在上面的示例中,路径将镜像到作业中,就像它在主机上存在一样 - 要指定不同的映射,参数将更改为 /host-path:/new-job-path 格式。在上面的示例中,指定了 Lustre 文件系统路径和共享 NFS 路径 - 要了解有关 Lustre 路径用途的更多信息,请参阅 DGX Cloud Lustre 文件系统概述。共享 NFS 路径将在本节稍后解释。

  • container-mount-home - 将用户的主目录挂载到生成的容器化环境中,路径为其 /home/username,位于作为该作业一部分的每个节点上。否则,在 DGX Cloud 中配置的利用 Enroot 的作业中,主目录不会自动挂载。

  • container-image - 指定将通过 Enroot 用作作业开始后的作业主机环境的 NGC 容器。对于公共 NGC 容器,参数格式为 nvcr.io#nvidia/container:version;如果使用私有注册表容器,则格式为 nvcr.io#org/container:versionnvcr.io#org/team/container:version

  • partition - 指定从中选择节点的队列。默认情况下,将使用 defq 队列。

3.6.1.2. 环境变量#

在每个主机上的 /etc/enroot/environ.d/ 目录中的多个文件中编码了在给定集群中跨多个节点实现目标性能所需的所有环境变量。

有关更多详细信息,请查看 环境变量。要指定其他环境变量,请考虑创建一个名为 env-vars.sh 的文件,并在其中定义任何必要的其他变量。

然后,您可以从脚本中使用 source 在作业中指定这些新的环境变量。

source env-vars.sh

3.6.1.3. 运行 srun 命令#

以下示例运行基于 GPU 的作业。

  1. 使用您选择的文本编辑器在 $HOME/hostname.sh 创建一个脚本,内容如下

    #!/bin/bash
    
    srun --nodes 1 --job-name example-srun-job --exclusive --gpus-per-node 8 --mpi=pmix --container-image nvcr.io/nvidia/pytorch:24.09-py3 --partition defq hostname
    
  2. 通过运行以下命令使脚本可执行

    chmod +x hostname.sh
    
  3. 您现在可以运行该脚本

    ./hostname.sh
    

命令输出(sdout 和 sderr)将从提交上述脚本的终端输出到终端。除非在后台使用 & 运行,否则 srun 的使用是阻塞的。

预期的输出示例将显示作业运行所在系统的hostname(Slurm 负责为您确定),例如以下内容

1pyxis: importing docker image: nvcr.io#nvidia/pytorch:24.02-py3
2pyxis: imported docker image: nvcr.io#nvidia/pytorch:24.02-py3
3gpu001

3.6.1.4. 运行 sbatch 命令#

或者,可以使用 sbatch 提交作业

1#!/bin/bash
2#SBATCH --partition defq --nodes 1
3#SBATCH --exclusive
4#SBATCH --job-name=example-sbatch-job
5#SBATCH --gpus-per-node=8
6
7srun --mpi=pmix --container-image nvcr.io/nvidia/pytorch:24.09-py3 hostname

参数可以在 sbatch 脚本的顶部指定,也可以在各个命令中根据需要指定。 srun 命令可以在 sbatch 脚本中指定,如下所示。

要提交上面的脚本,请将文本保存到名为 hostname.sbatch 的文件中,并运行 sbatch hostname.sbatch。这将是非阻塞的,这意味着如果需要,可以立即将其他作业排队。

3.6.1.5. 查看 sbatch 日志文件#

与作业编号对应的日志文件将自动在运行 sbatch 的目录中创建,格式为 slurm-x.out。此文件名和路径是可配置的 - 有关这些选项和更多信息,请查阅 SchedMD 文档。

要在队列中或运行时检查作业的状态,可以使用 squeue 命令,如集群概述文档中所示

1squeue
2
3JOBID  PARTITION  NAME       USER  ST  TIME   NODES  NODELIST(REASON)
442     batch      example-s  jdoe  R   0:01   1     gpu001

3.6.1.6. SSH 访问计算节点#

在执行期间,拥有节点上活动作业的用户可以在必要或需要时 SSH 到该节点。

ssh gpu001

3.6.1.7. 访问节点上运行的容器#

在某些情况下,创建交互式终端以访问已通过 sbatch 启动的作业,或作为交互式作业一部分的辅助终端是有利的。要实现此目的,您需要通过 Enroot 访问作为作业一部分运行的容器。

  1. 要访问作为节点上作业一部分运行的容器,首先要确定哪个节点正在运行该作业。

    1$ squeue
    2JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
    3  517      defq example- demo-use  R       2:44      1 gpu002
    
  2. SSH 到列出的节点。

    ssh gpu002
    
  3. 使用 enroot list --fancy 命令生成节点上正在运行的容器列表。

    1$ enroot list --fancy
    2NAME         PID      COMM  STATE  STARTED  TIME        MNTNS       USERNS      COMMAND
    3pyxis_517.0  2351732  bash  S      May02    3-15:37:17  4026540834  4026540785  /usr/bin/bash -c <command>
    
  4. 复制目标容器的 PID 值,并将其用作 enroot exec 命令的参数。在容器内运行 bash 命令。

    enroot exec 2351732 bash
    

最终结果将是在目标容器内运行的交互式会话。

1$ enroot exec 2351732 bash
2bash: module: command not found
3demo-user@gpu002:/workspace$

3.7. 示例单节点交互式 Bash 作业#

可以使用以下 srun 命令启动交互式作业。要记住的关键参数是 --pty 标志,它允许作业在终端中交互式运行。

1srun -N 1 --pty \
2--container-image nvcr.io/nvidia/pytorch:24.09-py3 \
3--container-mounts "/lustre/fs0" \
4--gpus 8 \
5--exclusive \
6--job-name "my-job:interactive" \
7bash

Shell 现在应指示已连接到具有 8 个 GPU 的节点,可以通过运行 nvidia-smi 来确认。

 1demo-user@gpu003:/workspace$ nvidia-smi
 2
 3+-----------------------------------------------------------------------------------------+
 4| NVIDIA-SMI 550.54.15              Driver Version: 550.54.15      CUDA Version: 12.4     |
 5|-----------------------------------------+------------------------+----------------------+
 6| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
 7| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
 8|                                         |                        |               MIG M. |
 9|=========================================+========================+======================|
10|   0  NVIDIA A100-SXM4-80GB          On  |   00000001:00:00.0 Off |                    0 |
11| N/A   35C    P0             63W /  400W |       0MiB /  81920MiB |      0%      Default |
12|                                         |                        |             Disabled |
13+-----------------------------------------+------------------------+----------------------+
14|   1  NVIDIA A100-SXM4-80GB          On  |   00000002:00:00.0 Off |                    0 |
15| N/A   35C    P0             65W /  400W |       0MiB /  81920MiB |      0%      Default |
16|                                         |                        |             Disabled |
17+-----------------------------------------+------------------------+----------------------+
18|   2  NVIDIA A100-SXM4-80GB          On  |   00000003:00:00.0 Off |                    0 |
19| N/A   35C    P0             64W /  400W |       0MiB /  81920MiB |      0%      Default |
20|                                         |                        |             Disabled |
21+-----------------------------------------+------------------------+----------------------+
22|   3  NVIDIA A100-SXM4-80GB          On  |   00000004:00:00.0 Off |                    0 |
23| N/A   35C    P0             65W /  400W |       0MiB /  81920MiB |      0%      Default |
24|                                         |                        |             Disabled |
25+-----------------------------------------+------------------------+----------------------+
26|   4  NVIDIA A100-SXM4-80GB          On  |   0000000B:00:00.0 Off |                    0 |
27| N/A   35C    P0             62W /  400W |       0MiB /  81920MiB |      0%      Default |
28|                                         |                        |             Disabled |
29+-----------------------------------------+------------------------+----------------------+
30|   5  NVIDIA A100-SXM4-80GB          On  |   0000000C:00:00.0 Off |                    0 |
31| N/A   34C    P0             64W /  400W |       0MiB /  81920MiB |      0%      Default |
32|                                         |                        |             Disabled |
33+-----------------------------------------+------------------------+----------------------+
34|   6  NVIDIA A100-SXM4-80GB          On  |   0000000D:00:00.0 Off |                    0 |
35| N/A   34C    P0             63W /  400W |       0MiB /  81920MiB |      0%      Default |
36|                                         |                        |             Disabled |
37+-----------------------------------------+------------------------+----------------------+
38|   7  NVIDIA A100-SXM4-80GB          On  |   0000000E:00:00.0 Off |                    0 |
39| N/A   34C    P0             62W /  400W |       0MiB /  81920MiB |      0%      Default |
40|                                         |                        |             Disabled |
41+-----------------------------------------+------------------------+----------------------+
42
43+-----------------------------------------------------------------------------------------+
44| Processes:                                                                              |
45|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
46|        ID   ID                                                               Usage      |
47|=========================================================================================|
48|  No running processes found                                                             |
49+-----------------------------------------------------------------------------------------+

3.7.1. 示例单节点 JupyterLab 作业#

NGC 容器支持启动 Jupyter 服务,以交互式使用 Jupyter 笔记本。本节提供了一个示例 sbatch 脚本,该脚本安装了 RAPIDS Jupyterlab Dashboard 并在 Slurm 作业中启动 Jupyter。然后,我们将逐步介绍如何通过本地 Web 浏览器连接到生成的 Jupyter 服务。

3.7.1.1. SSH 连接到登录节点#

与集群的登录节点之一建立新的 SSH 会话。这不是成功执行此结果的唯一方法,但它将使所有步骤都可以在单个 Shell 中完成。

ssh -i /path/to/ssh_cert <cluster-user>@ip-addr-of-login-node -L 8888:localhost:8888

3.7.2. 示例 Jupyter sbatch 脚本#

1#!/bin/bash
2#SBATCH --partition defq --nodes 1
3#SBATCH --exclusive
4#SBATCH --job-name=example-jupyter-sbatch-job
5#SBATCH --gpus-per-node=8
6
7srun --mpi=pmix --container-mounts /lustre/fs0/scratch/demo-user --container-image nvcr.io/nvidia/pytorch:24.02-py3 \
8  bash -c "set -x; pip install --extra-index-url https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --pre jupyterlab_nvdashboard;
9  jupyter lab --NotebookApp.token='' --notebook-dir=/ --no-browser --ip=0.0.0.0 --NotebookApp.allow_origin='*'; sleep 1d"

将上面的文本保存在名为 jupyterlab.sbatch 的文件中,并运行以下命令。

sbatch jupyterlab.sbatch

3.7.2.1. 连接到 Jupyter 服务#

  1. 通过 squeue 验证作业是否已启动并在节点上运行。记下它正在运行的节点。

    1$ squeue
    2JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
    3  517      defq example- demo-use  R       2:44      1 gpu002
    
  2. 监视作业的输出日志,查找类似于以下的输出,表明服务器可访问。

    1[I 2024-05-02 15:37:10.540 ServerApp] Jupyter Server 2.14.0 is running at:
    2[I 2024-05-02 15:37:10.540 ServerApp] http://gpu002:8888/lab
    3[I 2024-05-02 15:37:10.540 ServerApp]     http://127.0.0.1:8888/lab
    
  3. 从同一 SSH 会话中,SSH 连接到正在运行的 GPU 节点(在本示例中为 gpu002),并将端口 8888 传递到登录节点,完成与本地工作站的连接。

    ssh gpu002 -L 8888:localhost:8888
    
  4. 从您的 Web 浏览器导航到 https://127.0.0.1:8888。您应该看到一个 Jupyter 界面,其中集成了 RAPIDS Jupyterlab Dashboard。

    Jupyterlab with RAPIDS Jupyterlab Dashboard

3.7.3. 示例单节点 VS Code 作业#

对于开发人员工作流程,能够在 DGX Cloud 集群内的节点上运行 Microsoft Visual Studio Code 可以消除代码同步,同时迭代地试验软件更改。例如,我们将逐步介绍如何使用交互式作业来安装 vscode CLI,并利用其 Remote Tunnel 功能连接到您的本地工作站。

  1. 运行以下作业即可开始。请注意,如果希望在未参与运行应用程序测试的节点上进行代码更改,则可以选择 CPU 节点而不是 GPU 节点。

    1srun -N 1 --pty \
    2--container-image nvcr.io/nvidia/pytorch:24.02-py3 \
    3--container-mounts "/lustre/fs0" \
    4--container-mount-home \
    5--gpus 8 \
    6--exclusive \
    7--job-name "vscode-job:interactive" \
    8bash
    
  2. 下载并将 code 工具解压缩到用户的主目录。

    cd ~; curl -Lk 'https://vscode.js.cn/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz && tar -xf vscode_cli.tar.gz; rm vscode_cli.tar.gz;
    
  3. 使用 code tunnel 命令创建隧道。

    ./code tunnel --accept-server-license-terms --name dgxc-remote-tunnel
    
  4. 选择您首选的登录方法,并按照身份验证提示操作。

    *
    * Visual Studio Code Server
    *
    * By using the software, you agree to
    * the Visual Studio Code Server License Terms (https://aka.ms/vscode-server-license) and
    * the Microsoft Privacy Statement (https://privacy.microsoft.com/en-US/privacystatement).
    *
    ? How would you like to log in to Visual Studio Code? ›
    ❯ Microsoft Account
      GitHub Account
    
  5. 身份验证成功后,您将看到一个 URL,您可以使用该 URL 打开 Web 浏览器并使用远程隧道。

    Open this link in your browser https://vscode.dev/tunnel/dgxc-remote-tunnel/workspace
    

3.7.4. 示例多节点批处理作业#

多节点作业与单节点作业有很多相似之处 - 要修改 Slurm 命令以运行多节点作业,只需请求多个节点即可。以下是一个请求多个节点的示例 sbatch 脚本

1#!/bin/bash
2#SBATCH --partition defq --nodes 2
3#SBATCH --exclusive
4#SBATCH --job-name=example-mn-sbatch-job
5#SBATCH --gpus-per-node=8
6
7srun --mpi=pmix --container-image nvcr.io/nvidia/pytorch:24.09-py3 hostname

此 sbatch 脚本与之前讨论的单节点版本之间唯一的变化是将 `-nodes 参数输入从 1 增加到 2。

将上面的文本保存在名为 multinode-hostname.sbatch 的文件中,并运行以下命令。

sbatch multinode-hostname.sbatch

预期输出现在将按如下方式更改,并且可以在生成的 .out 文件中找到(在本例中,使用 cat 命令显示)。

1cat slurm-225.out
2
3pyxis: imported docker image: nvcr.io#nvidia/pytorch:24.02-py3
4pyxis: imported docker image: nvcr.io#nvidia/pytorch:24.02-py3
5gpu001
6gpu002

3.7.4.1. 关键环境变量#

环境变量 中记录了几个对于多节点功能至关重要的环境变量。它们分为几个类别。这些类别包括:确保设备正确呈现给软件(CUDA_DEVICE_ORDER、MELLANOX_VISIBLE_DEVICES),确保 MPI 和 PMIX 配置正确(以 OMPI_MCA 或 PMIX 开头的环境变量),确保 NCCL 配置正确(以 NCCL 开头的环境变量),以及确保 UCX 配置正确(以 UCX 开头的环境变量)。

除了注释的环境变量之外,Slurm 还会根据通过 srunsbatch 提供的参数自动创建和设置许多环境变量。可以通过 srun 获得的选项和关联的环境变量的完整列表可以在 官方文档 中找到。

此处提供了一个表格,其中包含相关的 SLURM_GPU 环境变量及其含义,以及确保环境变量在作业期间可见的机制。

环境变量

说明

关联标志

关联的 Sbatch 环境变量

SLURM_GPUS

作业所需的 GPU 总数。

--gpus

SBATCH_GPUS

SLURM_GPUS_ON_NODE

此节点上步骤可用的 GPU 数量。

--exclusive

SBATCH_EXCLUSIVE

SLURM_GPUS_PER_NODE

作业资源分配中包含的每个节点上作业所需的 GPU 数量。

--gpus-per-node

SBATCH_GPUS_PER_NODE

SLURM_GPUS_PER_TASK

作业资源分配中要生成的每个任务上作业所需的 GPU 数量。

--gpus-per-task

SBATCH_GPUS_PER_TASK

SLURM_GPU_BIND

任务绑定到作业中特定 GPU 的方式。

--gpu-bind

SBATCH_GPU_BIND

SLURM_GPU_FREQ

分配给作业的 GPU 的请求频率值。

--gpu-freq

SBATCH_GPU_FREQ

3.7.4.2. 示例 PyTorch 作业#

为了运行使用 PyTorch NGC 容器的更复杂示例,我们将首先将 PyTorch 示例存储库克隆到我们的主目录。如果我们要在此存储库中生成日志文件或下载数据,则将此存储库克隆到我们的 Lustre scratch 目录中会更有意义。

git clone https://github.com/pytorch/examples

我们将使用 PyTorch 的 torchrun 工具来启动 multinode.py 示例。

创建一个名为 torchrun.sh 的文件,并将以下文本添加到其中。我们已将环境变量指定为 torchrun 的参数,Slurm 会根据我们启动 Slurm 作业的方式为我们创建环境变量。

 1#!/bin/bash
 2
 3torchrun \
 4--nnodes $SLURM_JOB_NUM_NODES \
 5--nproc_per_node $SLURM_GPUS_ON_NODE \
 6--master-addr $MASTER_ADDR \
 7--master-port $MASTER_PORT \
 8--node-rank $RANK \
 9--log-dir="${PWD}/logs" \
10/home/demo-user/examples/distributed/ddp-tutorial-series/multinode.py 100 25

使 torchrun.sh 文件可执行。

chmod +x torchrun.sh

我们将创建一个 sbatch 脚本来运行 torchrun.sh。创建一个名为 multinode-torchrun.sbatch 的文件,并将以下文本添加到其中。

 1#!/bin/bash
 2
 3#SBATCH --job-name=multinode-example
 4#SBATCH --partition defq
 5#SBATCH --exclusive
 6#SBATCH --nodes=2
 7#SBATCH --ntasks-per-node=1
 8#SBATCH --gpus-per-node=1
 9#SBATCH --gpus-per-task=1
10
11source env-vars.sh
12
13srun --container-image nvcr.io/nvidia/pytorch:24.02-py3 --mpi=pmix --container-mounts /lustre/fs0 --container-mount-home /home/demo-user/torchrun.sh

sbatch 脚本将在两个请求的节点中的每个节点上使用单个 GPU。重要的是要指定 --ntasks-per-node=1,因为 torchrun 随后将启动任何其他必要的进程。使用以下命令运行 multinode-torchrun.sbatch

sbatch multinode-torchrun.sbatch

可以在生成的 .out 文件中找到类似于以下内容的输出(在本例中,使用 cat 命令显示)。

 1cat slurm-226.out
 2
 3pyxis: imported docker image: nvcr.io#nvidia/pytorch:24.02-py3
 4pyxis: imported docker image: nvcr.io#nvidia/pytorch:24.02-py3
 5[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO] Starting elastic_operator with launch configs:
 6[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   entrypoint       : /home/demo-user/examples/distributed/ddp-tutorial-series/multinode.py
 7[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   min_nodes        : 2
 8[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   max_nodes        : 2
 9[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   nproc_per_node   : 1
10[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   run_id           : none
11[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   rdzv_backend     : static
12[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   rdzv_endpoint    : gpu001:49228
13[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   rdzv_configs     : {'rank': 1, 'timeout': 900}
14[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   max_restarts     : 0
15[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   monitor_interval : 5
16[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   log_dir          : None
17[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]   metrics_cfg      : {}
18[2024-06-13 14:24:39,312] torch.distributed.launcher.api: [INFO]
19...
20[GPU0] Epoch 99 | Batchsize: 32 | Steps: 32
21gpu002:862118:862201 [0] NCCL INFO [Service thread] Connection closed by localRank 0
22gpu001:875891:875974 [0] NCCL INFO [Service thread] Connection closed by localRank 0
23gpu001:875891:875891 [0] NCCL INFO comm 0x55555cee37a0 rank 0 nranks 2 cudaDev 0 busId 100000 - Abort COMPLETE
24gpu002:862118:862118 [0] NCCL INFO comm 0x55555cee3e20 rank 1 nranks 2 cudaDev 0 busId 100000 - Abort COMPLETE
25[2024-06-13 14:24:51,350] torch.distributed.elastic.agent.server.api: [INFO] [default] worker group successfully finished. Waiting 300 seconds for other agents to finish.
26[2024-06-13 14:24:51,350] torch.distributed.elastic.agent.server.api: [INFO] Local worker group finished (WorkerState.SUCCEEDED). Waiting 300 seconds for other agents to finish
27[2024-06-13 14:24:51,351] torch.distributed.elastic.agent.server.api: [INFO] [default] worker group successfully finished. Waiting 300 seconds for other agents to finish.
28[2024-06-13 14:24:51,352] torch.distributed.elastic.agent.server.api: [INFO] Local worker group finished (WorkerState.SUCCEEDED). Waiting 300 seconds for other agents to finish
29[2024-06-13 14:24:51,353] torch.distributed.elastic.agent.server.api: [INFO] Done waiting for other agents. Elapsed: 0.0012083053588867188 seconds
30[2024-06-13 14:24:51,352] torch.distributed.elastic.agent.server.api: [INFO] Done waiting for other agents. Elapsed: 0.002357959747314453 seconds

3.8. 将数据移入您的 DGX Cloud 集群#

关于 DGX Cloud 中的数据移动,需要考虑以下几个因素

  • 数据是否在可以访问 DGX Cloud 集群的本地工作站上可用?

  • 数据是否在公司网络内的共享文件系统或存储库上可用?

  • 数据是否在对象存储之外的公共互联网上可用?

  • 数据是否在 CSP 对象存储中的公共互联网上可用?

  • 传输数据需要哪些协议、端口或客户端软件?

  • 将传输多少数据?

  • 传输数据的人员与将要使用数据的人员是否是同一人?

3.8.1. 将数据从本地工作站移动到 DGX Cloud#

要将数据从本地工作站移动到 DGX Cloud,请考虑您的数据规模。

如果您正在处理一组公开可用的代码(Github、Gitlab),则首选使用 git 从 DGX Cloud 登录节点或作业克隆该代码。

git clone https://git*b.com/my-repo

如果代码仅在您的本地工作站或可从您的工作站访问的文件共享中可用,则需要进行复制。您可以写入您的主目录(形式为 /home/<cluster user>)或您有权访问的 Lustre 目录(例如 /lustre/fs0/scratch/<cluster user>)。

请记住 主目录Lustre 中注明的指南 - 为您的数据传输选择合适的 location。少量代码和配置文件非常适合您的主目录。但是,包含数据(或在内部下载到存储库结构中)的较大代码集在 Lustre 上最有意义。

这些策略非常适用于配置为访问您的 DGX Cloud 环境的本地工作站和内部计算资源。

注意

根据您正在处理的本地数据的规模,将数据上传到对象存储可能比使用 scpsftprsync 等工具更有意义。

3.8.1.1. scp#

scp 是文件、存档和小型目录的常用默认数据传输方法。以下示例将本地 archive.tgz 存档复制到用户的主目录。

scp archive.tgz <cluster user>@ip-addr-of-login-node:/home/<cluster user>

以下命令会将 archive.tgz 复制到用户的 Lustre scratch 目录。

scp archive.tgz <cluster user>@ip-addr-of-login-node:/lustre/fs0/scratch/<cluster user>

要复制目录而不是文件或存档,请使用 -r 标志。

scp -r data/ <cluster user>@ip-addr-of-login-node:/lustre/fs0/scratch/<cluster user>

请注意,scp 期望远程目录存在。如果远程目录不存在,则会观察到以下行为。

1scp archive.tgz <cluster user>@ip-addr-of-login-node:/lustre/fs0/scratch/<cluster user>/fake-dir/
2scp: dest open "/lustre/fs0/scratch/<cluster user>/fake-dir/": Failure
3scp: failed to upload archive.tgz to /lustre/fs0/scratch/<cluster user>/fake-dir/

要解决此问题,请 SSH 连接到登录节点并创建预期的目录。

1ssh <cluster user>@ip-addr-of-login-node
2mkdir /lustre/fs0/scratch/<cluster user>/fake-dir/

3.8.1.2. sftp#

sftp 是另一种将文件从工作站传输到 DGX Cloud 的选项。要开始使用,请使 sftp 连接到登录节点。

sftp <cluster user>@ip-addr-of-login-node

您将看到提示符更改,表明身份验证成功,并且您正在使用 sftp

sftp>

sftp 提供用于将数据从本地系统移动到远程系统以及从远程系统移动到本地系统的命令。

某些操作适用于本地和远程目录和文件。对于这些操作,在本地工作站上运行的命令版本之前会添加一个 l

例如,要列出本地工作站目录的内容,请运行 lls。要列出 DGX Cloud 目录中的目录内容,请运行 ls

可以使用 ? 命令找到操作的完整清单。

1sftp> ?
2Available commands:
3...

要更改您的远程目录,请使用 cd 命令。然后,使用 pwd 命令检查您的远程目录,并使用 lpwd 检查您的本地目录。文件将复制到您在本地和远程上下文中更改到的目录或从中复制文件。

1sftp> cd /lustre/fs0/scratch/demo-user
2sftp> pwd
3Remote working directory: /lustre/fs0/scratch/demo-user
4sftp> lpwd
5Local working directory: /Users/demo-user

要将文件上传到 DGX Cloud,请使用 put 命令。

sftp> put archive.tgz

要将目录及其内容上传到 DGX Cloud,请添加 -R 标志。

sftp> put -R my-directory

要轻松地将数据从 DGX Cloud 下载到您的本地工作站,请使用 get 命令(对于目录下载,使用 -R 标志)。

sftp> get -R my-log-file-directory

要退出您的 sftp 会话,请使用 bye 命令。

sftp> bye

3.8.1.3. rsync#

rsync 也是一种常用的数据传输工具,主要是在需要移动多个文件和/或目录以及需要在本地和远程目录之间定期同步数据时使用。

例如,使用 rsync 将本地工作站文件复制到用户的 DGX Cloud 主目录。

rsync archive.tgz <cluster user>@ip-addr-of-login-node:/home/<cluster user>

rsync 的用法与 scp 类似,但存在一些重要的差异。

要将目录从本地工作站复制到 DGX Cloud,如果您打算维护本地目录结构,请确保本地目录参数带有尾部的 /

rsync local-directory/ <cluster user>@ip-addr-of-login-node:/home/<cluster user>

如果没有尾部的 /,则本地目录的内容将放置在 DGX Cloud 目标目录中。

使用 rsync 时,需要考虑大量的标志。查看 官方文档 以探索所有可能的标志并针对您的用例进行优化。

3.8.2. 将数据从基于云的存储移动到 DGX Cloud#

当您需要移入 DGX Cloud 的数据位于基于云的对象存储中时,以下通用策略可用于各种工具。

  1. 编写一个 sbatch 脚本,以下载合适的工具,配置身份验证,并将数据放置在您的目标目录中(可能是 Lustre scratch 目录)。

  2. 运行 sbatch 脚本。

  3. 验证您的目标 DGX Cloud 目录中的结果是否正确。

  4. 对其他数据重复执行。

有关如何在集群中的 CPU 节点上执行此操作的示例过程,请参见以下部分。

3.8.2.1. 在 CPU 节点上使用容器运行作业#

本节展示了在 CPU 节点上使用 NGC 容器运行批处理作业的示例。对于许多用例,这是可选的,但如果您有一个内置通用工具的容器,可以在 CPU 节点上利用该容器,则可能会有所帮助。

3.8.2.1.1. 识别节点#

您可以使用 sinfo 命令查看集群中的节点

1sinfo
2
3PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
4cpuq         up   infinite      2   idle cpu[001-002]
5defq*        up   infinite     64   idle gpu[001-064]

在本文示例中,CPU 节点在离散的 cpuq 分区中可用。在以下章节中,我们将继续引用此分区。在下一步中,我们将指定要在 CPU 节点上运行的作业示例。

注意

根据您的集群配置的详细信息,您的具体分区可能会有所不同。例如,CPU 节点可能与 GPU 节点位于相同的 defq 分区中,或者可能存在或已创建其他分区。

3.8.2.1.2. 运行作业#

在仅 CPU 节点上使用 NGC 容器所需的关键新增内容是 NVIDIA_VISIBLE_DEVICES=void 环境变量。以下 sbatch 脚本指定了此环境变量。

1#!/bin/bash
2#SBATCH --partition cpuq --nodes 1
3#SBATCH --exclusive
4#SBATCH --job-name=example-cpu-sbatch-job
5
6export NVIDIA_VISIBLE_DEVICES=void
7
8srun --mpi=pmix --container-image nvcr.io/nvidia/pytorch:24.09-py3 hostname

将以上脚本保存在名为 cpu-hostname.sbatch 的文件中,并使用 sbatch 运行它,如下所示。

sbatch cpu-hostname.sbatch
3.8.2.1.3. 查看 sbatch 日志#

使用 tail -f 命令来跟踪您的主目录中生成的 Slurm 日志文件的输出。

1tail -f slurm-20.out
2
3pyxis: importing docker image: nvcr.io/nvidia/pytorch:24.09-py3
4pyxis: imported docker image: nvcr.io/nvidia/pytorch:24.09-py3
5cpu002

3.8.2.2. 通过 CPU 节点上的批处理作业加载数据#

本节展示了一个示例,说明如何在 CPU 节点上运行批处理作业,从云对象存储下载数据,然后将数据存储在 Lustre 文件系统上。

3.8.2.2.1. 识别节点#

您可以使用 sinfo 命令查看集群中的节点

1sinfo
2
3PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
4cpuq         up   infinite      2   idle cpu[001-002]
5defq*        up   infinite     64   idle gpu[001-064]

在本文示例中,CPU 节点在离散的 cpuq 分区中可用。在以下章节中,我们将继续引用此分区。在下一步中,我们将指定要在 CPU 节点上运行的作业示例。

注意

根据您的集群配置的详细信息,您的特定分区可能会有所不同。例如,CPU 节点可能与 GPU 节点位于相同的 defq 分区中,或者可能存在和/或已创建其他分区。

3.8.2.2.2. S3#

通过 AWS CLI sbatch 作业从 S3 加载数据

在本节中,我们将编写一个批处理作业以从 S3 加载数据。该作业执行三个主要任务

  1. 下载 AWS CLI 工具。

  2. 将下载的 CLI 工具解压缩到您的主目录中。

  3. 使用该工具通过 AWS S3 将数据集下载到 Lustre。

    1#!/bin/bash
    2#SBATCH --partition cpuq --nodes 1
    3#SBATCH --exclusive
    4#SBATCH --job-name=aws-s3-download
    5srun bash -c 'curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"
    6  -o "awscliv2.zip"; unzip awscliv2.zip; mkdir /lustre/fs0/scratch/demo-user/s3-dl;
    7/home/demo-user/aws/dist/aws s3 sync --no-sign-request --region=us-east-1 s3://noaa-swpc-pds /lustre/fs0/scratch/demo-user/s3-dl/'
    

要运行脚本

  1. 将以上脚本另存为您的主目录中的 aws-s3-download.sbatch

  2. 将 <demo-user> 更新为您的用户名。

  3. 使用以下命令将作业提交到队列

    sbatch aws-s3-download.sbatch
    

本示例中使用的是开放数据集,因此不需要 AWS 凭证。

来自 sinfo 的输出将显示 cpuq 分区中 CPU 节点之一上的活动。

1sinfo
2
3PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
4cpuq         up   infinite      1  alloc cpu001
5cpuq         up   infinite      1   idle cpu002
6defq*        up   infinite     64   idle gpu[001-064]

使用身份验证访问 S3 数据

您可以使用环境变量来访问需要安全授权的 S3 存储桶。

以下是修改后的 sbatch 脚本,它使用 AWS 环境变量 - 它被重写为假设 AWS CLI 已下载并解压缩。

 1#!/bin/bash
 2#SBATCH --partition cpuq --nodes 1
 3#SBATCH --exclusive
 4#SBATCH --job-name=aws-secure-s3-download
 5
 6export AWS_ACCESS_KEY_ID=your-access-key
 7export AWS_SECRET_ACCESS_KEY=your-secret-access-key
 8export AWS_DEFAULT_REGION=target-region
 9
10srun bash -c 'mkdir /lustre/fs0/scratch/demo-user/secure-s3-dl; /home/user/aws/dist/aws s3 sync s3://your-secure-bucket /lustre/fs0/scratch/demo-user/secure-s3-dl/'

根据数据位置或公司政策,可能需要不同的身份验证机制。

使用 s5cmd 工具访问 S3 数据

对于使用 S3 进行数据下载,可以考虑的另一种工具是 s5cmd 工具。相对于标准的 aws 工具,它提供了显著的性能提升,这可以为数十 GB 或更大的大型数据移动操作节省大量时间。

以下 sbatch 脚本与之前的示例类似,但下载并使用了 s5cmd 工具。

1#!/bin/bash
2#SBATCH --partition cpuq --nodes 1
3#SBATCH --exclusive
4#SBATCH --job-name=s5cmd-s3-download
5srun bash -c 'wget https://github.com/peak/s5cmd/releases/download/v2.2.2/s5cmd_2.2.2_Linux-64bit.tar.gz; tar -xf s5cmd_2.2.2_Linux-64bit.tar.gz; mkdir /lustre/fs0/scratch/demo-user/s5cmd-dl;
6/home/demo-user/s5cmd --no-sign-request cp s3://noaa-swpc-pds/* /lustre/fs0/scratch/demo-user/s5cmd-dl/'
3.8.2.2.3. Azure#

通过 AzCopy sbatch 作业从 Azure 存储加载数据

在本节中,我们将编写一个批处理作业,以使用 AzCopy 从 Azure 存储加载数据。该作业执行三个主要任务

  1. 下载 AzCopy 工具。

  2. 将下载的 CLI 工具解压缩到您的主目录中。

  3. 使用该工具通过 Azure 存储将数据集下载到 Lustre。

    1#!/bin/bash
    2#SBATCH --partition cpuq --nodes 1
    3#SBATCH --exclusive
    4#SBATCH --job-name=azcopy-download
    5
    6srun bash -c 'wget -O azcopy_v10.tar.gz https://aka.ms/downloadazcopy-v10-linux && tar -xf azcopy_v10.tar.gz --strip-components=1; mkdir /lustre/fs0/scratch/demo-user/azcopy; ./azcopy copy "https://azureopendatastorage.blob.core.windows.net/mnist/train-images-idx3-ubyte.gz" "/lustre/fs0/scratch/demo-user/azcopy"'
    

要运行脚本

  1. 将以上脚本另存为您的主目录中的 azcopy-download.sbatch

  2. 将 <demo-user> 更新为您的用户名。

  3. 使用以下命令将作业提交到队列

    sbatch azcopy-download.sbatch
    

本示例中使用的是开放数据集,因此不需要 Azure 凭证。

来自 sinfo 的输出将显示 cpuq 分区中 CPU 节点之一上的活动。

1sinfo
2
3PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
4cpuq         up   infinite      1  alloc cpu001
5cpuq         up   infinite      1   idle cpu002
6defq*        up   infinite     64   idle gpu[001-064]
3.8.2.2.4. CPU 作业 sbatch 日志#

与本节中的其他示例一样,使用 tail -f 命令来跟踪您的主目录中生成的 Slurm 日志文件的输出。

 1tail -f /home/demo-user/slurm-22.out
 2
 3download: s3://noaa-swpc-pds/json/goes/primary/differential-protons-7-day.json to s3-dl/json/goes/primary/differential-protons-7-day.json
 4download: s3://noaa-swpc-pds/text/3-day-geomag-forecast.txt to s3-dl/text/3-day-geomag-forecast.txt
 5download: s3://noaa-swpc-pds/text/aurora-nowcast-hemi-power.txt to s3-dl/text/aurora-nowcast-hemi-power.txt
 6download: s3://noaa-swpc-pds/text/45-day-ap-forecast.txt to s3-dl/text/45-day-ap-forecast.txt
 7download: s3://noaa-swpc-pds/json/solar-cycle/sunspots.json to s3-dl/json/solar-cycle/sunspots.json
 8download: s3://noaa-swpc-pds/json/goes/primary/xrays-7-day.json to s3-dl/json/goes/primary/xrays-7-day.json
 9download: s3://noaa-swpc-pds/text/3-day-forecast.txt to s3-dl/text/3-day-forecast.txt
10download: s3://noaa-swpc-pds/text/27-day-outlook.txt to s3-dl/text/27-day-outlook.txt
11download: s3://noaa-swpc-pds/products/alerts.json to s3-dl/products/alerts.json
12download: s3://noaa-swpc-pds/text/relativistic-electron-fluence-tabular.txt to s3-dl/text/relativistic-electron-fluence-tabular.txt
3.8.2.2.5. 验证数据#

下载的数据将存在于 Lustre 文件系统中,可以进行本地操作或摄取到基于 GPU 的作业中(如果已预处理)。

1ls /lustre/fs0/scratch/demo-user/s3-dl/
2
3index.html  json  products  text

3.9. 管理作业#

3.9.1. 作业状态和监控#

要查看集群上哪些作业的状态,请使用 squeue 命令

1squeue -a -l
2
32Tue Nov 17 19:08:18 2020
43JOBID PARTITION NAME USER STATE TIME TIME_LIMIT NODES NODELIST(REASON)
549      batch    bash user01 RUNNING 5:43 UNLIMITED 1 dgx1
6510     batch    Bash user02 RUNNING 6:33 UNLIMITED 2 dgx[2-3]

这会显示 JOBID 以及队列中所有作业的状态。

您可以使用 -u 标志来查看特定用户名的作业

squeue -l -u USERNAME

要查看有关特定作业的更详细信息,请使用 scontrol 命令

scontrol show job

3.9.2. 调整作业优先级#

您可以使用以下命令更改排队作业的作业优先级

scontrol update JOBID Priority=<Priority-Integer>

其中 <Priority-Integer> 替换为介于 12^32 - 1 之间的整数。整数越高,作业的优先级越高。

3.9.3. 暂停和恢复正在运行的作业#

可以使用 scontrol suspend 命令暂停正在运行的作业

scontrol suspend JOBID

作业将在其当前步骤停止,因此可以在稍后恢复。

要恢复暂停的作业,请使用 scontrol resume 命令

scontrol resume JOBID

3.9.4. 保持和释放排队的作业#

可以使用 scontrol hold 命令阻止排队的作业运行

scontrol hold JOBID

作业将保持在队列中的“保持”状态,因此在释放之前不会运行

scontrol release JOBID

3.9.5. 重新提交作业#

您可以将 requeue 标志与 scontrol 一起使用,以将处于 CONFIGURINGRUNNINGSTOPPEDSUSPENDED 状态的批处理作业添加到待处理队列中

scontrol requeue JOBID

3.9.6. 取消作业#

要取消正在运行的作业,首先请确保您知道 JOBID,可以使用 squeue 命令找到它,如先前所示。然后您可以使用 scancel 取消

scancel JOBID

可以通过用逗号分隔作业 ID 在一个命令中取消多个作业

scancel JOBID1, JOBID2