作业步 (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:作业步被用户或系统取消
作业步与作业对比¶
| 方面 | 作业 | 作业步 |
|---|---|---|
| 资源分配 | 从集群分配资源 | 使用父作业的资源 |
| 分区 | 必须指定分区 | 从父作业继承 |
| 账户 | 必须指定账户 | 从父作业继承 |
| QoS | 必须指定QoS | 从父作业继承 |
| ID格式 | 整数(如123) | jobid.stepid(如123.2) |
| 创建方式 | 通过cbatch、crun、calloc | 通过作业分配内的crun |
| 独立性 | 完全独立 | 依赖于父作业 |
| 生命周期 | 独立生命周期 | 不能超过父作业 |
何时使用作业步¶
以下情况使用作业步:¶
- 顺序运行多个任务
- 预处理 → 计算 → 后处理工作流
- 每个任务需要不同的资源配置
-
希望将所有任务保留在一个作业分配下
-
并行任务执行
- 同时运行多个独立计算
- 并行测试不同参数或配置
-
资源高效的并行工作流
-
交互式计算会话
- 使用
calloc一次性分配资源 - 交互式运行各种工具和命令
-
根据需要动态启动任务
-
资源效率
- 通过使用一个作业分配减少调度器开销
- 最大化已分配资源的利用率
- 避免重复的分配/释放周期
以下情况使用独立作业:¶
- 任务有完全不同的资源需求(分区、账户、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
最佳实践¶
-
分配足够的资源:确保作业分配有足够的资源用于所有计划的作业步
-
监控作业步进度:使用
cqueue --step跟踪作业步执行和资源使用 -
处理作业步失败:在脚本中实现错误处理以优雅地管理作业步失败
-
资源规划:规划作业步资源需求以最大化父作业利用率
-
使用描述性名称:为作业步使用清晰的名称,便于监控和调试
-
清理资源:显式取消不需要的作业步,而不是等待它们超时
-
日志管理:将作业步输出定向到单独的日志文件,便于调试
限制和注意事项¶
- 资源约束:作业步不能请求超过父作业中可用的资源
- 作业依赖:作业步不能超过父作业的生命周期
- 无属性覆盖:作业步不能更改从父作业继承的分区、账户或QoS
- 调度器开销:大量短生命周期的作业步可能会产生调度开销
- 时间限制:作业步必须在父作业的时间限制内完成