如何将嵌套的for循环转换为perl中的多线程程序

时间:2014-10-16 12:46:47

标签: multithreading perl

我需要帮助将嵌套的for循环转换为Perl中的多线程程序,例如:

for ( my $i=0; $i<100; $i++) {
    for ( my $j=0; $j<100; $j++ ) {
         for ( my $k=0; $k<100; $k++ ) { 
             #do something ....                 
         } 
     }
 }

有没有办法可以将第一个循环分割成如下并且并行运行

#Job1: 
for ( my $i=0; $i < 40; $i++) {
    for( my $j=0; $j < 100; $j++) {
        for( my $k=0; $k < 100; $k++) {
            #do something ....
         }
     }
 }

#Job2: 
for ( my $i=40; $i < 80; $i++) {
    for( my $j=0; $j<100; $j++) {
        for( my $k=0; $k<100; $k++) {
            #do something ....
         }
     }
 }

#Job3
for ( my $i=80; $i < 100; $i++) {
    for( my $j=0; $j < 100; $j++) {
        for( my $k=0; $k < 100; $k++) {
            #do something ....
         }
     }
 }

如何并行运行每个程序,然后仅在所有子程序Job1,Job2和job3完成时退出主程序。

1 个答案:

答案 0 :(得分:6)

我会提供之前使用的similar answer的参考资料 - 他们的关键问题是 - 您的工作是否完全脱离了?例如。没有数据需要在它们之间移动?

如果是这样,请使用Parallel::ForkManager,它有点像这样:

use Parallel::ForkManager;
my $fork_manager = Parallel::ForkManager -> new ( 10 ); #10 in parallel

for ( my $i=0;$i<100;$i++) {
    #in parallel:
    $fork_manager -> start and next;
    for ( my $j=0; $j < 100; $j++) {
         for ( my $k=0; $k < 100; $k++) { 
             #do something ....
         }
    }
    $fork_manager -> finish;
}
$fork_manager -> wait_all_children();

对于$i的每次迭代,这将代码并且并行运行 - 而ForkManager会将并发性限制为10。

这个数字应该与你的并行性的限制因素大致相当 - 如果是CPU,那么CPU的数量,但请记住,你经常受到磁盘IO的限制。

进行并行时的主要注意事项:

  • 您无法保证执行顺序而不会搞乱。循环$i==1之后循环$i==2完全可能完成。或之前。管他呢。

  • 如果您在循环之间传递信息,并行会失去效率 - 因为发送者和接收者都需要同步。如果你需要同步整个批次会更糟,所以尽量避免这样做。 (例如,尽可能将其保留至结束并整理结果)。

  • 对于分叉代码而言,它是双倍的 - 它们是独立的进程,因此您实际上必须尝试来回传输内容。

  • 由于第一点,您可以从并行代码中获得一些非常果味的错误。各行代码可能以任何顺序出现,因此可能会发生非常奇怪的事情。每个进程将进行排序,但多个进程可能会交错。像open ( my $file, ">>", $output_filename );这样无害的东西会让你失望。

  • 分叉的能力非常有限,它能够在分叉之间共享数据。如果您需要做很多事情,请考虑使用线程。

线程是并发的另一种模式,在某些情况下可能很有价值。我一般都倾向于{{1}一般的“更好”,但在我想要进行相当多的进程间通信的地方,我&#39; d倾向于更多地关注forkPerl daemonize with child daemons