Slurm 节能指南

目录

概述

Slurm 提供了一种集成机制,可以根据需要或请求将节点挂起(关闭电源,进入节能模式)和恢复(开机,从节能模式恢复)。在 IDLE 状态下保持SuspendTime 的节点将被 SuspendProgram 挂起,并且在 SuspendTimeout 内将无法进行调度。节点将通过 ResumeProgram 自动恢复以完成分配给它们的工作。在 ResumeTimeout 内未能注册的节点将变为 DOWN,并且其分配的作业将被重新排队。可以通过 scontrol update nodename=<nodename> state=power_<down|up> 手动请求节点节能。节点恢复或挂起的速率可以通过 ResumeRateSuspendRate 控制。

Slurm 可以通过其 API 配置为在任何云提供商(例如 亚马逊网络服务谷歌云平台微软 Azure)中实现节能,通过管理计算资源。这些资源可以与现有集群结合使用以处理超出工作负载(云突发),或者可以作为独立的自包含集群运行。

要在 Slurm 中启用节能操作,必须配置以下内容:

  • ResumeProgramSuspendProgram 必须定义。它们的值必须是程序的有效路径。
  • ResumeTimeoutSuspendTimeout 必须定义,或者全局定义,或者至少在一个分区上定义。
  • SuspendTime 必须定义,或者全局定义,或者至少在一个分区上定义,并且不能是 INFINITE-1
  • ResumeRateSuspendRate 必须大于或等于 0

Slurm 控制守护进程 slurmctld 必须重新启动以初始启用节能操作。配置参数(例如 SuspendTime)的更改将在修改 slurm.conf 配置文件并执行 scontrol reconfigure 后生效。

配置

以下感兴趣的配置参数包括:

DebugFlags

定义应提供更详细事件日志记录的特定子系统。感兴趣的选项包括:

Power

电源管理插件和节能(挂起/恢复程序)详细信息。

ReconfigFlags

控制在发出 scontrol reconfigure 命令时可能采取的各种操作的标志。感兴趣的选项包括:

KeepPowerSaveSettings

如果设置,则 scontrol reconfigure 命令将保留 SuspendExcNodesSuspendExcPartsSuspendExcStates 的当前状态。

ResumeFailProgram

当节点未能在 ResumeTimeout 内恢复时要执行的程序。程序的参数将是失败节点的名称(使用 Slurm 的主机列表表达式格式)。

ResumeProgram

用于从节能模式恢复节点的程序。该程序以 SlurmUser 身份执行(如在 slurm.conf 中配置)。程序的参数将是要从节能模式恢复的节点名称(使用 Slurm 的主机列表表达式格式)。

如果 slurmd 守护进程未能在配置的 ResumeTimeout 值内以更新的 BootTime 响应,则该节点将被置于 DOWN 状态,请求该节点的作业将被重新排队。如果节点实际上没有重启(例如,当配置了多个 slurmd 时),可以使用 "-b" 选项启动 slurmd,以将节点启动时间报告为现在。

通过读取由 SLURM_RESUME_FILE 环境变量指定的临时文件,可以获得作业到节点的映射,文件应在 ResumeProgram 开始时使用 - 有关更多详细信息,请参见 容错 部分。该程序可以使用 scontrol show nodename 命令来确保节点已启动并且 slurmd 守护进程已启动。

SLURM_RESUME_FILE=/proc/1647372/fd/7:
{
  "all_nodes_resume" : "cloud[1-3,7-8]",
  "jobs" : [
    {
      "extra" : "来自 --extra 的任意字符串",
      "features" : "c1,c2",
      "job_id" : 140814,
      "nodes_alloc" : "cloud[1-4]",
      "nodes_resume" : "cloud[1-3]",
      "oversubscribe" : "OK",
      "partition" : "cloud",
      "reservation" : "resv_1234"
    },
    {
      "extra" : null,
      "features" : "c1,c2",
      "job_id" : 140815,
      "nodes_alloc" : "cloud[1-2]",
      "nodes_resume" : "cloud[1-2]",
      "oversubscribe" : "OK",
      "partition" : "cloud",
      "reservation" : null
    },
    {
      "extra" : null,
      "features" : null,
      "job_id" : 140816,
      "nodes_alloc" : "cloud[7-8]",
      "nodes_resume" : "cloud[7-8]",
      "oversubscribe" : "NO",
      "partition" : "cloud_exclusive",
      "reservation" : null
    }
  ]
}

