Multithreading Perl手动模块到线程
我正在尝试使用以下代码将一个子例程从自写模块传递到线程 这是我第一次使用线程,所以我对它不太熟悉 主脚本(短端) 模块Multithreading Perl手动模块到线程,multithreading,perl,perl-module,Multithreading,Perl,Perl Module,我正在尝试使用以下代码将一个子例程从自写模块传递到线程 这是我第一次使用线程,所以我对它不太熟悉 主脚本(短端) 模块 package goldstandard; use strict; use warnings; sub mate_tagging{ my $Referenz = shift; my $input = shift; my $output_temp_dir = shift; my $output_mate_human = shift; my
package goldstandard;
use strict;
use warnings;
sub mate_tagging{
my $Referenz = shift;
my $input = shift;
my $output_temp_dir = shift;
my $output_mate_human = shift;
my $anna = shift;
my $model = shift;
opendir(DIR,"$input");
my @dir = readdir(DIR);
my $anzahl = @dir;
foreach(@dir){
unless($_ =~ m/^\./){
my $name = $_;
my $path = $input . $_;
my $out_temp = $output_temp_dir . $name;
my $out_mate_human_final = $output_mate_human . $name;
qx(java -Xmx10G -classpath $anna is2.tag.Tagger -model $model -test $path -out $out_temp);
open(OUT, "> $out_mate_human_final");
open(TEMP, "< $out_temp");
my $output_text;
while(<TEMP>){
unless($_ =~ m/^\s+$/){
if ($_ =~ m/^\d+\t(.*?)\t_\t_\t_\t(.*?)\t_\t/) {
my $tags = $2;
my $words = $1;
print OUT "$words\t$tags\n";
}
}
}
}
}
}
sub morpheus_tagging{
my $Referenz = shift;
my $input = shift;
my $output = shift;
my $stemlib = shift;
my $cruncher = shift;
opendir(DIR,"$input");
my @dir = readdir(DIR);
foreach(@dir){
unless($_ =~ m/^\./){
my $name = $_;
my $path = $input . $_;
my $out = $output . $name;
qx(env MORPHLIB='$stemlib' '$cruncher' < '$path' > '$out');
}
}
}
1;
我猜我称之为踏板的方式或者我提供论点的方式是错误的。我希望有人能帮我?我还发现了一些关于安全和不安全模块的问题,我不确定这是否真的是问题所在
我猜我称之为踏板的方式或者我提供论点的方式是错误的。我希望有人能帮我?我在安全和不安全模块上也发现了一些问题,我不确定这是否真的是问题所在。请提前感谢您必须将子模块的名称或子模块的引用以及参数传递给
线程->创建。所以你需要像
my $method_ref = $invoker->can($method_name);
threads->create($method_ref, $invoker, @args);
也就是说,将参数传递给threads->create
有一些问题,可以通过使用闭包来避免
threads->create(sub { $invoker->$method_name(@args) })
上述内容可以更简单地写如下:
async { $invoker->$method_name(@args) }
这使我们了解到:
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @jobs;
for (keys %hash) {
if (/mate/) {
push @jobs, [ 'goldstandard', 'mate_tagging',
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
];
}
if (/morpheus/) {
push @jobs, [ 'goldstandard', 'morpheus_tagging',
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
];
}
}
my @threads;
for my $job (@jobs) {
my ($invoker, $method_name, @args) = @$job;
push @threads, async { $invoker->$method_name(@args) };
}
$_->join for @threads;
}
或者只是
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @threads;
for (keys %hash) {
if (/mate/) {
push @threads, async {
goldstandard->mate_tagging(
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
);
};
}
if (/morpheus/) {
push @threads, async {
goldstandard->morpheus_tagging(
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
);
};
}
}
$_->join for @threads;
}
注意,我延迟了对join
的调用,直到创建了所有线程。您的方式使得一次只能运行一个线程
但我们所拥有的并不伟大。我们无法限制一次有多少线程处于活动状态,我们(昂贵地)创建了许多线程,而不是重用它们。我们可以使用工作人员池来解决这两个问题
use constant NUM_WORKERS => 5;
use Thread::Queue 3.01 qw( );
my $q;
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @threads;
for (keys %hash) {
if (/mate/) {
$q->enqueue(sub {
goldstandard->mate_tagging(
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
);
});
}
if (/morpheus/) {
$q->enqueue(sub {
goldstandard->morpheus_tagging(
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
);
});
}
}
}
{
$q = Thread::Queue->new();
for (1..NUM_WORKERS) {
async {
while ( my $job = $q->dequeue() ) {
$job->();
}
};
}
... call tagging and whatever ...
$q->end();
$_->join() for threads->list();
}
必须将子对象的名称或子对象的引用以及参数传递给threads->create
。所以你需要像
my $method_ref = $invoker->can($method_name);
threads->create($method_ref, $invoker, @args);
也就是说,将参数传递给threads->create
有一些问题,可以通过使用闭包来避免
threads->create(sub { $invoker->$method_name(@args) })
上述内容可以更简单地写如下:
async { $invoker->$method_name(@args) }
这使我们了解到:
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @jobs;
for (keys %hash) {
if (/mate/) {
push @jobs, [ 'goldstandard', 'mate_tagging',
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
];
}
if (/morpheus/) {
push @jobs, [ 'goldstandard', 'morpheus_tagging',
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
];
}
}
my @threads;
for my $job (@jobs) {
my ($invoker, $method_name, @args) = @$job;
push @threads, async { $invoker->$method_name(@args) };
}
$_->join for @threads;
}
或者只是
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @threads;
for (keys %hash) {
if (/mate/) {
push @threads, async {
goldstandard->mate_tagging(
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
);
};
}
if (/morpheus/) {
push @threads, async {
goldstandard->morpheus_tagging(
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
);
};
}
}
$_->join for @threads;
}
注意,我延迟了对join
的调用,直到创建了所有线程。您的方式使得一次只能运行一个线程
但我们所拥有的并不伟大。我们无法限制一次有多少线程处于活动状态,我们(昂贵地)创建了许多线程,而不是重用它们。我们可以使用工作人员池来解决这两个问题
use constant NUM_WORKERS => 5;
use Thread::Queue 3.01 qw( );
my $q;
sub tagging {
my %hash = goldstandard->tagging_hash(\%folder);
my @threads;
for (keys %hash) {
if (/mate/) {
$q->enqueue(sub {
goldstandard->mate_tagging(
$hash{$_}{raw},
$hash{$_}{temp},
$hash{$_}{tagged},
$mate_anna,
$mate_model,
);
});
}
if (/morpheus/) {
$q->enqueue(sub {
goldstandard->morpheus_tagging(
$hash{$_}{source},
$hash{$_}{tagged},
$morpheus_stemlib,
$morpheus_cruncher,
);
});
}
}
}
{
$q = Thread::Queue->new();
for (1..NUM_WORKERS) {
async {
while ( my $job = $q->dequeue() ) {
$job->();
}
};
}
... call tagging and whatever ...
$q->end();
$_->join() for threads->list();
}
明确地说,create
的第一个参数必须是包含为线程提供代码的子例程名称的字符串,或者是对该子例程的引用。以下任何参数都将作为调用的参数直接传递给子例程。您已经传递了一个未编译的Perl代码字符串,这两个选项都不是。此外,goldstandard->morpheus\u tagging
是一个类方法调用,它将字符串goldstandard
作为第一个参数传递。明确地说,create
的第一个参数必须是包含为线程提供代码的子例程名称的字符串,或者是对该子例程的引用。以下任何参数都将作为调用的参数直接传递给子例程。您已经传递了一个未编译的Perl代码字符串,这两个选项都不是。此外,goldstandard->morpheus\u tagging
是一个类方法调用,它将字符串goldstandard
作为第一个参数传递。这太神奇了。非常感谢。正如我所看到的,$q->enqueue(sub{…)似乎仍然存在问题,我得到了一个无法对一个未定义的值调用方法“enqueue”…但是如果它自己使用的话,它是被定义和工作的。这太神奇了。谢谢!正如我所看到的,$q->enqueue(sub{…)似乎仍然存在问题,我得到了一个无法调用方法“enqueue”在一个未定义的值上…但是它是定义的,如果它自己使用的话就可以工作。