Multithreading 如何在Perl中开始多线程
我有一个perl程序,运行时间超过13个小时。我认为引入多线程可能会使它受益,但我以前从未这样做过,我不知道如何开始 以下是我的情况: 我有一个包含数百个文本文件的目录。我使用基本for循环遍历目录中的每个文件,并进行一些处理(对文件本身进行文本处理,对文件调用外部程序,并对其进行压缩)。完成后,我将转到下一个文件。我继续这样做,以串行方式一个接一个地处理每个文件。这些文件彼此完全独立,并且进程不返回任何值(成功/失败代码除外),因此这似乎是多线程的一个很好的候选者 我的问题是:Multithreading 如何在Perl中开始多线程,multithreading,perl,Multithreading,Perl,我有一个perl程序,运行时间超过13个小时。我认为引入多线程可能会使它受益,但我以前从未这样做过,我不知道如何开始 以下是我的情况: 我有一个包含数百个文本文件的目录。我使用基本for循环遍历目录中的每个文件,并进行一些处理(对文件本身进行文本处理,对文件调用外部程序,并对其进行压缩)。完成后,我将转到下一个文件。我继续这样做,以串行方式一个接一个地处理每个文件。这些文件彼此完全独立,并且进程不返回任何值(成功/失败代码除外),因此这似乎是多线程的一个很好的候选者 我的问题是: 如何重写基本循
如果您有任何建议,我们将不胜感激。因为您的线程只是要启动一个进程并等待它结束,所以最好绕过中间商,只使用进程。除非您使用的是Windows系统,否则我建议您在场景中使用Parallel::ForkManager
use Parallel::ForkManager qw( );
use constant MAX_PROCESSES => ...;
my $pm = Parallel::ForkManager->new(MAX_PROCESSES);
my @qfns = ...;
for my $qfn (@qfns) {
my $pid = $pm->start and next;
exec("extprog", $qfn)
or die $!;
}
$pm->wait_all_children();
如果希望避免在Windows中使用不必要的中间线程,则必须使用类似于以下内容的内容:
use constant MAX_PROCESSES => ...;
my @qfns = ...;
my %children;
for my $qfn (@qfns) {
while (keys(%children) >= MAX_PROCESSES) {
my $pid = wait();
delete $children{$pid};
}
my $pid = system(1, "extprog", $qfn);
++$children{$pid};
}
while (keys(%children)) {
my $pid = wait();
delete $children{$pid};
}
由于您的线程只是要启动一个进程并等待它结束,所以最好绕过中间商,只使用进程。除非您使用的是Windows系统,否则我建议您在场景中使用Parallel::ForkManager
use Parallel::ForkManager qw( );
use constant MAX_PROCESSES => ...;
my $pm = Parallel::ForkManager->new(MAX_PROCESSES);
my @qfns = ...;
for my $qfn (@qfns) {
my $pid = $pm->start and next;
exec("extprog", $qfn)
or die $!;
}
$pm->wait_all_children();
如果希望避免在Windows中使用不必要的中间线程,则必须使用类似于以下内容的内容:
use constant MAX_PROCESSES => ...;
my @qfns = ...;
my %children;
for my $qfn (@qfns) {
while (keys(%children) >= MAX_PROCESSES) {
my $pid = wait();
delete $children{$pid};
}
my $pid = system(1, "extprog", $qfn);
++$children{$pid};
}
while (keys(%children)) {
my $pid = wait();
delete $children{$pid};
}
有人给了你一个很好的例子。fork不是Windows上的原生版本,所以我倾向于使用线程 为了完整性,这里有一个线程工作原理的大致概念(IMO是更好的方法之一,而不是重新启动线程)
#/usr/bin/perl
严格使用;
使用警告;
使用线程;
使用线程::队列;
我的$nthreads=5;
我的$process_q=Thread::Queue->new();
我的$failed_q=Thread::Queue->new();
#这是一个子例程,但它“作为线程”运行。
#当它启动时,它继承程序状态“原样”。例如。
#以上所有变量声明都适用,但对
#程序中的值为“线程本地”,除非
#变量定义为“共享”。
#幕后-Thread::Queue是“共享”数组。
下属{
#注意-这将无限期地循环,直到您关闭队列。
#使用$process_q->end
#一旦我们把所有我们想处理的事情都排好队,我们就会这样做
#潜艇完成并整齐地退出。
#然而如果你不结束它,这将永远等待。
while(my$server=$process\u q->dequeue()){
chomp($server);
打印线程->self()->tid()。“:pinging$server\n”;
my$result=`/bin/ping-c1$server`;
如果($?){$failed\u q->enqueue($server)}
打印$result;
}
}
#将任务插入线程队列。
打开(我的$input_fh,“有人给了你一个分叉的例子。分叉不是Windows上固有的,所以我倾向于使用线程
为了完整性,这里有一个线程工作原理的大致概念(IMO是更好的方法之一,而不是重新启动线程)
!/usr/bin/perl
严格使用;
使用警告;
使用线程;
使用线程::队列;
我的$nthreads=5;
我的$process_q=Thread::Queue->new();
我的$failed_q=Thread::Queue->new();
#这是一个子例程,但它“作为线程”运行。
#当它启动时,它继承程序状态“原样”。
#以上所有变量声明都适用,但对
#程序中的值为“线程本地”,除非
#变量定义为“共享”。
#幕后-Thread::Queue是“共享”数组。
下属{
#注意-这将无限期地循环,直到您关闭队列。
#使用$process_q->end
#一旦我们把所有我们想处理的事情都排好队,我们就会这样做
#潜艇完成并整齐地退出。
#然而如果你不结束它,这将永远等待。
while(my$server=$process\u q->dequeue()){
chomp($server);
打印线程->self()->tid()。“:pinging$server\n”;
my$result=`/bin/ping-c1$server`;
如果($?){$failed\u q->enqueue($server)}
打印$result;
}
}
#将任务插入线程队列。
打开(my$input_fh),“抓取文件列表,然后使用并行::ForkManager循环,在该循环中使用exec
启动处理器,则多线程处理不会加快程序的速度。它实际上可能会减慢程序的速度!@AKHolland,文件压缩通常是CPU的任务bound@ikegami这要视情况而定,在着手重写他的程序之前,当然值得做一些评测。@Akhland,profiling?你是说基准测试。由于缓存的原因,很难准确地进行评测,但是following会给出一个想法:time bash-c'extprog file1;extprog file2'
vstime bash-c'extprog file1&extprog file2'
抓取文件列表,然后使用并行::ForkManager循环,在该循环中使用exec
启动处理器。如果您的程序是IO绑定的(听起来可能是),则多线程处理不会加快程序的速度。它实际上可能会减慢程序的速度!@AKHolland,文件压缩通常是CPU的任务bound@ikegami这要视情况而定,在着手重写他的程序之前,当然值得做一些评测。@Akhland,profiling?你是说基准测试。由于缓存的原因,很难准确地进行评测,但是following会给出一个想法:timebash-c'extprog file1;extprog file2'
vstimeba