有关 oversubscribe 的可能值,请参见 squeue 手册页

注意SLURM_RESUME_FILE 仅在 Slurm 使用 JSON-C 序列化库编译时存在并可用。

ResumeRate

每分钟从节能模式中移除的最大节点数。值为零表示不施加限制。默认值为 300。使用此值可以防止电力消耗快速增加。

ResumeTimeout

发出节点恢复请求和节点实际可用之间允许的最大时间(以秒为单位)。在此时间范围内未能响应的节点将被标记为 DOWN,调度在该节点上的作业将被重新排队。此时间范围后重启的节点将被标记为 DOWN,原因是“节点意外重启”。默认值为 60 秒。

SchedulerParameters

此参数的解释因 SchedulerType 而异。多个选项可以用逗号分隔。感兴趣的选项包括:

salloc_wait_nodes

如果定义,salloc 命令将在所有分配的节点准备好使用(即启动)之前等待。默认情况下,salloc 在资源分配完成后立即返回。salloc 命令可以使用 --wait-all-nodes 选项来覆盖此配置参数。

sbatch_wait_nodes

如果定义,sbatch 脚本将在所有分配的节点准备好使用(即启动)之前等待。在默认情况下,sbatch 脚本将在作业分配中的第一个节点准备好后立即启动。sbatch 命令可以使用 --wait-all-nodes 选项来覆盖此配置参数。

SlurmctldParameters

以逗号分隔的选项,标识 slurmctld 选项。感兴趣的选项包括:

cloud_dns

默认情况下,Slurm 期望云节点的网络地址在节点创建之前未知,并且 Slurm 会在注册时通知节点的地址。由于 Slurm 通信依赖于 slurm.conf 中找到的节点配置,Slurm 会在等待所有节点启动后,告诉客户端命令每个节点的 IP 地址。然而,在节点在 DNS 中的环境中,可以通过配置此选项来避免此步骤。

idle_on_node_suspend

在使用 SuspendProgram 挂起节点时,无论当前状态如何,将节点标记为闲置,以便节点在稍后可以恢复。

node_reg_mem_percent=#

节点允许注册的内存百分比,而不被标记为低内存。默认值为 100。对于 State=CLOUD 节点,默认值为 90。

power_save_interval=#

power_save 线程检查恢复和挂起节点的频率。power_save 线程将在节点状态发生变化时更早执行工作。默认值为 10 秒。

power_save_min_interval=#

power_save 线程至少检查恢复和挂起节点的频率。默认值为 0。

SuspendExcNodes

不受挂起/恢复逻辑约束的节点。这可以用于避免挂起和恢复不在云中的节点。或者,挂起/恢复程序可以将本地节点与从云中提供的节点区分对待。使用 Slurm 的主机列表表达式来识别节点,使用可选的 ":" 分隔符和要从前面的范围中排除的节点计数。例如 nid[10-20]:4 将防止在 nid[10-20] 集合中 4 个可用节点(即 IDLE 且不 DOWN、DRAINING 或已关闭电源)被关闭。可以在逗号分隔的列表中指定多个节点集合,带或不带计数(例如 nid[10-20]:4,nid[80-90]:2)。默认情况下,不排除任何节点。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings

SuspendExcParts

包含永远不会进入节能模式的节点的分区列表。可以使用逗号分隔符指定多个分区。默认情况下,不排除任何节点。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings

