|
|
本帖最后由 wal 于 2026-8-24 23:56 编辑
1 前言
多数量子化学程序的运行需要极长的时间,如果研究者想要运行一批任务,就免不了涉及到队列运行问题。就我所知,想要达成队列运行,有如下解决方案:
1)采用成熟的作业调度系统如slurm,sge,pbs等
作业调度系统在资源分配上做的很出色,是多数集群的队列管理首选。但在个人单机场景中,这些调度系统涉及到一些初见时比较难以理解的概念,且安装比较复杂,不太方便推广。
使用作业调度系统还有另一个问题,就是任务模板该如何管理。如果每次运行时都手写任务脚本,将会非常繁琐,像笔者这样懒惰而记性不好的人一看就该放弃了。
2)使用自建调度脚本
自建调度脚本的优点是运行命令可以设计得极简,启动调度脚本就能开始运行。
但缺点是此类调度脚本常常只针对某种程序、某类工作流等。若想实现并行,会极大提高调度脚本本身的复杂度。如果还想兼顾不同程序的兼容性,甚至可能需要像作业调度系统一样需要任务脚本来启动。
2 思路
为了解决上述问题,构造一种既适用于单机又适用于集群的队列管理程序,笔者做过一些尝试。首先,若要队列运行一些量子化学任务,我们的有效输入信息大致有以下三类:
1)每个任务的资源控制
2)每个任务的环境加载
3)每个任务的主运行命令
其余信息,如slurm模板八股文之类每个任务都一致的此处不算做有效信息。
对于信息(1),笔者自己做计算的时候,一般都是挑一个核数,然后所有程序都用这个设置,只有在特殊需求时才会更改。此出可暂时认为资源控制可以有一个默认值,特殊需求使用命令行临时覆盖
对于信息(2、3),若想做到通用队列,则必须以某种方式区分不同任务。此处笔者的选择是使用配置文件,按程序划分,每个程序有一个配置文件,保存其环境和运行命令。
有了这些信息,我们就可以像搭积木一样把所有东西全都搭起来,最终按照需求组合成作业调度系统或自建队列的任务脚本。
早期笔者尝试过bash脚本,但是发现bash脚本想做本地队列比较费劲,所以给队列单独做了个python脚本。后来觉得这样不是很优雅,于是把整个队列管理做成了一整个程序,也就是btrun。
注:btrun是某更大项目的一个组件,所以并不仅仅为了上述目的而设计,其中可能存在一些其他与本文无关的功能,可以忽视。
3 btrun
btrun是一个队列管理工具,支持主流的slurm、pbs、sge作业调度系统的任务脚本统一生成,也有自带的本地队列供没有安装调度系统的服务器单机串行、并行。对于大部分量子化学程序,在用户配置好后,只需要执行如'btrun task -t g16'这样的短命令,就可以完成对当前目录下所有相应程序输入文件的排队运行。
3.1 配置文件
btrun采用配置文件管理每种量子化学程序的构造信息,配置文件统一存放在~/.bane/task/envs里。在使用btrun前,你需要为你常用的量化程序做好配置文件。例如,Gaussian的~/.bane/task/envs/g16.conf:
- [main]
- # 资源配置
- CONF_CORES=32
- CONF_MEMORY=96000
- SUFFIX=gjf
- CONF_SPAN_NODES=false
- [ENV_SETUP]
- # g16 environment
- # module load g16
- source "$HOME/apprepo/gaussian/16-hy/scripts/env.sh"
- export PGI_FASTMATH_CPU=sandybridge
- export PATH=~/scripts/bin:$PATH
- [RUN_CMD_TEMPLATE]
- g16loop "${ACTUAL_INPUT_FILE}" --crash-handle all > "${ACTUAL_OUTPUT_FILE}"
复制代码 配置文件格式为类toml。[main]区配置默认本程序的提交资源,以及该程序对应的输入后缀、其他杂项设置。[ENV_SETUP]区直接写环境加载命令。[RUN_CMD_TEMPLATE]直接写程序运行命令。由于早期是bash设计,[RUN_CMD_TEMPLATE]处残留了bash风格的变量占位符痕迹,即如果用户需要使用输入文件名,则用"${ACTUAL_INPUT_FILE}"占位;输出文件则用"${ACTUAL_OUTPUT_FILE}" 占位。像GAMESS之类的需要在命令行指出核数的程序,则可以用"${CORES}"占位。
3.2 资源和作业调度系统管理
由于需要了解本机情况,且所需信息很碎,btrun提供了init命令来初始化。btrun init命令将自动探查资源情况并作为建议值提供,而用户可以交互式一项一项自定义资源要求。具体的看示例吧
- [gaus@login06 ~]$ btrun init
- Profile/cluster name [default]:
- Scheduler backend (slurm/sge/pbs/local) [slurm]:
- Detected local machine:
- cores: 64
- memory_mb: 257529
- gpus: 0
- scheduler commands: slurm,sge/pbs
- inferred role: login_node
- Enable local execution target? [y/N]: y
- Local role [login_node]:
- Local max CPU cores [64]:
- Local max memory, MB [257529]:
- Local max GPUs [0]:
- Local GPU ids, comma-separated:
- Reserve CPU cores for OS/interactive use [4]:
- Reserve memory for OS/interactive use, MB [16384]:
- Reserve GPUs [0]:
- Discovered scheduler queues: whhcnormal
- Use discovered queues? [Y/n]:
- Configure queue 'whhcnormal'? [Y/n]:
- Queue 'whhcnormal' resources and submit header
- Logical btrun queue key: whhcnormal
- Scheduler queue/partition name: whhcnormal
- Description [Discovered scheduler queue whhcnormal]:
- Aliases, comma-separated:
- Priority used by fallback, lower is preferred [10]:
- Physical CPU cores per node [32]:
- Max nodes [377]:
- Max CPU cores per node [32]:
- Max memory per node, MB [255500]:
- Max GPUs per node [0]:
- Default cores per job [16]: 32
- Default memory per job, MB [64000]: 96000
- High-memory threshold, MB/core [7984]:
- Slurm header style (ntasks_per_node/ntasks/cpus_per_task) [ntasks_per_node]:
- Add another queue manually? [y/N]:
复制代码 在配置好后,btrun就可以开始管理本地队列和作业调度系统队列了。
3.3 作业调度系统管理
由于笔者的主力是slurm调度系统,btrun对slurm生成的默认模板会比较稳定,而PBS和SGE则可能需要用户手动检查一下。此外,由于每个集群对作业脚本有不同的要求,比如拒绝某种选项,支持某种选项,只能用某种选项,这类村规难以统一,因此btrun允许用户自定义任务脚本的模板。例如,上述init自动生成的slurm模板配置保存在~/.bane/task/btrun/queues/default.yaml,内容为
- kind: queue_catalog
- schema_version: 1
- profile: default
- scheduler: slurm
- defaults:
- queue: whhcnormal
- priority_policy: lower_priority_first
- queues:
- whhcnormal:
- scheduler_queue_name: "whhcnormal"
- description: "Discovered scheduler queue whhcnormal"
- aliases: []
- enabled: true
- priority: 10
- resources:
- physical_cpu_num: 32
- max_nodes: 455
- max_cores_per_node: 32
- max_memory_mb_per_node: 255500
- max_gpus_per_node: 0
- default_cores: 32
- default_memory_mb: 96000
- high_memory_threshold_mb_per_core: 6000
- header_lines:
- - "#!/bin/bash"
- - "#SBATCH -J {{job_name}}"
- - "#SBATCH -p {{scheduler_queue_name}}"
- - "#SBATCH -N {{nodes}}"
- - "#SBATCH --ntasks-per-node={{cores_per_node}}"
- - "#SBATCH --mem={{memory_mb_per_node}}M"
- - "{{array_directive}}"
- - "export CORES={{cores}}"
- - "export BTRUN_QUEUE={{queue_name}}"
- - "cd {{workdir_quoted}} || exit 97"
复制代码 其中,header_lines:后面的内容均为slurm脚本头。有的集群只能使用ntasks-per-node,有的集群建议使用ncpus,有的集群禁止指定mem,用户可以根据需要修改这里的模板,使得渲染出的任务脚本符合自己的需求。
3.4 提交作业
完成上述配置之后,btrun就正式可用了。假如你配置好了g16的conf文件,而当前目录下存在1.gjf,2.gjf,3.gjf,1.log,则运行
btrun会先查找~/.bane/task/envs/g16.conf,然后读取SUFFIX值,确定要找的任务目标。此处为gjf,于是1.gjf,2.gjf,3.gjf均进入候选。随后检查是否存在同stem的log(这个输出后缀可以用OUTPUT_SUFFIX指定),发现1.log,认为这个已经运行过了,避免重复提交,排除该任务。随后,若配置了作业调度系统,则btrun组合header、环境加载、运行命令为任务脚本,并直接提交2.gjf、3.gjf到作业调度系统;
若没有作业调度系统,btrun会使用自己实现的本地队列来进行串行/并行任务。不过由于笔者平常的环境都有slurm,local队列较少使用,因此btrun的local队列可能存在一些bug,需要一些验证,欢迎反馈bug。进入local queue模式时,btrun生成btq文件(也就是btrun自带队列的任务脚本),然后开始运行。btrun会简单计算资源如何组合,如总共64核,提交上来一批32核的任务,且内存相加不超过内存上限,则btrun会两个两个地并行。但是btrun不会像真正的作业调度系统一样绑核,也不会实际限制内存分配,本质上资源分配只在btrun内部验证一下,后面跟bash去执行那个任务脚本没啥区别,这一点需要注意。以及自然,btrun的队列是阻塞运行的,如果想后台的话需要使用nohup等方式实现。可以使用btrun queue list来简单查询队列信息,btrun queue cancel来终止某个任务,btrun queue history看历史记录等,其他详细信息可以看btrun queue的帮助。
- $ btrun queue list
- JOBID STATE BACKEND PROFILE PID EXIT JOB_NAME WORKDIR
- 260823-170000_aaaaaaaa running local - 16995 - live-job /tmp/live
- $ btrun queue history
- JOBID STATE BACKEND PROFILE PID EXIT JOB_NAME WORKDIR
- 260823-160000_bbbbbbbb done local - - 0 done-job /tmp/done
- 260823-150000_cccccccc failed local - - 127 failed-job /tmp/failed
复制代码
btrun还有更多调整提交细节的功能,可以在运行btrun task -h和btrun queue -h在帮助里查看。例如btrun task -h输出:
- $ btrun task -h
- Standalone task submission
- USAGE:
- btrun task [<file-or-directory>...] [OPTIONS]
- INPUT:
- <file-or-directory>... Input files or directories
- OPTIONS:
- -h, --help Show help for this command
- Common submission options:
- -b, --backend <auto|local|slurm|sge|pbs>
- Filter targets by backend; auto selects from discovered local, scheduler,
- and remote targets
- -L, --local Restrict selection to the local file-queue runner
- -S, --slurm Restrict selection to Slurm targets, local or remote
- -E, --sge Restrict selection to SGE targets, local or remote
- -B, --pbs Restrict selection to PBS targets, local or remote
- -P, --profile <profile> Restrict selection to one execution profile
- --profiles <profile,...> Restrict selection to a comma/semicolon/space-separated profile target pool
- -D, --profile-dir <directory> Directory containing execution profiles
- -q, --queue <queue> Require a queue name, alias, or native partition
- --auto-target Allow unconstrained automatic selection of remote profiles
- --no-auto-target Disable automatic remote-profile selection for this invocation
- --no-local Exclude the local file-queue runner
- --health-check Probe candidate remote scheduler commands over SSH
- --no-health-check Disable remote scheduler health probes for this invocation
- --explain Print discovered, rejected, and selected execution targets
- --selection-mode <local_first|remote_first|best_fit|first_runnable_by_priority>
- Target ordering: local_first, remote_first, best_fit, or
- first_runnable_by_priority
- -d, --dry-run Render/prepare work but skip submission
- -k, --keep-script Keep generated submit scripts
- -p, --path <directory> Directory to scan for kick/submit/render/task
- Local queue options:
- -w, --poll <seconds> Runner polling interval in seconds; default: 5
- -F, --follow Follow local job .out/.err logs in this terminal
- --verbose Print full local job IDs, paths, and finish source
- --detach Start or join a short-lived background local runner
- --no-detach Disable detached local-runner mode for this invocation
- -c, --cores <count> Total CPU cores available to the local runner
- --gpus <count> Total GPUs available to the local runner
- --gpu-ids <id,...> GPU IDs visible to local jobs, for example 0 or 0,1
- Batch submission options:
- --max-submit <count> Process at most N discovered jobs in this invocation; default: unlimited
- Task options:
- --config-dir <directory> Directory containing <type>.conf files
- -r, --raw-mode Submit each input directory as a raw task
- --file-mode Force normal input-file mode when RAW_MODE=true
- -f, --force Submit even when expected output already exists
- -a, --recursive Recursively scan input directories
- -l, --list-types List available task types in the config search path
- -H, --help-type <type> Show the HELP_START/HELP_END block from TYPE.conf
- -t, --type <type> Task type resolved from TYPE.conf; defaults from manifest, then gaussian
- -n, --task-cores <count> Per-job CPU cores; --cores is also used when this option is omitted
- -m, --memory <megabytes> Per-job memory in MB
- -x, --extra-args <arguments> Value for EXTRA_ARGS in RUN_CMD_TEMPLATE
- --post-var <variable> Append a named config variable after the main command
- Behavior:
- task builds jobs from <type>.conf plus explicit input files, scanned
- input directories, or task.manifest.json.
- Type/config resolution:
- Type priority: -t/--type, then task.manifest.json program_params.prog,
- then task.manifest.json program_type, then gaussian. TYPE.conf is found
- from --config-dir, BTRUN_TASK_CONFIG_DIR, BANETASK_ENVCONF_PATH,
- ./envs, ./conf/envs, installed envs, and ~/.bane/task/envs.
- POSIX path-list values use ':'; Windows path-list values use ';'.
- Manifest fields used when present:
- input_files, output_file_name, program_type, program_params.prog,
- program_params.args/extra_args, nprocs/nproc/cores, memory/mem,
- maxcore, cores_pre_node/cores_per_node, gpus, gpu_mem, gpu_type.
- When no task.manifest.json is present, g16 inputs are probed
- for %nprocshared/%nproc and %mem, and orca inputs for %pal/!PALN
- and %maxcore, unless CLI options override them.
- Examples:
- btrun task -L -t gaussian --path ./cases -a -c 64 -n 16
- btrun task -S -t orca mol1.inp mol2.inp
- btrun task --path ./case-with-manifest
- btrun task -l --config-dir ~/.bane/task/envs
- btrun task -H gaussian
- btrun help conf
- Use 'btrun help conf' for the task environment .conf format.
复制代码
3.5 其他
btrun存在一些其他的需要提及的默认行为,在这里提示。可能有一些其他没想到的,随时补充。
1)对于Gaussian任务(必须是g16.conf)和ORCA任务(必须是orca.conf),若没有在命令行用-m,-n等指定核数,btrun会尝试解析输入文件头的资源设置作为提交作业的资源设定。
2)btrun会根据队列的memory-per-core(init时的High-memory threshold参数)限制来动态调整申请的资源。例如,对于postHF任务,通常需要小核数+大内存。然而,一些集群要求内存与核之比不能高于xxxx,因此量化实际使用资源不等于提交所用资源。遇到超出队列memory-per-core的高内存需求任务时,btrun会用总内存除以memory-per-core阈值,向上取整得到最终请求核数。例如,队列限制memory-per-core最高3000,我有个任务是需要使用16核+96000M的,btrun会利用96000/3000=32,尝试提交一个32核(当然队列必须有这么多核)、memory-per-core=3000的任务。
3)High-memory threshold还有另一个行为,就是在任务内存需求超出High-memory threshold时,如果你配置了其他队列,btrun会优先尝试把任务转交到一个内存够高的队列去,而不是扩大核数在本队列提交。
4)当前btrun task对GPU的管理方案不完整,未来可能会进一步支持
4 下载
btrun暂未开源,未来可能会随另一个项目一块放出。二进制文件下载:
linux:
btrun.zip
(2 MB, 下载次数 Times of downloads: 0)
配置文件示例:
envs.zip
(3.75 KB, 下载次数 Times of downloads: 0)
(不要照抄,按照你当前环境的实际情况修改)
欢迎反馈bug,直接在本贴回复即可
|
评分 Rate
-
查看全部评分 View all ratings
|