2017-12-01 4 views
1

次のコードを使用して、自己記述モジュールからスレッドにサブルーチンを渡そうとしています。Perlハンドモジュールからスレッド

これはスレッドを初めて使用したので、私はそれに慣れていません。

メインスクリプト(shortend)このコードを実行する

#!/usr/bin/perl -w 
use strict; 
use threads; 

use lib 'PATH TO LIB'; 
use goldstandard; 

my $delete_raw_files = 0; 
my $outfolder = /PATH/; 
my %folder = goldstandard -> create_folder($outfolder,$delete_raw_files); 

&tagging if $tagging == 1; 

sub tagging{ 
    my %hash = goldstandard -> tagging_hash(\%folder); 
    my @threads; 
    foreach(keys %hash){ 
     if($_ =~ m/mate/){ 
      my $arguments = "goldstandard -> mate_tagging($hash{$_}{raw},$hash{$_}{temp},$hash{$_}{tagged},$mate_anna,$mate_model)"; 
      push(@threads,$arguments); 
     } 
     if($_ =~ m/morpheus/){ 
      my $arguments = "goldstandard -> morpheus_tagging($hash{$_}{source},$hash{$_}{tagged},$morpheus_stemlib,$morpheus_cruncher)"; 
      push(@threads,$arguments) 
     } 
    } 
    foreach(@threads){ 
     my $thread = threads->create($_); 
     $thread ->join(); 
    } 
} 

モジュール

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; 

は私がeather私はトレッドまたは方法Iを呼び出しています方法を推測

Thread 1 terminated abnormally: Undefined subroutine &main::goldstandard -> morpheus_tagging(...) called at ... line 43. 

を取得議論の提供が間違っている。私はそれで私を助けることができることを願っていますか?私はまた、安全で安全でないモジュールで何かを見つけました。私はこれが本当に問題であるか分かりません。

私はトレッドを呼び出す方法、または私が引数を提供している方法が間違っていると思います。私はそれで私を助けることができることを願っていますか?私も安全で安全でないモジュールで何かを見つけました。私はこれが本当に問題かどうか分かりません。事前にお気軽に

+0

(https://perldoc.perl.org/threads.html)[ 'threads'プラグマのドキュメント]は明らかにcreate''への最初のパラメータはの名前を含む文字列のいずれかでなければならないと述べていますスレッドのコードを提供するサブルーチン、またはそのサブルーチンへの参照。以下のパラメータは、呼び出しのパラメータとしてサブルーチンに直接渡されます。これらのオプションのいずれでもない、コンパイルされていないPerlコードの文字列を渡しました。さらに、 'goldstandard - > morpheus_tagging'は、' goldstandard'という文字列を最初のパラメータとして渡すクラスメソッド呼び出しです。 – Borodin

答えて

4

サブの名前または参照の名前、さらには引数をthreads->createに渡す必要があります。だから、threads->createに引数を渡すと、クロージャを使用することによって回避することが可能な問題を持っている、と述べた

my $method_ref = $invoker->can($method_name); 
threads->create($method_ref, $invoker, @args); 

ようなものが必要。

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; 
} 

ノートへの呼び出しすべてのスレッドが作成されるまであなたの方法は一度に1つのスレッドしか実行されないようにしました。

しかし、私たちが持っているものはあまり良くありません。一度にアクティブになっているスレッドの数を制限する方法はなく、再利用する代わりに多数のスレッドを作成する(費用がかかります)。ワーカープールを使用して、これらの問題の両方を解決することができます。

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(); 
} 
+0

これは素晴らしいです。ありがとうございました! –

+0

私が見る通り、まだ問題があるようです。 $ q-> enqueue(sub {.... 私はundef値でメソッド "enqueue"を呼び出せません...しかし、それは定義されていますすべて単独で使用されている場合は動作します。 –

関連する問題