SuspendExcStates

指定不应自动关闭电源的节点状态。有效状态包括 CLOUD、DOWN、DRAIN、DYNAMIC_FUTURE、DYNAMIC_NORM、FAIL、INVALID_REG、MAINTENANCE、NOT_RESPONDING、PERFCTRS、PLANNED 和 RESERVED。默认情况下,如果处于这些状态中的任何一个且闲置时间超过 SuspendTime,将关闭电源。此值可以使用 scontrol 更新。有关设置持久性的详细信息,请参见 ReconfigFlags=KeepPowerSaveSettings

SuspendProgram

用于将节点置于节能模式的程序。该程序以 SlurmUser 身份执行(如在 slurm.conf 中配置)。程序的参数将是要置于节能模式的节点名称(使用 Slurm 的主机列表表达式格式)。

SuspendRate

每分钟放入节能模式的最大节点数。值为零表示不施加限制。默认值为 60。使用此值可以防止电力消耗快速下降。

SuspendTime

节点在闲置或关闭此秒数后变为可进入节能模式。负数将禁用节能模式。默认值为 -1(禁用)。

SuspendTimeout

发出节点挂起请求和节点关闭完成之间允许的最大时间(以秒为单位)。在此时,节点必须准备好以便发出恢复请求以满足新工作负载的需要。默认值为 30 秒。

节点配置

感兴趣的节点参数包括:

Feature

节点特性可以与从云中获取的资源相关联,用户作业可以使用 --constraint 选项指定其资源使用偏好。

NodeName

这是 Slurm 识别节点的名称。建议使用包含数字后缀的名称以方便使用。

State

要按需添加的节点应具有 CLOUD 状态。

Weight

每个节点可以配置一个权重,表示使用该资源的优先级。权重较低的节点优先于权重较高的节点。默认值为 1。Slurm 将首先从已开机的节点分配资源,其次是启动的节点,最后是已关闭电源的节点 - 在每个集合中遵循节点权重。

分区配置

感兴趣的分区参数包括:

PowerDownOnIdle

如果设置为 YES 并且该分区启用了节能,则从该分区分配的节点在分配至少一个作业后将请求关闭电源。这些节点在从 COMPLETING 转换为 IDLE 之前不会关闭电源。如果设置为 NO,则节能将按照分区的配置运行。默认值为 NO

以下将导致从 COMPLETING 转换为 IDLE

  • 完成所有正在运行的作业,而不分配其他作业。
  • ExclusiveUser=YES,在所有正在运行的作业完成后,但在分配其他用户的作业之前。
  • OverSubscribe=EXCLUSIVE,在运行作业完成后,但在分配其他作业之前。

注意:当 PowerDownOnIdle 设置为 NO 时,节点在闲置时间超过 SuspendTime 时仍然会被关闭电源。

ResumeTimeout

发出节点恢复请求和节点实际可用之间允许的最大时间(以秒为单位)。在此时间范围内未能响应的节点将被标记为 DOWN,调度在该节点上的作业将被重新排队。此时间范围后重启的节点将被标记为 DOWN,原因是“节点意外重启”。默认值为 60 秒。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 ResumeTimeout 值。

SuspendTime

在此秒数内保持闲置或关闭的节点将通过 SuspendProgram 进入节能模式。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 SuspendTime 值。将 SuspendTime 设置为 INFINITE 将禁用该分区中节点的挂起。

SuspendTimeout

发出节点挂起请求和节点关闭完成之间允许的最大时间(以秒为单位)。在此时,节点必须准备好以便发出恢复请求以满足新工作负载的需要。默认值为 30 秒。

对于在多个分区中设置此选项的节点,将采用最高时间。如果在任何分区中未设置,则节点将使用整个集群设置的 SuspendTimeout 值。

节点生命周期

