运行 使用并行工具在 PBS 中包含数百万个列表

Run million of list in PBS with parallel tool

我有一个巨大的(几百万)作业包含列表并且想要 运行 java 编写工具来执行功能比较。此工具在

内完成计算
real    0m0.179s
user    0m0.005s
sys 0m0.000s sec

运行 5 个节点(每个节点有 72 个 cpus)在 GNU 并行中使用 pbs 扭矩调度程序,工具 运行s 很好并产生结果但是当我设置 72 个作业时每个节点,一次应该 运行 72 x 5 个作业,但我只能看到 运行 25-35 个作业! 检查每个节点上的 cpu 利用率也显示利用率低。

我希望一次 运行 72 X 5 个工作或更多,并利用所有可用资源 (72 X 5 cpus) 产生结果。

正如我提到的,运行 有约 2 亿份工作,我希望以 using/increasing nodes/cpus 的数量更快地完成它(1-2 小时)。

当前代码、输入和作业状态:

example.lst(大约有 3 亿行)

ZNF512-xxxx_2_N-THRA-xxtx_2_N
ZNF512-xxxx_2_N-THRA-xxtx_3_N
ZNF512-xxxx_2_N-THRA-xxtx_4_N
.......

猫job_script.sh

#!/bin/bash
#PBS -l nodes=5:ppn=72
#PBS -N job01
#PBS -j oe

#work dir
export WDIR=/shared/data/work_dir

cd $WDIR;  

# use available 72 cpu in each node    
export JOBS_PER_NODE=72

#gnu parallel command
parallelrun="parallel -j $JOBS_PER_NODE --slf $PBS_NODEFILE --wd $WDIR --joblog process.log --resume"

$parallelrun -a example.lst sh run_script.sh {}

猫run_script.sh

#!/bin/bash 
# parallel command options
i=
data=/shared/TF_data

# create tmp dir and work in
TMP_DIR=/shared/data/work_dir/$i
mkdir -p $TMP_DIR
cd $TMP_DIR/

# get file name
mk=$(echo "$i" | cut -d- -f1-2) 
nk=$(echo "$i" | cut -d- -f3-6) 

#run a tool to compare the features of pair files
/shared/software/tool_v2.1/tool -s1 $data/inf_tf/$mk -s1cf $data/features/$mk-cf -s1ss $data/features/$mk-ss -s2 $data/inf_tf/$nk.pdb -s2cf $data/features/$nk-cf.pdb -s2ss $data/features/$nk-ss.pdb > $data/$i.out

# move output files    
mv matrix.txt $data/glosa_tf/matrix/$mk"_"$nk.txt
mv ali_struct.pdb $data/glosa_tf/aligned/$nk"_"$mk.pdb
# move back and remove tmp dir
cd $TMP_DIR/../
rm -rf $TMP_DIR
exit 0

PBS 投稿

qsub job_script.sh

登录到其中一个节点:ssh ip-172-31-9-208

top - 09:28:03 up 15 min,  1 user,  load average: 14.77, 13.44, 8.08
Tasks: 928 total,   1 running, 434 sleeping,   0 stopped, 166 zombie
Cpu(s):  0.1%us,  0.1%sy,  0.0%ni, 98.4%id,  1.4%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  193694612k total,  1811200k used, 191883412k free,    94680k buffers
Swap:        0k total,        0k used,        0k free,   707960k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                       
15348 ec2-user  20   0 16028 2820 1820 R  0.3  0.0   0:00.10 top                            
15621 ec2-user  20   0  169m 7584 6684 S  0.3  0.0   0:00.01 ssh                            
15625 ec2-user  20   0  171m 7472 6552 S  0.3  0.0   0:00.01 ssh                            
15626 ec2-user  20   0  126m 3924 3492 S  0.3  0.0   0:00.01 perl                                                     
.....

顶部的所有节点都显示相似的状态,并通过 运行一次仅生成 ~26 个结果!

我的 aws-parallelcluster 包含 5 个节点(每个节点有 72 个 cpus),带有扭矩调度程序和 GNU Parallel 2018,2018 年 3 月


更新

通过引入在 stdin 上接受输入的新函数,运行并行运行脚本效果很好,并利用了本地机器中的所有 CPU。

然而,当它在远程机器上的 运行s 时,它会产生一个

parallel: Error: test.lst is neither a file nor a block device

MCVE:

一个简单的代码,回显列表在 运行 在远程机器上运行它时给出相同的错误,但在本地机器上运行良好:

cat test.lst # 包含列表

DNMT3L-5yx2B_1_N-DNMT3L-5yx2B_2_N
DNMT3L-5yx2B_1_N-DNMT3L-6brrC_3_N
DNMT3L-5yx2B_1_N-DNMT3L-6f57B_2_N
DNMT3L-5yx2B_1_N-DNMT3L-6f57C_2_N
DNMT3L-5yx2B_1_N-DUX4-6e8cA_4_N
DNMT3L-5yx2B_1_N-E2F8-4yo2A_3_P
DNMT3L-5yx2B_1_N-E2F8-4yo2A_6_N
DNMT3L-5yx2B_1_N-EBF3-3n50A_2_N
DNMT3L-5yx2B_1_N-ELK4-1k6oA_3_N
DNMT3L-5yx2B_1_N-EPAS1-1p97A_1_N

cat test_job.sh # GNU 并行提交脚本

#!/bin/bash
#PBS -l nodes=1:ppn=72
#PBS -N test
#PBS -k oe

# introduce new function and Run from ~/
dowork() {
parallel sh test_work.sh {}
}
export -f dowork

parallel -a test.lst --env dowork --pipepart --slf $PBS_NODEFILE --block -10 dowork

cat test_work.sh # run/work 脚本

#!/bin/bash 
i=
data=pwd
#create temporary folder in current dir
TMP_DIR=$data/$i
mkdir -p $TMP_DIR
cd $TMP_DIR/
# split list
mk=$(echo "$i" | cut -d- -f1-2) 
nk=$(echo "$i" | cut -d- -f3-6) 
# echo list and save in echo_test.out
echo $mk, $nk >> $data/echo_test.out
cd $TMP_DIR/../
rm -rf $TMP_DIR

我不确定 tool 是做什么的。但是,如果复制花费了大部分时间,并且 tool 仅读取文件,那么您可以将文件符号链接到 $TMP_DIR 而不是复制。

您是否可以更快地完成它的一个很好的指示是查看集群中 5 台机器中的 top。如果他们都以 >90% 的速度使用所有内核,那么您不能指望它会更快。

根据你的时间:

real    0m0.179s
user    0m0.005s
sys 0m0.000s sec

似乎该工具只使用很少的 CPU 功能。当 GNU Parallel 运行 本地作业时,每个作业的开销为 10 毫秒 CPU 时间。您的作业使用 179 毫秒和 5 毫秒 CPU 时间。因此 GNU Parallel 将使用相当多的时间。

远程 运行 宁作业时,开销要大得多。这里我们说的是 10 毫秒 + 运行 宁一个 ssh 命令。这很容易达到 100 毫秒的数量级。

那么我们如何才能最大限度地减少 ssh 命令的数量以及如何将开销分散到多个内核上?

首先让我们创建一个函数,可以在 stdin 和 运行 脚本上获取输入 - 每个 CPU 并行线程一个作业:

dowork() {
  [...set variables here. that becomes particularly important we when run remotely...]
  parallel sh run_script.sh {}
}
export -f dowork

通过 运行ning 测试这是否有效:

head -n 1000 example.lst | dowork

然后让我们看看 运行本地的工作。这可以像这里描述的那样完成:https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Running-more-than-250-jobs-workaround

parallel -a example.lst --pipepart --block -10 dowork

这会将 example.lst 拆分为每个 CPU 线程的 10 个块。因此,在具有 72 CPU 个线程的机器上,这将生成 720 个块。它将开始 72 doworks,当完成一个时,它将获得 720 个块中的另一个。我选择 10 而不是 1 的原因是如果其中一份工作 "get stuck" 有一段时间,那么你不太可能注意到这一点。

这应该确保本地计算机上 100% 的 CPU 处于忙碌状态。

如果可行,我们需要将这项工作分配给远程机器:

parallel -j1 -a example.lst --env dowork --pipepart --slf $PBS_NODEFILE --block -10 dowork

每个 CPU 线程总共应该启动 10 ssh(即 5*72*10)- 即每个块一个。每个服务器 1 运行ning 在 $PBS_NODEFILE 中并行列出。

不幸的是,这意味着 --joblog--resume 将不起作用。目前没有办法使这项工作,但如果它对你有价值,请通过 parallel@gnu.org.

与我联系