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

Multithreading 如何在perl中将嵌套for循环转换为多线程程序,multithreading,perl,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 .... } } } 对于(my$i=0;$i我将提供一个我以前使用过的示例-关

我需要帮助将嵌套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 ....                 
         } 
     }
 }

对于(my$i=0;$i我将提供一个我以前使用过的示例-关键问题是-您的作业是否完全解耦?例如,无需在它们之间移动数据

如果是这样的话,请使用下面的代码:

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();
使用Parallel::ForkManager;
我的$fork#u manager=Parallel::ForkManager->new(10);#10并行
对于(我的$i=0;$i开始和下一步;
对于(my$j=0;$j<100;$j++){
对于(my$k=0;$k<100;$k++){
#做点什么。。。。
}
}
$fork_manager->finish;
}
$fork_manager->wait_all_children();
对于
$i
的每次迭代,这将分叉代码并并行运行,
ForkManager
将并发限制在10

这个数字应该与并行性中的限制因素大致相当——如果是CPU,则是CPU的数量,但请记住,您通常更受磁盘IO的限制

执行并行时的关键注意事项:

  • 你不能保证执行顺序不乱。完全有可能循环
    $i==1
    在循环
    $i==2
    之后或之前完成。或者其他任何情况

  • 如果您在循环之间传递信息,并行会失去效率-因为发送方和接收方都需要同步。如果您需要同步整批信息,则情况会更糟,因此尽量避免进行不必要的同步(例如,尽可能将其留到最后并整理结果)

  • 对于分叉代码来说,这是双重的——它们是独立的进程,所以您实际上必须尝试来回传输东西

  • 由于第一点,您可以从并行代码中得到一些非常有用的bug。代码的各行可能以任何顺序出现,因此可能会发生非常奇怪的事情。每个进程都会按顺序进行,但多个进程可能会交错。一些无害的东西,如
    open(my$file,“>>”,$output\u filename);
    会把你绊倒的

  • <> > Pr>在叉之间共享数据的能力是非常有限的。如果需要做很多事情,请考虑线程代替。

线程是一种可选的并发模式,在某些情况下可能很有价值。我通常倾向于
fork
ing通常“更好”,但在我希望进行相当多的进程间通信的地方,我倾向于更多地关注
线程。

循环执行块是相互依赖的吗?还是顺序无关紧要?例如,如果在i=3的块之前执行i=5的块,这对您有关系还是相同?这个问题直接影响解决方案,我会选择
Parallel::ForkManager
,因为这看起来是隐式并行的。我可以按任何顺序运行循环只有它们才能成功运行,然后只有主程序才能退出上面的10个实例,i值从1到100,如果我想分割循环,使每个作业实例都以1到10,10到20,20到30,30到40…的值运行,直到100。它将在每次迭代中启动一个实例。因此,最初-10个作业,1..10。作为其中之一完成后,它将从11开始。这样您就可以按顺序处理它们,但始终有10个同时进行。如果您真的想分割它们,那么每个分支都会执行1..10、11..20等操作。您可以,但您需要更改循环。我想问您为什么需要费心,因为创建分支流程是高效的。
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();