跳转至

作业步 (Job Steps)

作业步是作业内的子执行单元,允许在单个作业分配内运行多个执行阶段或并发任务。

什么是作业步?

作业步是在父作业上下文中运行的独立执行单元。与其为每个单独的任务分配资源,不如一次性分配资源(作为作业),然后在该分配内运行多个作业步。这种方法更高效,并提供更好的资源利用控制。

主要特征

  • 资源共享:作业步共享分配给父作业的资源
  • 独立执行:每个作业步可以有自己的命令、资源需求和生命周期
  • 灵活调度:作业步可以在作业的资源限制内顺序或并行运行
  • 简化管理:作业步自动继承作业属性,如分区、账户和QoS

作业步类型

CraneSched区分三种类型的作业步:

1. DAEMON步骤 (step_id=0)

  • 目的:作业生命周期的资源持有者
  • 生命周期:在作业的整个持续时间内存在
  • 执行:不执行用户代码
  • 创建:系统为每个作业自动创建
  • 用例:内部资源管理和作业协调

2. PRIMARY步骤 (step_id=1)

  • 目的:作业的主要执行单元
  • 生命周期:运行主要作业任务
  • 执行:执行作业提交时指定的命令/脚本
  • 创建:为每个作业自动创建
  • 用例:对于批处理作业,运行提交的脚本;对于交互式作业,运行用户shell

3. COMMON步骤 (step_id≥2)

  • 目的:额外的交互式步骤
  • 生命周期:可以在作业执行期间动态启动
  • 执行:运行用户指定的命令
  • 创建:用户通过作业分配内的crun创建
  • 用例:在作业内运行多个并行或顺序任务

作业步ID格式

作业步使用两部分格式标识:

格式: jobid.stepid

示例: - 123.0 - 作业123的DAEMON步骤 - 123.1 - 作业123的PRIMARY步骤 - 123.2 - 作业123的第一个COMMON步骤 - 456.3 - 作业456的第二个COMMON步骤

此格式在所有支持作业步操作的CraneSched命令中统一使用。


作业步生命周期

作业步经历以下状态:

PENDING → RUNNING → COMPLETED
         FAILED/CANCELLED

作业步状态

  • PENDING:作业步正在等待父作业内的资源
  • RUNNING:作业步正在执行
  • COMPLETED:作业步成功完成
  • FAILED:作业步因错误终止
  • CANCELLED:作业步被用户或系统取消

作业步与作业对比

方面 作业 作业步
资源分配 从集群分配资源 使用父作业的资源
分区 必须指定分区 从父作业继承
账户 必须指定账户 从父作业继承
QoS 必须指定QoS 从父作业继承
ID格式 整数(如123) jobid.stepid(如123.2)
创建方式 通过cbatch、crun、calloc 通过作业分配内的crun
独立性 完全独立 依赖于父作业
生命周期 独立生命周期 不能超过父作业

何时使用作业步

以下情况使用作业步:

  1. 顺序运行多个任务
  2. 预处理 → 计算 → 后处理工作流
  3. 每个任务需要不同的资源配置
  4. 希望将所有任务保留在一个作业分配下

  5. 并行任务执行

  6. 同时运行多个独立计算
  7. 并行测试不同参数或配置
  8. 资源高效的并行工作流

  9. 交互式计算会话

  10. 使用calloc一次性分配资源
  11. 交互式运行各种工具和命令
  12. 根据需要动态启动任务

  13. 资源效率

  14. 通过使用一个作业分配减少调度器开销
  15. 最大化已分配资源的利用率
  16. 避免重复的分配/释放周期

以下情况使用独立作业:

  • 任务有完全不同的资源需求(分区、账户、QoS)
  • 任务需要在不同时间运行或有不同优先级
  • 任务应计费到不同账户
  • 任务之间需要最大程度的隔离

使用示例

示例1:基本作业步工作流

# 分配交互式使用的资源
calloc -N 2 -c 8 --mem 4G -t 2:00:00

# 现在CRANE_JOB_ID已设置,crun将创建作业步
# 运行预处理作业步
crun -N 1 -c 4 ./preprocess.sh input.dat

# 并行运行多个计算作业步
crun -N 1 -c 8 ./compute.sh part1 &
crun -N 1 -c 8 ./compute.sh part2 &
wait

# 运行后处理作业步
crun -N 2 -c 4 ./postprocess.sh results

示例2:监控作业步

# 在另一个终端中监控作业步
cqueue --step -j 12345

# 查看特定作业步的详细信息
ccontrol show step 12345.2

# 使用自定义格式检查作业步状态
cqueue --step --format "%i %n %t %e %L"

示例3:管理作业步

# 取消特定作业步(其他作业步继续运行)
ccancel 12345.2

# 取消多个作业步
ccancel 12345.2,12345.3

# 取消所有作业步(整个作业)
ccancel 12345

示例4:作业步感知脚本

#!/bin/bash
# script.sh - 检测是否作为作业步运行

if [ -n "$CRANE_STEP_ID" ]; then
    echo "作为作业 $CRANE_JOB_ID 的作业步 $CRANE_STEP_ID 运行"
    echo "分配给此作业步的资源"
else
    echo "作为独立作业 $CRANE_JOB_ID 运行"
    echo "主要作业执行"
fi

# 运行计算
./my_program

示例5:使用作业步进行参数扫描

# 一次性分配资源
calloc -N 4 -c 16 -t 4:00:00

# 将参数扫描作为并行步骤运行
for param in 0.1 0.5 1.0 2.0 5.0; do
    crun -N 1 -c 4 ./simulate --param=$param &
done
wait

# 收集结果
crun -N 1 ./collect_results.sh

最佳实践

  1. 分配足够的资源:确保作业分配有足够的资源用于所有计划的作业步

  2. 监控作业步进度:使用cqueue --step跟踪作业步执行和资源使用

  3. 处理作业步失败:在脚本中实现错误处理以优雅地管理作业步失败

  4. 资源规划:规划作业步资源需求以最大化父作业利用率

  5. 使用描述性名称:为作业步使用清晰的名称,便于监控和调试

  6. 清理资源:显式取消不需要的作业步,而不是等待它们超时

  7. 日志管理:将作业步输出定向到单独的日志文件,便于调试


限制和注意事项

  • 资源约束:作业步不能请求超过父作业中可用的资源
  • 作业依赖:作业步不能超过父作业的生命周期
  • 无属性覆盖:作业步不能更改从父作业继承的分区、账户或QoS
  • 调度器开销:大量短生命周期的作业步可能会产生调度开销
  • 时间限制:作业步必须在父作业的时间限制内完成

相关命令

  • crun - 运行交互式任务并创建作业步
  • calloc - 为作业步执行分配资源
  • cqueue - 使用--step标志查询作业步信息
  • ccancel - 取消作业步
  • ccontrol - 控制和查询作业步详细信息