当 Slurm 配置为节能操作时,节点与之相关的状态集扩展。与节能相关的状态在使用 sinfo 查看节点详细信息时通常会标记符号。

图 1. 节点生命周期
图 1. 节点生命周期

感兴趣的节点状态:

状态 节能符号 描述
POWER_DOWN ! 关闭电源请求。当节点不再运行作业时,运行 SuspendProgram
POWER_UP   开机请求。当可能时,运行 ResumeProgram
POWERED_DOWN ~ 节点已关闭电源或处于节能模式。
POWERING_DOWN % 节点正在关闭电源或被置于节能模式,并且在 SuspendTimeout 内无法运行任何作业。
POWERING_UP # 节点正在开机或从节能模式恢复。

手动节能

可以通过使用 scontrol 将节点的状态设置为以下状态来手动开关节点:

scontrol update nodename=<nodename> state=power_<down|down_asap|down_force|up>

scontrol update 命令的操作/状态感兴趣:

POWER_DOWN
将使用配置的 SuspendProgram 程序显式将节点置于节能模式。如果节点已经在关闭电源的过程中,则该命令只会更改节点的状态,但在达到配置的 SuspendTimeout 之前不会产生任何效果。
POWER_DOWN_ASAP
将排空节点并标记为关闭电源。当前正在运行的作业将首先完成,且不会分配其他作业到该节点。
POWER_DOWN_FORCE
将取消节点上的所有作业,关闭电源,并将其状态重置为 IDLE
POWER_UP
将使用配置的 ResumeProgram 程序显式将节点移出节能模式。如果节点已经在开机的过程中,则该命令只会更改节点的状态,但在达到配置的 ResumeTimeout 之前不会产生任何效果。
RESUME
不是实际的节点状态,但将节点状态从 DRAIN、DRAINING、DOWN 或 REBOOT 更改为 IDLE 和 NoResp。slurmctld 将尝试联系 slurmd 请求节点注册自身。一旦注册,节点状态将移除 NoResp 标志,并恢复正常操作。它还将清除节点的 POWERING_DOWN 状态,使其有资格被分配。

恢复与挂起程序

ResumeProgramSuspendProgramSlurmUser 身份在 slurmctld 守护进程运行的节点上执行(主服务器和备份服务器节点)。可能需要使用 sudo 使 SlurmUser 能够关闭电源和重启节点。如果需要将 Slurm 的主机列表表达式转换为单个节点名称,scontrol show hostnames 命令可能会很有用。用于启动或关闭节点的命令将取决于您的集群管理工具。

ResumeProgramSuspendProgram 不受任何时间限制,但必须具有 容错。它们应执行所需的操作,理想情况下验证该操作(例如,节点启动并启动 slurmd 守护进程,因此节点不再对 slurmctld 无响应)并终止。长时间运行的程序将被 slurmctld 记录,但不会被中止。

示例 ResumeProgram

#!/bin/bash
# 示例 ResumeProgram
hosts=$(scontrol show hostnames "$1")
logfile=/var/log/power_save.log
echo "$(date) Resume invoked $0 $*" >>$logfile
for host in $hosts
do
        sudo node_startup "$host"
done
exit 0

示例 SuspendProgram

#!/bin/bash
# 示例 SuspendProgram
hosts=$(scontrol show hostnames "$1")
logfile=/var/log/power_save.log
echo "$(date) Suspend invoked $0 $*" >>$logfile
for host in $hosts
do
        sudo node_shutdown "$host"
done
exit 0

注意:挂起和恢复程序的 stderr 和 stdout 不会被记录。如果需要记录,则应将其添加到脚本中。

容错

如果 slurmctld 守护进程正常终止,它将等待最多十秒(或 SuspendTimeoutResumeTimeout 中较小的值)以终止任何生成的 SuspendProgramResumeProgram,然后再终止守护进程。如果生成的程序在该时间段内未终止,则事件将被记录,slurmctld 将退出,以允许启动另一个 slurmctld 守护进程。任何生成的 SuspendProgramResumeProgram 将继续运行。

