2014-09-30 43 views
0

我写一个脚本如果我设置0之间的参数为1,这取一系列参数的命令行多芯和并行处理运行脚本

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) { 
... 

}}}}} 

,它需要很长的时间。最简单的方法是将它们分成更小的间隔,如

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

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

有人可以指导我如何自动做到这一点?

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

+0

在同一台机器上一次打开100个屏幕,并在其上运行100个不同的脚本不会并行任何操作。如果你的机器有2个内核,操作系统可能会分配核心1上的前50个脚本和核心2上的下50个脚本 – arunmoezhi 2014-09-30 19:55:46

+1

你究竟在做什么?这看起来像一大堆嵌套的迭代......但是这没有任何作用。无论如何,perl支持线程和分叉来执行并行代码。最适合的问题是你想要完成什么的问题。 – Sobrique 2014-09-30 19:57:44

+0

你尝试过什么吗?您是否查看过在核心之间分配工作的perl方法?鉴于你如何分割它们的例子,解决方案不是向你展示吗?是否提醒您可以使用'&'help在shell的后台运行脚本? – 2014-09-30 19:57:49

回答

2

启动255个paralell过程的真正关键的问题是依赖性。我会假设 - 因为你的脚本可以细分 - 你在循环内没有做任何复杂的事情。

但是因为你正在步进0.001和5个循环,所以你只需要做很多次迭代,如果你想从0到1的话。

为了平行,我个人建议你'展开'外环,并使用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; 
} 

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

但请记住 - 这只适用于微不足道的'cpu密集型'任务。如果你正在做大量的磁盘IO或试图共享内存,这将不会有效。

另请注意 - 如果外环上的步数少于CPU的数量,它将不会平行。

我也注意到 - $k2有一个较小的迭代器。我从源头上复制了这些内容,但可能是拼写错误。

+1

非常感谢。很有帮助。 $ k2有一个较小的迭代器。这是正确的 – EpiMan 2014-09-30 20:57:14

+0

当我在文件中输出嵌套循环时,遇到了一个问题。我已经发布(http://stackoverflow.com/questions/26179647/perl-problems-printing-nested-loop-output-after-parallelizing)。 – EpiMan 2014-10-03 15:02:44

+0

是的,使用'fork()'的缺点之一是你在做IO时会遇到竞争条件。保存结果并将它们提供给'$ k1.results'会起到诀窍的作用,因为$ k1在每个分支中都会有所不同。但要记住,IO往往是并行处理的限制因素。 – Sobrique 2014-10-04 15:54:36

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本身提供的各种平行工具。

1

terdon的回答变:

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

会看着并行代码时,在接下来的形式

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