Pipeline Job Splitting
概述
使用这个 skill 将“已经能运行但提交粒度过粗”的管线改造成“多个细粒度单核子任务”的 HPC 工作流。默认保留原有分析模块和结果逻辑,只调整 pipe/、conf/ 和调度包装层,不默认自动提交。
固定工作流
按以下顺序组织实现:
- 检查当前项目的目录结构、总控脚本、配置文件和实际执行入口。
- 明确当前粗粒度任务的执行单元,例如“整张样本表一次跑完”或“一个大脚本内部并行”。
- 找出最自然的切分维度,优先考虑已有任务列表,而不是改写分析算法。
- 确认主 runner 是否已经支持外部传入配置文件、输入列表或任务参数。
- 如果不支持,优先对主 runner 做最小接口改造,使其可接收 task-specific 配置或输入覆盖。
- 在
pipe/下新增一个总控生成脚本,负责读取基准配置、切分任务列表、生成子配置、生成调度脚本并写出手动提交说明。 - 默认让每个生成出的子任务只申请
1个 CPU 核心,除非用户明确要求其他资源规格。 - 默认只生成作业脚本,不自动调用
bsub、sbatch或qsub。 - 检查输出目录、日志目录和路径解析是否会发生冲突,特别是批次目录不在项目内的情况。
- 在交付前验证批次目录结构、子任务文件一一对应关系以及生成脚本的资源规格。
必须决策的事项
在动手改造前,明确以下问题:
- 当前任务最适合按什么维度切分。
- 每个子任务包含多少条记录或多少个处理单元。
- 当前实际调度器是什么,默认按 LSF 处理还是需要映射到其他系统。
- 批次文件生成在项目内还是项目外的独立磁盘。
- 主 runner 是否需要支持
bash runner.sh /path/to/task.conf这种外部配置注入方式。 - 子配置文件、子调度脚本和批次目录的命名规则是什么。
- 是否只生成脚本由人工提交,还是用户明确要求自动提交。
- 输出目录和日志路径是否会因并发或重跑产生冲突。
- 如果批次目录位于项目外,是否把
PIPELINE_ROOT和关键文件路径直接写成绝对路径。
默认策略
除非用户明确要求,否则使用以下默认值:
- 调度器默认按 LSF 处理。
- 切分方式默认按任务列表固定行数切分。
- 粒度默认每个子任务 1 行。
- 每个子任务默认只申请 1 个 CPU 核。
- 默认由人工手动提交生成出的作业脚本。
- 默认保留原算法和原分析模块,不重写核心业务逻辑。
- 默认把批次目录放在
conf/hpc_batches/<batch_id>/。 - 如果批次目录放在项目外,生成的 wrapper 必须写绝对
PIPELINE_ROOT、CONF_FILE和主 runner 路径。
反模式
明确避免以下做法:
- 仅为了切分任务就重写核心分析代码或 Python/R 模块。
- 明明是 embarrassingly parallel 的工作负载,却继续保留一个多核大任务内部并行。
- 生成的调度脚本依赖脆弱的相对路径自动猜项目根目录,尤其在批次目录位于项目外时。
- 默认自动提交作业,导致用户失去检查生成物的机会。
- 不检查输出目录冲突就直接复用原路径。
- 主 runner 不能接收 task-specific 输入时,仍然直接生成大量子脚本。
交付要求
交付结果默认应包含:
- 一个基准配置文件。
- 一个可切分的任务列表。
- 一个
pipe/下的批次生成脚本。 - 每个子任务唯一的切分后列表文件。
- 每个子任务唯一的配置文件。
- 每个子任务唯一的调度脚本。
- 一个手动提交说明文件。
参考资料
- 详细方法:读取
references/workflow.md - LSF 模式与命名:读取
references/lsf-patterns.md - 验收与审查:读取
references/review-checklist.md