当 slurmctld 守护进程关闭时,任何 SLURM_RESUME_FILE 临时文件将不再可用,即使 slurmctld 重新启动。因此,ResumeProgram 应在启动后十秒内使用 SLURM_RESUME_FILE 以保证它仍然存在。

启动不同的映像

如果您希望 ResumeProgram 根据作业规范启动各种映像,则它需要是一个相当复杂的程序,并执行以下操作:

  1. 确定与要启动的节点相关联的作业。SLURM_RESUME_FILE 将有助于此步骤。
  2. 确定每个作业所需的映像。可以通过 NodeFeaturesPlugins 映射映像。
  3. 为每个节点启动适当的映像。

使用分配

资源分配请求将在选择资源后立即获得批准,可能在所有节点都可用之前。作业步骤的启动将被延迟,直到所需节点恢复服务(它会打印关于等待节点变为可用的警告,并定期重试,直到它们可用)。

sbatch 命令的情况下,批处理程序将在分配的节点零准备好使用时启动,并可以根据需要执行预处理,然后使用 srun 启动作业步骤。可以使用 sbatch --wait-all-nodes=<value> 选项在每个作业的基础上覆盖此行为,并可以使用 SchedulerParameters=sbatch_wait_nodes 选项设置系统范围的默认值。

salloc 命令的情况下,一旦分配完成,将在登录节点上创建一个新 shell。可以使用 salloc --wait-all-nodes=<value> 选项在每个作业的基础上覆盖此行为,并可以使用 SchedulerParameters=salloc_wait_nodes 选项设置系统范围的默认值。

节点特性

NodeFeaturesPlugins 定义的特性,并与 slurm.conf 中的云节点相关联,将在节点关闭电源时可用但不活跃。如果作业请求可用但不活跃的特性,控制器将分配已关闭电源且具有可用特性的节点。在分配时,这些特性将变为活跃。云节点将保持活跃特性,直到节点关闭电源(即节点无法重启以获取其他特性,直到节点关闭电源)。当节点关闭电源时,这些特性变为可用但不活跃。任何未由 NodeFeaturesPlugins 定义的特性始终处于活跃状态。

示例:

slurm.conf:
NodeFeaturesPlugins=node_features/helpers

NodeName=cloud[1-5] ... State=CLOUD Feature=f1,f2,l1
NodeName=cloud[6-10] ... State=CLOUD Feature=f3,f4,l2

helpers.conf:
NodeName=cloud[1-5] Feature=f1,f2 Helper=/bin/true
NodeName=cloud[6-10] Feature=f3,f4 Helper=/bin/true

特性 f1、f2、f3 和 f4 是可变特性,并在 slurm.conf 中的节点行上定义,因为 CLOUD 节点在分配之前不会注册。通过将 Helper 脚本设置为 /bin/true,slurmd 将不会向控制器报告任何活跃特性,控制器将管理所有活跃特性。如果 Helper 设置为报告活跃特性的脚本,控制器将验证报告的活跃特性是节点活跃可变特性的超集。特性 l1 和 l2 将始终处于活跃状态,并可以用作可选择的标签。

混合集群

按需获取的云节点可以放置在其自己的 Slurm 分区中。这种操作模式可以仅在用户请求时使用这些节点。请注意,作业可以提交到多个分区,并将使用允许更快启动的分区的资源。以下是一个示例配置,当工作负载超过可用资源时,从云中添加节点。用户可以通过使用 --constraint 选项显式请求本地资源或云资源。

示例:

# slurm.conf 摘录
SelectType=select/cons_tres
SelectTypeParameters=CR_CORE_Memory

SuspendProgram=/usr/sbin/slurm_suspend
ResumeProgram=/usr/sbin/slurm_resume
SuspendTime=600
SuspendExcNodes=tux[0-127]
TreeWidth=128

