高性能计算(High-performance computing,HPC)是一个计算机集群系统,它通过各种互联技术将多个计算机系统连接在一起,利用所有被连接系统的综合计算能力来处理大型计算问题,所以又通常被称为高性能计算集群。
简单的说,如果你的电脑是4核的,一次可以处理4个任务的话,HPC也许一次可以处理400个任务。对于数据量大的计算,HPC是不可或缺的资源。比如需要用16核电脑运行1个星期的脚本,在HPC只需要1个小时。当然也有可能老掉牙的HPC连笔记本的性能都不如,比如我就亲自体验过比笔记本性能还差的HPC,虽然可以有几百个核可以用,结果速度还不如笔记本。
HPC的资源管理一般用slrum或者pbs体系,对应了不同的语法和命令,但是原理都是一样的:用户在Head node上申请资源,随后系统分配资源,运行脚本。 之前使用的HPC一直用pbs体系,结果刚熟悉不到半年就换成了slrum,想必是slrum在资源管理上更有优势。实际体验来看,slrum也更容易上手。这个推送分享使用频率最高的命令,JOB_ARRAY的使用和一些琐碎的Tips。大部分研究者可能用的是实验室自己的服务器,其实瞄一眼也无妨,万一哪天用上了呢。。
最常用的命令
提交任务 sbatch
sbatch job_file
job_file中定义了申请nodes的个数,核的数量,内存,时间和需要运行的命令。这里以运行某个matlab脚本为例。R/Python换成相应的命令行命令即可。
#!/bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=100
#SBATCH --mem=8G
#SBATCH --time=2:00:00
#SBATCH --job-name=test
#SBATCH --output=%x
cd job_path
matlab -r "run('some_matlab_code.m')"
监测任务 sqeueue
查看用户任务当前的状态
squeue -u user_id
取消任务 scancel
一种是取消特定的任务,这里的job_id可以使用通配符(*)进行批量操作。
scancel job_id
一种是取消用户的所有任务
scanel -u user_id
创建交互任务
HPC不允许用户在Head node上做大量的运行,如果需要调试脚本,可以申请一个interactive的job,其实所谓interactive也没有界面。。
srun --nodes=1 --ntasks=1 --mem=16G --time=01:00:00 --pty bash
JOB_ARRAY
假如你需要预处理1000个被试,想按正常的方式提交一个100核的任务,在for循环中用100个核并行。这样做的缺点是需要排队很长时间,系统才会给你分配资源。当然可以考虑只提交一个25核的任务,这样处理的时间会大大增加。或者提交4个25核的任务,这样需要手动拆分任务。JOB_ARRAY提供了完美的解决方案,它可以让你一次提交1000任务,每个任务处理一个被试,而且每个任务只需要申请一个核,大大增加了资源获取和代码运行的效率。
只需要增加--array=1-1000,它会为提交1000个任务,并且可以将SLURM_ARRAY_TASK_ID也就是1-1000分别作为你的代码的输入。代码需要是被试水平的代码。若其输入为1-1000,job1会处理sub1,job2处理sub2,依此类推。
#! /bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem=8G
#SBATCH --time=04:00:00
#SBATCH --job-name=ty
#SBATCH --array=1-1000
#SBATCH --output=%x_log_sub%a.out
cd job_path
matlab -r 'preprocessing_subject(${SLURM_ARRAY_TASK_ID})'
有的HPC会对用户可申请的任务数量做出限制,比如一个用户只能提交1000任务。当你有1500个被试,第二次提交的后500个任务,需要手动加上1000 ${SLURM_ARRAY_TASK_ID}+1000,因为slurm不支持从1001开始的array。这是和pbs相比的明显差别。
#! /bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem=8G
#SBATCH --time=04:00:00
#SBATCH --job-name=ty
#SBATCH --array=1-500
#SBATCH --output=%x_log_sub1k%a.out
cd $SLURM_SUBMIT_DIR
matlab -r 'preprocessing_subject(${SLURM_ARRAY_TASK_ID}+1000)'
R和Python使用类似,只需要将代码改为被试水平的代码,接收SLURM_ARRAY_TASK_ID作为输入即可。
#!/bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem=8G
#SBATCH --time=15:00:00
#SBATCH --job-name=ty
#SBATCH --array=1-21
#SBATCH --output=%x
Rscript --vanilla preprocessing_one_subject.R ${SLURM_ARRAY_TASK_ID}
在R代码中加入以下两行就可以将${SLURM_ARRAY_TASK_ID}作为你的input。
args = commandArgs(trailingOnly=TRUE)
idx=as.numeric(args[1])
假如发现有八个被试需要重新进行预处理,分别是第54, 70, 1357, 1366, 1401, 1406, 1463, 1465号被试,因为你使用的array只能是1-8,所有这时需要一点点bash知识将${SLURM_ARRAY_TASK_ID}转为真正需要重新运行被试的index:SUBI。
#! /bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --mem=8G
#SBATCH --time=04:30:00
#SBATCH --job-name=bsl_add
#SBATCH --array=1-8
#SBATCH --output=%x_log_sub1k%a.out
JOB_ARRAY=(54 70 1357 1366 1401 1406 1463 1465)
eval 'SUBI=${JOB_ARRAY[${SLURM_ARRAY_TASK_ID}]}'
cd $SLURM_SUBMIT_DIR
matlab -r 'preprocess_subject(${SUBI})'
琐碎的Tips
使用conda安装和配置你的python和R版本和环境
可能由于权限的问题,有的pakage就是装不上。可以使用conda安装某些R装不上的pakage,可以在anoconda的主页搜索你需要的包。
强烈推荐WinSCP作为你的FTP/SFTP客户端,它有一切你需要的功能,可能是留在Window的理由之一。
如何替换window下的\r\n?
用window编辑的文件,到了Linux下难免出现水土不服,\r\n不识别的问题,需要替换为Linux下的\n
使用linux的dos2unix,一般HPC不会有这个软件
使用网页版本的dos2unix转化,多导一道手。
使用Linux内置的sed命令
sed 's/\r$//' input_file.txt > output_file.txt
cat input.txt | sed 's/\r/\n/g' > output.txt
—END—