集群作业#
您可以在现有集群上运行作业,这些作业会自动排队和调度。
这非常适合在现有集群上进行交互式开发以及重用其设置。
入门#
使用 sky exec
命令向现有集群提交作业
# Launch the job 5 times.
sky exec mycluster job.yaml -d
sky exec mycluster job.yaml -d
sky exec mycluster job.yaml -d
sky exec mycluster job.yaml -d
sky exec mycluster job.yaml -d
-d / --detach
标志会将日志与终端分离,这对于并发启动许多长时间运行的作业很有用。
要显示集群的作业及其状态
# Show a cluster's jobs (job IDs, statuses).
sky queue mycluster
要显示每个作业的输出
# Stream the outputs of a job.
sky logs mycluster JOB_ID
要取消作业
# Cancel a job.
sky cancel mycluster JOB_ID
# Cancel all jobs on a cluster.
sky cancel mycluster --all
提示
sky launch
命令/CLI 在一次调用中执行许多步骤,包括向现有或新供应的集群提交作业。请参阅此处。
多节点作业#
也支持在多个节点上运行的作业。
首先,创建一个 cluster.yaml
文件来指定所需的集群
num_nodes: 4
resources:
accelerators: H100:8
workdir: ...
setup: |
# Install dependencies.
...
使用 sky launch -c mycluster cluster.yaml
命令供应一个 4 节点集群(每个节点有 8 个 H100 GPU)。num_nodes
字段用于指定所需的节点数量。
接下来,创建一个 job.yaml
文件来指定每个作业
num_nodes: 2
resources:
accelerators: H100:4
run: |
# Run training script.
...
这指定了一个需要在 2 个节点上运行的作业,每个节点必须有 4 个空闲的 H100。然后您可以使用 sky exec mycluster job.yaml
命令提交此作业。
有关更多详细信息,请参阅分布式多节点作业。
使用 CUDA_VISIBLE_DEVICES
#
环境变量 CUDA_VISIBLE_DEVICES
会自动设置为分配给每个节点上每个作业的设备。此变量在调用作业的 run
命令时设置。
例如,上面的 job.yaml
在每个有 8 个 GPU 的节点上启动一个需要 4 个 GPU 的作业,因此在调用该作业的 run
命令时,CUDA_VISIBLE_DEVICES
将填充 4 个设备 ID。
如果您的 run
命令使用 Docker/docker run
,只需传递 --gpus=all
;正确的环境变量将在容器内部设置(只会设置分配的设备 ID)。
示例:网格搜索#
向集群提交具有不同超参数的多个试验
$ sky exec mycluster --gpus H100:1 -d -- python train.py --lr 1e-3
$ sky exec mycluster --gpus H100:1 -d -- python train.py --lr 3e-3
$ sky exec mycluster --gpus H100:1 -d -- python train.py --lr 1e-4
$ sky exec mycluster --gpus H100:1 -d -- python train.py --lr 1e-2
$ sky exec mycluster --gpus H100:1 -d -- python train.py --lr 1e-6
使用的选项
--gpus
:指定每个作业的资源需求。-d
/--detach
:将运行和日志与终端分离,允许多个试验并发运行。
如果集群上只有 4 个 H100 GPU,SkyPilot 将把 1 个作业排队,而其他 4 个并行运行。一旦一个作业完成,下一个作业将立即开始执行。有关 SkyPilot 调度行为的更多详细信息,请参阅下方。
提示
您还可以使用环境变量为每个试验设置不同的参数。
示例:分数 GPU#
要在每个 GPU 上运行多个试验,请在资源需求中使用分数 GPU。例如,使用 --gpus H100:0.5
让 2 个试验共享 1 个 GPU
$ sky exec mycluster --gpus H100:0.5 -d -- python train.py --lr 1e-3
$ sky exec mycluster --gpus H100:0.5 -d -- python train.py --lr 3e-3
...
共享 GPU 时,请确保 GPU 的内存没有超额分配(否则可能会发生内存不足错误)。
调度行为#
SkyPilot 的调度器有两个目标
防止资源超额分配:SkyPilot 使用作业的资源需求在集群上调度作业——这些需求可以在作业 YAML 的
resources
字段中指定,或者通过sky exec
CLI 命令的--gpus
选项指定。SkyPilot 尊重这些资源需求,同时确保集群中的任何资源都不会超额分配。例如,如果一个节点有 4 个 GPU,它不能托管多个作业,这些作业的 GPU 需求总和超过 4。最小化资源空闲:如果某个资源处于空闲状态,SkyPilot 将调度一个可以利用该资源的排队作业。
我们通过回顾教程:AI 训练来阐述调度行为。在该教程中,我们有一个作业 YAML 文件,指定了这些资源需求
# dnn.yaml
...
resources:
accelerators: H100:4
...
由于我们在运行 sky launch -c lm-cluster dnn.yaml
时创建了一个新集群,SkyPilot 供应的集群资源与作业所需的资源完全相同。因此,lm-cluster
有 4 个 H100 GPU。
在这个初始作业正在运行时,我们提交更多作业
$ # Launch 4 jobs, perhaps with different hyperparameters.
$ # You can override the job name with `-n` (optional) and
$ # the resource requirement with `--gpus` (optional).
$ sky exec lm-cluster dnn.yaml -d -n job2 --gpus=H100:1
$ sky exec lm-cluster dnn.yaml -d -n job3 --gpus=H100:1
$ sky exec lm-cluster dnn.yaml -d -n job4 --gpus=H100:4
$ sky exec lm-cluster dnn.yaml -d -n job5 --gpus=H100:2
由于集群只有 4 个 H100 GPU,我们将看到以下事件序列
初始的
sky launch
作业正在运行并占用 4 个 GPU;所有其他作业都处于 pending(等待中)状态(没有空闲 GPU)。然后前两个
sky exec
作业(job2、job3)开始运行,每个占用 1 个 GPU。第三个作业(job4)将处于 pending(等待中)状态,因为它需要 4 个 GPU,而只剩下 2 个空闲 GPU。
第四个作业(job5)将开始运行,因为它的需求可以通过剩下的 2 个空闲 GPU 满足。
一旦除了 job5 之外的所有作业都完成,集群的 4 个 GPU 将再次变为空闲,job4 将从 pending 状态转换为 running(运行中)状态。
因此,我们可能会在此集群上看到以下作业状态
$ sky queue lm-cluster
ID NAME USER SUBMITTED STARTED STATUS
5 job5 user 10 mins ago 10 mins ago RUNNING
4 job4 user 10 mins ago - PENDING
3 job3 user 10 mins ago 9 mins ago RUNNING
2 job2 user 10 mins ago 9 mins ago RUNNING
1 huggingface user 10 mins ago 1 min ago SUCCEEDED