NodeName=DEFAULT    Sockets=1 CoresPerSocket=4 ThreadsPerCore=2
NodeName=tux[0-127] Weight=1 Feature=local State=UNKNOWN
NodeName=ec[0-127]  Weight=8 Feature=cloud State=CLOUD
PartitionName=debug MaxTime=1:00:00 Nodes=tux[0-32] Default=YES
PartitionName=batch MaxTime=8:00:00 Nodes=tux[0-127],ec[0-127]

当全局设置 SuspendTime 时,Slurm 尝试挂起所有节点,除非被 SuspendExcNodesSuspendExcParts 排除。记住将本地节点添加到排除选项可能会很棘手。通过将全局 SuspendTime 设置为 INFINITE 并在特定于云的分区上配置 SuspendTime,可以避免必须排除节点。

示例:

# slurm.conf 摘录
SelectType=select/cons_tres
SelectTypeParameters=CR_CORE_Memory

SuspendProgram=/usr/sbin/slurm_suspend
ResumeProgram=/usr/sbin/slurm_resume
TreeWidth=128

NodeName=DEFAULT    Sockets=1 CoresPerSocket=4 ThreadsPerCore=2
NodeName=tux[0-127] Weight=1 Feature=local State=UNKNOWN
NodeName=ec[0-127]  Weight=8 Feature=cloud State=CLOUD
PartitionName=debug MaxTime=1:00:00 Nodes=tux[0-32] Default=YES
PartitionName=batch MaxTime=8:00:00 Nodes=tux[0-127],ec[0-127]
PartitionName=cloud Nodes=ec[0-127] SuspendTime=600

在这里,我们配置了一个仅包含云节点的分区,并在该分区上定义了 SuspendTime。这样可以让我们控制这些节点何时关闭电源,而不影响我们的本地节点,因此在此设置中不需要 SuspendExcNodesSuspendExcParts

云计费

有关云实例的信息可以存储在数据库中。这可以通过在 slurmd 启动时配置实例 ID/类型或使用 scontrol update 来完成。节点的“额外”字段也将存储在数据库中。

在 slurmd 启动时配置云信息:

$ slurmd --instance-id=12345 --instance-type=m7g.medium --extra="任意字符串" . . .

使用 scontrol update 配置云信息:

$ scontrol update nodename=n1 instanceid=12345 instancetype=m7g.medium extra="任意字符串"

然后可以使用 scontrol show node 在控制器上查看这些数据。过去和当前的数据可以通过 sacctmgr show instance 在数据库中查看,也可以通过 slurmrestd 使用 /instance/instances 端点查看。

使用 scontrol 在控制器上显示云信息:

$ scontrol show nodes n1 | grep "NodeName\|Extra\|Instance"
NodeName=n1 Arch=x86_64 CoresPerSocket=4
   Extra=任意字符串
   InstanceId=12345 InstanceType=m7g.medium

使用 sacctmgr 从数据库中显示云信息:

$ sacctmgr show instance format=nodename,instanceid,instancetype,extra
NodeName                  InstanceId         InstanceType                Extra
--------------- -------------------- -------------------- --------------------
n1                             12345           m7g.medium     任意字符串

使用 slurmrestd 从数据库中显示云信息:

$ curl -k -s \
        --request GET \
        -H X-SLURM-USER-NAME:$(whoami) \
        -H X-SLURM-USER-TOKEN:$SLURM_JWT \
        -H "Content-Type: application/json" \
        --url localhost:8080/slurmdb/v0.0.40/instances \
        | jq ".instances"

[
  {
    "cluster": "c1",
    "extra": "任意字符串",
    "instance_id": "12345",
    "instance_type": "m7g.medium",
    "node_name": "n1",
    "time": {
      "time_end": 0,
      "time_start": 1687213177
    }
  }
]

最后修改于 2025 年 5 月 20 日