--- weight: 4 title: "使用队列系统" --- ## 队列系统的作用 简而言之:排队。你告诉队列系统使用什么资源(例如多少核的 CPU)运行某个程序,轮到你的任务执行时,队列系统会按照你的要求执行任务。 队列系统会考虑服务器的负载能力(不可以同时运行太多任务把服务器挤垮)、有多人使用服务器时公平分配资源,以及记录任务执行过程中的开销。 队列系统不与某个特定的计算软件(例如 VASP)绑定。 也就是说,你可以脱离队列系统直接运行 VASP,也可以把别的软件也放到队列系统里运行,它们虽然经常在一起使用,但本质上是两个分离的概念。[^1] ## 使用队列系统 队列系统与操作系统绑定很深。 * srv1:使用 [Slurm(新)](#slurm新)。 * srv1(Windows):请阅读 [Windows](#windows) 章节,了解相关注意事项。 * xmupc1 和 xmupc2:使用 [Slurm(旧)](#slurm旧)。 * 厦大超算(jykang):使用 [LSF](#lsf)。 ### Slurm(新) #### 使用图形界面快速开始 使用命令 `sbatch-tui` 或者 `sbatch` 不带任何参数,就可以看到一个图形界面[^3]。 按照提示,鼠标点选对应按钮,即可提交任务。这可以满足一多半的需求。 以下用一些例子来进一步介绍如何使用 Slurm。更多细节请参考[官方文档](https://slurm.schedmd.com/)。 例子中一些选项是可选的、一些是必写的,会详细说明。 #### 提交任务 使用 `sbatch` 提交任务。当加上参数时,会直接提交任务;当不加任何参数时,会调用 `sbatch-tui` 让你选。 提交一个 VASP(CPU)任务的例子: ```bash sbatch --ntasks=2 --cpus-per-task=4 --hint=nomultithread --job-name="my great job" --output=output.txt --queue=localhost --export=ALL,OMP_NUM_THREADS=4,OMP_STACKSIZE=512m --nodes=1-1 --mem=28G --wrap="vasp-intel srun --mpi=pmix vasp-std" ``` * `--ntasks=2 --cpus-per-task=4` 两者的乘积指定使用多少 CPU 核[^5],必写。 同样是占用 9 个核,`--ntasks=3 --cpus-per-task=3` 和 `--ntasks=9 --cpus-per-task=1` 性能并不相同。 此外,当 `--cpus-per-task` 不为 `1` 时,VASP 的 `NCORE` 等参数也与这里的参数耦合[^9]。 可以照抄下面的设置,或者自己尝试一下如何设置性能更好[^15]: * 对于 xmupc1:`--ntasks=3 --cpus-per-task=4`。 * 对于 xmupc2:`--ntasks=4 --cpus-per-task=10`。 * 对于 srv1 的默认队列:`--cpus-per-task=10`,`--ntasks=8` 或按需设置。 * 对于 srv1 的其它队列:`--ntasks=4 --cpus-per-task=8`。 * `--hint=nomultithread` 对于大多软件(包括 VASP)都需要写[^6],不写不会出错但会比较慢。 * `--job-name=xxx` 指定任务的名字,可以不写。 * `--queue=xxx` 指定队列的名字,不写时使用默认队列。 * `--export=ALL,OMP_NUM_THREADS=4,OMP_STACKSIZE=512m` 指定环境变量。完全不写这个参数时,相当于 `--export=ALL`。 * `ALL` 表示使用当前环境中的所有变量,并额外设置后面追加的值; * `OMP_NUM_THREADS=4` 表示设置 OpenMP 的线程数为 4。 对于使用 OPENMP 并行的程序(包括 VASP(CPU),但不包括 VASP(GPU)),`OMP_NUM_THREADS` 必须设置为与 `--cpus-per-task` 相同的值; 即使没有设置 `--cpus-per-task`,也需要设置 `OMP_NUM_THREADS=1`。 * `OMP_STACKSIZE` 设置每个 OpenMP 线程的栈大小,需要足够大,VASP 文档推荐设置为 `512m`,通常已经足够。 如果遇到段错误(Segmentation fault),可以尝试增大这个值。 * `--nodes=1-1` 强制所有任务分配到一个节点上(即不跨节点运行),推荐在大多情况下使用[^11]。 若要跨节点并行,并且节点 CPU/GPU 相同,不写这个参数就可以。 当要跨的节点的 CPU/GPU 型号不同时,还有别的注意事项,详见[这里](../qa#混合使用不同型号的节点)。 * `--mem=28G` 指定只使用内存大于等于 28 G 的节点,不设置则没有这个限制。 由于 Slurm 看到的内存大小比物理内存小一些[^14](例如 32 G 内存的节点,Slurm 可能会认为它只有 31.5 G),因此指定时也需要略小一些。 * `--wrap="vasp-intel srun --mpi=pmix vasp-std"` 指调用 std 版本的 VASP[^7]。 要使用 gam 或 ncl 版本,将最后的 `vasp-std` 改为 `vasp-gam` 或 `vasp-ncl`。 以下是一个提交 VASP(GPU)任务的例子(这个例子适用于旧的打包方式,会在下次服务器维护后更改): ```bash sbatch --gpus=1 --ntasks-per-gpu=1 --nodes=1-1 --job-name="my great job" --output=output.txt vasp-nvidia-std ``` * `--gpus` 指定使用哪个 GPU: * 要占用任意一个 GPU(排到这个任务时哪个空闲就使用哪个),写 `--gpus=1`。要占用任意两个就写 `--gpus=2`,以此类推。 对于 VASP,单个任务不要占用超过一个 GPU,是多个显卡的速度会比单个更慢(因为显卡之间的通信速度会是瓶颈)[^12]。 * 要指定具体使用哪一个 GPU 时,写 `--gpus=4090:1`。2080 Ti 需要写为 `2080_ti`,P5000 需要写为 `p5000`。 * 当需要使用多个不同型号的 GPU 时(例如,指定使用一个 3090 和一个 4090 ),写 `--gres=gpu:3090:1,gpu:4090:1`。 * `--ntasks-per-gpu=1` 对于 VASP(GPU)来说一定要写且只能设置为 `1`,对于其它任务(例如 LAMMPS)可以适当修改。[^4] * `--cpus-per-task` 对于 VASP(GPU)来说通常不用指定[^13],其它程序可能需要。这个选项的具体含义参考上一个例子。 * `vasp-nvidia-std` 即要执行的程序[^7],要使用 gam 或 ncl 版本时,写为例如 `vasp-nvidia-gam`。 要把其它程序提交到队列里,也是类似的写法。请自行举一反三。 #### 查看任务 要列出正在等待和正在运行的任务: ```bash squeue -l ``` 要列出已经提交(包括已经完成、取消、失败)的任务: ```bash squeue -t all -l ``` 要显示还没有完成的任务的详细信息,或刚刚完成的任务的详细信息: ```bash scontrol show job 114514 ``` 要在数据库中查找某一段时间内(例如 2024 年 8 月)提交的所有任务的详细信息[^10]: ```bash sacct --units M --format=ALL --starttime 2024-08-01T00:00:00 --endtime 2024-09-01T00:00:00 | bat -S ``` #### 调整和取消任务 取消一个任务: ```bash # 按任务的 id 取消 scancel 114514 # 按任务的名字取消 scancel -n my_great_job # 取消一个用户的所有任务 scancel -u chn ``` 如果自己已经提交了许多任务,现在想要把一个任务调整到自己的其它任务前面(不会影响整体的优先级),可以使用: ```bash scontrol top 114514 ``` 要无条件将一个任务优先级设置为最高或最低(需要管理员权限): ```bash # 最高 sudo scontrol update JobId=3337 Nice=-2147483645 # 最低 sudo scontrol update JobId=3337 Nice=2147483645 ``` ### Slurm(旧) 与 Slurm(新)基本相同,只是 VASP(CPU)的打包方式不同,使得提交任务的命令略有不同。 下一次服务器维护时,xmupc1 和 xmupc2 计划合并为一个集群,并且应用新的打包方式。 提交 VASP(CPU)任务的例子: ```bash sbatch --ntasks=2 --cpus-per-task=4 --hint=nomultithread --job-name="my great job" --output=output.txt vasp-intel-std ``` ### LSF 待补充。 ### Windows Windows 没有通用的队列系统程序,通常手动控制任务依次执行。~~我曾经在2024年暑假答应鹏岗帮他写一个,但事实是我把他鸽了,有空一定写,咕咕咕。~~ 你可以使用 FDTD Solutions 自带的一个单用户的队列系统。 在 FDTD Solutions 内的控制台使用 `addjob` 命令将要模拟的文件加入队列,然后它就会依次运行。 文档见[这里](https://optics.ansys.com/hc/en-us/articles/360034410714-addjob-Script-command)。 {{< callout type="warning" >}} 不要同时启动过多的计算任务。
例如,如果一个任务需要一个小时跑完,那么按顺序运行两个任务需要两个小时,但是同时运行两个任务需要的时间往往远大于两个小时。 若同时运行 10 个任务,可能连系统都没有反应了。 {{< /callout >}} {{% details title="一个简易的队列系统的实现" closed="true" %}} 待补充 {{% /details %}} [^1]: 实际上队列系统与要运行的软件还是有许多耦合的,尤其是使用 MPI 并行的程序(包括绝大多数成熟的大型科学计算软件)。 如何让队列系统与这些软件对接好有时会很麻烦,只是普通用户不需要关心(我替你们搞定了)。 [^3]: 其实这个不能叫“图形用户界面(gui)”,应该叫“文本用户界面(tui)”。但后者会让不熟悉的人误解,所以这里还是叫“图形界面”。 [^4]: 这个参数指定的通常是 MPI 进程数(为这个参数指定的数值乘以 GPU 数量),其实就是 `--ntasks` 的另外一种写法。 VASP(GPU)限制每个 GPU 必须对应且只能对应一个 MPI 进程,不满足这个条件就会报错或者只使用 CPU 计算,因此只能用一个。 [^5]: 通常来说,`--ntasks` 对应 MPI 进程数,`--cpus-per-task` 对应 OpenMP 线程数。 这个对应关系并不是一定的,比如你先请求 10 个 task,然后用 `srun` 运行 10 个不相关的程序也是可以的,这个过程中可以根本没有 MPI 和 OpenMP。 [^6]: 这个选项用于忽略 CPU 的超线程,即认为物理核心和对应的虚拟核心总共算一个核心。 Slurm 默认会把超线程核心和物理核各算成一个核,但做科学计算时一般要关掉超线程。 [^7]: 使用 `--wrap` 参数和直接写在 `sbatch` 后面,都可以指定要运行的程序。 区别在于,后者必须是一个脚本(不能是二进制程序),并且在脚本里可以指定一些给 Slurm 看的参数。 [^9]: 具体是如何耦合的,见[官方文档](https://www.vasp.at/wiki/index.php/Combining_MPI_and_OpenMP)。 [^10]: 我不确定这里是否真的是任务的“提交时间”而不是“完成时间”或者别的什么时间,官方文档没有说清楚。 [^11]: 跨节点并行可能会有比较大的损耗。我们的服务器都仅仅使用千兆网互联,比不上学校的超算,可能损耗更大。 [^12]: 如果有 nvlink,或许就不会出现这种情况。 [^13]: 按照经验,大多情况下,对于 VASP,一个 CPU 核心搭配一个显卡已经足够,增加核心数并不会更快。 少数情况下增加可能会有用,例如运行机器学习时(VASP 的机器学习使用纯 CPU 实现)。 [^14]: 实际上是在 Slurm 的配置文件中手动指定的。具体每个节点指定了多少,见[系统配置文件](https://github.com/CHN-beta/nixos)。 [^15]: 按照经验,OpenMP 线程数等于单个 CPU 或单个 ccx 的核心数或者核心数的一半时,性能最好。 ```