通配符Snakemake规则如何实现公共昂贵预处理资源一次性加载
方案1:本地单节点/多进程运行场景(非集群提交)
直接将公共加载逻辑放在Snakefile全局作用域,工作流解析阶段仅执行一次加载,所有规则任务复用实例:
import somemodule # 全局仅加载一次 data = somemodule.Loader("some_big_data") rule sample: input: "{name}.config" output: "{name}.npz" run: np.savez(output, data.process(input))
注:Linux环境下多进程运行时,fork机制的写时复制特性会保证只读的data对象不会被重复拷贝,不会额外占用内存
方案2:集群/分布式运行场景(每个任务为独立进程)
有两种实现可选,完全匹配你期望的写法:
选项A:使用官方内置setup块(Snakemake 7.1+版本支持)
setup块在每个任务执行进程中仅运行一次,该进程处理的所有同规则任务会复用setup阶段加载的资源:
rule sample: input: "{name}.config" output: "{name}.npz" setup: import somemodule data = somemodule.Loader("some_big_data") # 单进程内仅加载一次 run: np.savez(output, data.process(input))
选项B:使用作业分组合并多任务到同一进程
给规则添加分组属性,运行时指定分组合并的任务数量,即可在run块中遍历所有同组任务,实现一次加载多次处理:
rule sample: input: "{name}.config" output: "{name}.npz" group: "sample_process_group" run: import somemodule data = somemodule.Loader("some_big_data") # 整组任务仅加载一次 # 遍历同组所有任务处理 for job in snakemake.jobs: np.savez(job.output[0], data.process(job.input[0]))
运行工作流时添加以下参数,指定每个分组合并10个任务(可根据实际资源调整数值):
snakemake --groups sample=sample_process_group --group-components sample_process_group=10
备选方案:预序列化公共数据
如果Loader加载的结果支持序列化,可以新增一条单独的预处理规则,将加载后的对象序列化存储为中间文件,后续处理规则直接读取该中间文件即可,适合序列化开销远低于原始加载开销的场景。
内容的提问来源于stack exchange,提问作者abukaj
相关产品推荐
相关产品推荐

