Linux下如何使用多cpu提高计算速度

Linux下如何使用多cpu提高计算速度,linux,shell,unix,parallel-processing,mpi,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 te

我想在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
#/bin/bash
n1=1;n2=1000
而[$n1-le$n2]
做
cat测试
打开(1,文件='n1.txt',格式='formatted',状态='unknown')
写下(1,*)“你好,世界!”
停止终止
EOF
gfortran试验
/a.out
((n1++)
完成

如果我执行上面的example.sh,那么它将执行1000次。我最初的fortran程序有点大,每次运行大约需要3分钟。因此,完成我的脚本需要2天左右的时间。那么,如何使用多个CPU来加快速度呢?我的系统显示CPU:8。

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

#!/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
#/bin/bash
如果[“$#”=0];然后
陷阱'kill-9$job_list'0#如果给定CTRL+C,则清除
i=0;CPU=8;总数=1000
而[$i-lt$CPU];做
from=$((i*总计/CPU+1))
i=$((i+1))
to=$((i*总计/CPU))
bash$0$from$to&
job_list=“$job_list$!”
完成
等待
陷阱-0#完成,删除清理代码
出口
fi
n1=1美元;n2=2美元
而[$n1-le$n2];做
cat测试$n1.f
打开(1,文件='n1.txt',格式='formatted',状态='unknown')
写下(1,*)“你好,世界!”
停止终止
EOF
陷阱“rm-f测试$n1.f a$n1.out”0
gfortran测试$n1.f-o a$n1.out
/美元1.5美分
rm测试$n1.f a$n1.out
((n1++)
完成
这将运行给定Fortran代码的125次循环中的8次循环。所有八个循环同时运行


这使用and:在命令末尾使用
&
将其作为后台作业运行(并在不等待它完成的情况下继续运行),
$
是最新后台作业的作业规范(我们将其保存在
$job_list
中,以便在需要时将其杀死),并且
等待
,当没有参数时,将在继续之前等待所有后台作业。

此代码将自身执行八次(每次在后台执行)然后等待全部八个退出:

#!/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
#/bin/bash
如果[“$#”=0];然后
陷阱'kill-9$job_list'0#如果给定CTRL+C,则清除
i=0;CPU=8;总数=1000
而[$i-lt$CPU];做
from=$((i*总计/CPU+1))
i=$((i+1))
to=$((i*总计/CPU))
bash$0$from$to&
job_list=“$job_list$!”
完成
等待
陷阱-0#完成,删除清理代码
出口
fi
n1=1美元;n2=2美元
而[$n1-le$n2];做
cat测试$n1.f
打开(1,文件='n1.txt',格式='formatted',状态='unknown')
写下(1,*)“你好,世界!”
停止终止
EOF
陷阱“rm-f测试$n1.f a$n1.out”0
gfortran测试$n1.f-o a$n1.out
/美元1.5美分
rm测试$n1.f a$n1.out
((n1++)
完成
这将运行给定Fortran代码的125次循环中的8次循环。所有八个循环同时运行

这使用and:在命令末尾使用
&
将其作为后台作业运行(并在不等待它完成的情况下继续运行),
$
是最新后台作业的作业规范(我们将其保存在
$job_list
中,以便在需要时将其删除),并且
等待
,如果没有参数,将等待所有后台作业,然后再继续。

做得很好

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

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

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

做得很好

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

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


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

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

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

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

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

您正在通过脚本编写fortran程序,编译此程序,然后运行它?这一定是你做这件事最糟糕的方式了。将循环和代码全部放在一个fortran程序中,该程序接受输入参数并编译/运行一次。然后我们可以讨论实现MPI。谢谢@NoseKnowsAll。是的,我的剧本写了一个关于堡垒的故事