Amazon ec2 使用并行工具在PBS中运行百万个列表

Amazon ec2 使用并行工具在PBS中运行百万个列表,amazon-ec2,parallel-processing,openmpi,gnu-parallel,pbs,Amazon Ec2,Parallel Processing,Openmpi,Gnu Parallel,Pbs,我有一个巨大的(几百万)作业包含列表,希望运行java编写的工具来执行功能比较。此工具在中完成计算 real 0m0.179s user 0m0.005s sys 0m0.000s sec 在GNU并行环境下,使用pbs torque scheduler运行5个节点(每个节点都有72个CPU),该工具运行良好并产生结果,但当我为每个节点设置72个作业时,它应该一次运行72 x 5个作业,但我只能看到它运行25-35个作业! 检查每个节点上的cpu利用率也会显示低利用率 我希望一次运

我有一个巨大的(几百万)作业包含列表,希望运行java编写的工具来执行功能比较。此工具在中完成计算

real    0m0.179s
user    0m0.005s
sys 0m0.000s sec
在GNU并行环境下,使用pbs torque scheduler运行5个节点(每个节点都有72个CPU),该工具运行良好并产生结果,但当我为每个节点设置72个作业时,它应该一次运行72 x 5个作业,但我只能看到它运行25-35个作业! 检查每个节点上的cpu利用率也会显示低利用率

我希望一次运行72 X 5个或更多作业,并利用所有可用源(72 X 5 CPU)生成结果

正如我提到的,要运行约2亿个作业,我希望通过使用/增加节点/CPU的数量来更快地完成它(1-2小时)

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

example.lst(大约有3亿行)

cat 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 {}
#!/bin/bash 
# parallel command options
i=$1
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
cat run_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 {}
#!/bin/bash 
# parallel command options
i=$1
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个CPU),带有torque调度器和GNU Parallel 2018,2018年3月


更新

通过引入新的函数,该函数在stdin上获取输入,并并行运行脚本,效果非常好,并利用了本地机器上的所有CPU

但是,当它在远程机器上运行时,会产生

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#运行/工作脚本

#!/bin/bash 
i=$1
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

我不确定
工具的功能。但是,如果复制占用了大部分时间,并且
工具
仅读取文件,则您可以将文件符号链接到
$TMP_DIR
中,而不是复制


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

我不确定
工具的功能。但是,如果复制占用了大部分时间,并且
工具
仅读取文件,则您可以将文件符号链接到
$TMP_DIR
中,而不是复制

查看集群中5台机器的
top
,可以很好地指示您是否可以更快地完成此任务。如果他们都以>90%的速度使用所有内核,那么您就不能期望更快地获得这些内核。

从您的计时:

real    0m0.179s
user    0m0.005s
sys 0m0.000s sec
似乎该工具使用的CPU功率非常小。当GNU并行运行本地作业时,每个作业的CPU时间开销为10毫秒。您的作业使用179毫秒的时间和5毫秒的CPU时间。所以GNU并行将使用相当多的时间

远程运行作业时,开销更大。这里我们讨论的是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
通过运行以下命令来测试此功能是否有效:

head -n 1000 example.lst | dowork
然后让我们看看在本地运行作业。这可以像这里描述的那样进行:

这将把
example.lst
拆分为每个CPU线程10个块。因此,在一台有72个CPU线程的机器上,这将产生720个块。它将启动72个
doworks
,完成一个后,将获得720个块中的另一个块。我选择10而不是1的原因是,如果其中一份工作“卡住”了一段时间,那么你不太可能注意到这一点

这应确保本地计算机上的CPU 100%繁忙

如果可行,我们需要将此工作分发到远程机器:

parallel -j1 -a example.lst --env dowork --pipepart --slf $PBS_NODEFILE --block -10 dowork
每个CPU线程(即5*72*10)总共应启动10个
ssh
——即每个块一个。在
$PBS\u NODEFILE
中列出的每台服务器上并行运行1台

不幸的是,这意味着
--joblog
--resume
将无法工作。目前还没有办法做到这一点,但如果对你有价值,请通过以下方式与我联系:parallel@gnu.org.

从您的计时:

real    0m0.179s
user    0m0.005s
sys 0m0.000s sec
似乎该工具使用的CPU功率非常小。当GNU并行运行本地作业时,每个作业的CPU时间开销为10毫秒。您的作业使用179毫秒的时间和5毫秒的CPU时间。所以GNU并行将使用相当多的时间

远程运行作业时,开销更大。这里我们讨论的是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
通过运行以下命令来测试此功能是否有效:

head -n 1000 example.lst | dowork
然后让我们看看在本地运行作业。这可以像这里描述的那样进行:

这将把
example.lst
拆分为每个CPU线程10个块。因此,在一台有72个CPU线程的机器上,这将产生720个块。它将启动72个
doworks
,完成一个后,将获得720个块中的另一个块。我选择10而不是1的原因是,如果其中一份工作“卡住”了一段时间,那么你不太可能注意到这一点

这应确保本地计算机上的CPU 100%繁忙

如果可行,我们需要将此工作分发到远程机器:

parallel -j1 -a example.lst --env dowork --pipepart --slf $PBS_NODEFILE --block -10 dowork
每个CPU线程(即5*72*10)总共应启动10个
ssh
——即每个块一个。在
$PBS\u NODEFILE
中列出的每台服务器上并行运行1台

不幸的是,这意味着
--joblog
--resume
将无法工作。目前没有办法做到这一点