在多核和并行处理上运行脚本

时间:2014-09-30 19:50:27

标签: linux perl shell

我正在编写一个脚本,它从命令行

获取一系列参数
script.pl start end 

for ($k1=$start; $k1<$end; $k1 += 0.001) {
  for ($k2=$start; $k2<$end; $k2 += 0.01) {
    for ($k3=$start; $k3<$end; $k3 += 0.001) {
      for ($k4=$start; $k4<$end; $k4 += 0.001) {
        for ($k5=$start; $k5<$end; $k5 += 0.001) {
...

}}}}}

如果我将参数设置在0到1之间,则需要很长时间。最简单的方法是将它们分成更小的间隔,如

script.pl 0 0.01 
script.pl 0.01 0.02
...
script.pl 0.9 1

然后我必须同时打开100个屏幕!!

有人可以指导我如何自动完成吗?

我不确定最好的方法是什么,因为这个原因我问道。我有256个核心。

3 个答案:

答案 0 :(得分:2)

查看并行代码时真正关键的问题是依赖关系。我将假设 - 因为你的脚本可以细分 - 你在循环中没有做任何复杂的事情。

但是因为你踩着0.001和5个循环深度,你只是做了很多次迭代,如果你要从0变为1. 100,000,000,000,000,确切地说。

为了并行化,我个人建议您“展开”外部循环并使用Parallel::ForkManager

E.g。

my $CPU_count = 256;

my $fork_manager = Parallel::ForkManager->new($CPU_count);

for ( my $k1 = $start; $k1 < $end; $k1 += 0.001 ) {
    # Run outer loop in parallel
    my $pid = $fork_manager->start and next;

    for ( my $k2 = $start; $k2 < $end; $k2 += 0.01 ) {
        for ( my $k3 = $start; $k3 < $end; $k3 += 0.001 ) {
            for ( my $k4 = $start; $k4 < $end; $k4 += 0.001 ) {
                for ( my $k5 = $start; $k5 < $end; $k5 += 0.001 ) {
                    ...;
                }
            }
        }
    }

    $fork_manager->end;
}

这将做的是 - 对于那个'外部'循环的每次迭代,分叉你的进程并运行4个内部循环作为一个单独的进程。它将限制在256个并发进程。您应该将其与可用的CPU数量相匹配。

请记住 - 这只适用于琐碎的“cpu密集型”任务。如果您正在执行大量磁盘IO或尝试共享内存,这将无法正常工作。

另请注意 - 如果外部循环上的步数少于CPU的数量,则它将无法很好地并行化。

我还要注意 - $k2有一个较小的迭代器。我从你的来源复制了它,但它可能是一个错字。

答案 1 :(得分:1)

我不确定你的意思但是这将在后台并行启动100个工作。请注意,它可以让您的计算机瘫痪,具体取决于您的硬件:

$ seq 0 0.02 0.99 | perl -lne 'print "$_ ",$_+0.01' | 
    while read start end; do script.pl $start $end; done; script.pl 0.99 1

这个想法是使用seq来生成间隔,通过一个打印出对的perl脚本来管道。然后由bash循环读取这些内容,并使用相关参数启动脚本。

但请注意,这远非实现目标的优雅方式。您可能希望研究GNU Parallel或Perl本身可用的各种并行化工具。

答案 2 :(得分:1)

terdon答案的变体:

paste <(seq -w 0 .01 1) <(seq -w 0.01 0.01 1.01) | xargs -n2 -P 255 ./script.pl

将在下一个表单中启动255个并列进程

./script.pl 0.00 0.01
./script.pl 0.01 0.02
...
...
./script.pl 0.98 0.99
./script.pl 0.99 1.00