我正在移动在LSF集群中开发的Snakemake工作流程
环境(例如bsub
)到SGE集群环境(例如qsub
)。
我以前使用
规则中的resources
关键字,建议使用变量mem_mb
在docs中。我还使用threads
关键字指定了我希望可用于该作业的线程数。这些值有时最终会作为我自己的作业的参数(我正在运行的程序允许我指定其最大内存使用量。)
我在转换集群提交时遇到困难
概要文件/脚本对qsub
的内存要求的规范,
其中每个作业指定每个核心的内存需求,而bsub
则指定每个作业的内存需求。例如,我可能有一个多线程作业,需要64GB内存,并且要在8个内核上运行:
bsub
,这(基本上)由
bsub -M 65536 -n 8 {...}
。qsub
,我需要指定每个内核的内存(8192):
qsub -l h_vmem=8192M -l m_mem_free=8192M -pe smp 8 {...}
。过去,我的bsub
集群命令将使用这些值
从资源/线程提交作业:
snakemake --cluster "bsub -M {resources.mem_mb} -n {threads}"
。
我希望我可以使用Snakemake的字符串格式进行数学运算:
snakemake --cluster "qsub -l h_vmem={resources.mem_mb // threads} -pe smp {threads}"
。不幸的是,这不起作用-它告诉我mem_mb // threads
不是resources
的元素。
我希望能够拥有一个Snakefile,该文件对我的群集环境的影响最小。现在,我正在指定用于完成工作的资源,但这应该相对独立于平台。
是否有一种简单/标准的方法可以解决此差异,我可以应用该方法来提取/计算群集提交命令的此作业信息,而无需添加单独的资源命令?也就是说,我想避免:
# xxx is the memory requirements of the job in MB
mem_mb = xxx
# + 1 to guarantee that mem_mb_per_thread * threads >= mem_mb
mem_mb_per_thread = lambda wc, threads: (xxx // threads) + 1
现在,我期望进入我的Snakefile文件并为特定的集群平台添加一个冗余的resources
参数,这似乎是不合适的。这种情况下的最佳做法是什么?
答案 0 :(得分:0)
答案在Snakemake文档中有点:一个自定义的Snakemake配置文件,以提供一个自定义的Python作业提交脚本。我无法在他们的示例个人资料中找到它,但是在broadinstitute/snakemake-broad-uger上实现了一个很好的示例。此后,我使用jaicher/snakemake-sync-bq-sub处的bsub
Snakemake指令为基于qsub
或--cluster-sync
(SGE)的群集实现了一个实现。
在这种情况下,我们可以使用Snakemake辅助函数snakemake.utils.read_job_properties
从作业脚本(作业脚本的最后一个参数)中读取作业属性。这使我们能够从作业脚本中提取作业名称,通配符,资源和群集参数,从而可以进行其他处理。因此,最小的解决方案与我想避免的最初想法相距不远:
import sys # for sys.argv (command-line arguments)
from snakemake.utils import read_job_properties # to obtain properties
# get path of jobscript
jobscript = sys.argv[-1]
# get job properties
job_info = read_job_properties(jobscript)
# get threads information
threads = job_info.get("threads", 1)
# get resources information
resources = job_info.get("resources", dict())
# get mem_mb information
mem_mb = resources.get("mem_mb", DEFAULT_VALUE) # define DEFAULT_VALUE elsewhere
mem_mb_per_thread = round(mem_mb / threads, 2) # memory per thread
# if bsub, resources subcommand is...
bsub_subcmd = f" -M {mem_mb} -n {threads}"
# if qsub, resources subcommand is...
qsub_subcmd = (
f" -l h_vmem={mem_mb_per_thread}M -l m_mem_free={mem_mb_per_thread}M"
f" -pe smp {threads}"
)
# run something like `bsub {qsub_subcmd} {other_params} {jobscript}`