如何使用多CPU在Linux中更快地进行计算

时间:2015-07-29 04:04:25

标签: linux shell unix parallel-processing mpi

我想加快我在linux中的计算速度?作为示例,我有以下脚本:example.sh

#!/bin/bash
n1=1; n2=1000
while [ $n1 -le $n2 ]
do
cat << EOF > test.f 
       open (1,file='$n1.txt',form='formatted', status='unknown')
       write (1, *) "Hello World!"
       stop;end
EOF
gfortran test.f
./a.out
(( n1++ ))
done

如果我执行上面的example.sh,那么它将执行1000次。我原来的fortran程序有点大,需要大约3分钟才能完成。所以完成我的脚本需要大约2天。那么如何使用多CPU来加快速度呢?我的系统显示CPU:8。

3 个答案:

答案 0 :(得分:3)

GNU Parallel做得很好。

GNU Parallel可用于使用一台或多台计算机并行执行作业。这消除了管理进程的需要,并为我们提供了一种并行执行二进制文件的方法。

因此,您的脚本(让我们称之为test.sh)变为

#!/bin/bash
n1=$1
cat << EOF > test.f 
   open (1,file='$n1.txt',form='formatted', status='unknown')
   write (1, *) "Hello World!"
   stop;end
EOF
gfortran test.f
./a.out

现在可以使用'parallel'调用脚本test.sh,如下所示。

seq 1000 | parallel -j 8 --workdir $PWD ./test.sh {}

-j 8指定要运行的作业数。这将启动./test.sh 1, ./test.sh 2, ./test.sh 3 ... ./test.sh 1000并确保其中8个并行运行。

答案 1 :(得分:2)

此代码将自行执行八次(每次在后台执行),然后等待所有八个代码退出:

#!/bin/bash

if [ "$#" = 0 ]; then

  trap 'kill -9 $job_list' 0  # clean up if given CTRL+C

  i=0; CPUs=8; total=1000
  while [ $i -lt $CPUs ]; do
    from=$((i*total/CPUs+1))
    i=$((i+1))
    to=$((i*total/CPUs))
    bash $0 $from $to &
    job_list="$job_list $!"
  done

  wait
  trap - 0  # done, remove cleanup code
  exit

fi

n1=$1; n2=$2
while [ $n1 -le $n2 ]; do
  cat << EOF > test$n1.f 
         open (1,file='$n1.txt',form='formatted', status='unknown')
         write (1, *) "Hello World!"
         stop;end
EOF
  trap "rm -f test$n1.f a$n1.out" 0
  gfortran test$n1.f -o a$n1.out
  ./a$n1.out
  rm test$n1.f a$n1.out
  (( n1++ ))
done

这将运行给定Fortran代码的125次运行的八个循环。所有八个循环同时运行。

这使用waitjob control:在命令末尾使用&将其作为后台作业运行(并继续运行而不等待它完成),{{1是最近的后台作业的作业规范(我们保存在$!中,因此我们可以在需要时将其删除),$job_list,如果没有参数,将等待 all 继续工作。

答案 2 :(得分:2)

正如其他人所提到的,重写程序以接受命令行参数是值得的。我在下面的示例中扩展了代码:

runfile.f90

program runfile
  character(len=128) :: arg
  integer :: i

  do i = 1,command_argument_count()
     call get_command_argument(i, arg)

     open (1, file=trim(arg) // ".txt", form='formatted', status='unknown')
     write (1, *) "Hello world!"
  end do
end program runfile

然后你可以编译一次这个程序(可能还有一些更积极的编译标志,如果你对速度感兴趣)并与另一个答案中提到的GNU parallel并行化:

seq -w 1000 | parallel -j 8 ./runfile {}

我完成命令行处理的方式就像许多Unix工具一样,所以即使你不进行并行化,你现在也可以像./runfile {01..10}一样调用你的程序进行10次运行。此外,如果文本文件实际上是要处理的内容,您可以稍微修改程序以允许调用./runfile *.txt