2011-10-27 14 views
2

Perlの可変スレッド数でファイルデータを共有するための信頼性のある方法を探しています。私は、メインスレッドがファイルから行を読み込み、他のワーカースレッドが個々のエントリを処理するような設定をしたいと考えています。Perlのスレッド間でファイルデータを共有するための巧妙な方法

これまでのところ、私はThread :: Queueを使用しようとしましたが、それらには多大な幸運はありませんでした。ファイルの最後に到達すると、スレッドの大部分は、メインスレッドが読み込みを終了してからデータを読み込むのを待っているブロック状態になってしまいます。スレッドはリムーバでやや張り付いていて、join()はそれらを巻き戻すことができません。

キューに対して非ブロックアクセスを使用すると、スレッドは "データを取得しようとすると、その定義されていない、データを取得しようとする... "これは、CPUを壊すと仕事をして終了します。各スレッドは、通常、1つのワーカースレッドしかない場合でも、タイトループの少なくとも数回の反復を取得します。 sleep()は整数値しか取らないので(sleep(0)は役に立たずsleep(1)は遅すぎる)ので、sleep()の投げ込みはあまり役に立ちません。

最適なのは、入力ファイルのストリームを共有し、各スレッドにロックをかけ、そこから行を読み込んだり、ロックを解除したりすることができますが、グロブの共有は禁止されています。私は最初にファイル全体をメモリにロードしますが、ローエンドの推定値として4000万エントリがあるので、それは非常に実現可能ではありません。

これはどこに来ているのですか?私はデータを待っている過度のCPUを浪費しないメ​​インスレッドとワーカースレッドの間でリーダー/プロセッサーの設定を実装し、読み手がファイルの終わりに達すると()対応可能な状態になります。

ありがとうございました!その後、

+0

短時間の遅延や、(shudder) 'select undef、undef、undef、$ short_delay'でも' Time :: HiRes :: sleep'を使用してください。 – mob

答えて

4

は、この小さなテストでは、私のために働きました。 (私は前にスレッドを使用したことはありませんでしたが、過去にフォークとパイプで同じことをしました)。だから、基本的には、あなたが参加する前にスレッドを終了するように指示する必要があります。これは、私はキューにundefを張ります。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use threads; 
use Thread::Queue; 

use constant MAX_THREADS => 5; 

sub process_data 
{ 
    my($q) = @_; 
    while(defined(my $data = $q->dequeue())) 
    { 
     print "Thread[".threads->tid()."]: Processing data($data)\n"; 
    } 

    print "Thread[".threads->tid()."]: Got end message\n"; 
} # END process_data 

# Main program 
{ 
    my @threads; 
    my $q = Thread::Queue->new(); 
    foreach (1 .. MAX_THREAD) 
    { 
     push(@threads, async { process_data($q) }); 
    } 

    while(my $line = <STDIN>) 
    { 
     chop($line); 
     $q->enqueue($line); 
    } 

    foreach my $thread (@threads) 
    { 
     $q->enqueue(undef); 
    } 

    foreach my $thread (@threads) 
    { 
     $thread->join(); 
    } 
} 
+0

悪くない、私はこれを撃つだろうと思う。私は同様のことを考えていましたが、 'undef'を仕上げフラグとして使うことについては考えていませんでした。 –

+0

@ikegamiは私の答えを編集しました。 'async'ブロックは何をしますか?そしてなぜそれが 'threads-> new(" process_data "、$ q)'の前にあったものと違っていますか?不平を言うことなく、ただ学びたいと思う、これはperlのスレッドでの私の最初の遊びでした。 – Sodved

+0

@Sodved、新しいスレッドを開始します。私が編集メッセージで指定したように、参照されていないスタックに関するスレッドに引数を渡すことにはいくつかの問題があります。私は正確な問題を覚えていませんが、私は常に安全な側にいるために 'async'を使います。 – ikegami

2

メインスレッドで読むとラインを処理するためにcoroutinesを使用します。

use strict; 
use warnings; 
use Coro; 

my $sem = Coro::Semaphore->new(10); # maximum of ten semaphores 
while my $line (<$FILE>) { 
    $sem->down; 
    async { 
     dostuff($line); 
     $sem->up; 
    }; 
} 
+0

私の唯一の懸念は、行の処理が通常の行の読み取り操作よりも長くかかることです。これは、共同作業が完了するよりも早く開始されることを意味します。私はバランシングポイントがあると確信していますが、それは偶然にそれを残しているように感じる。私はおそらくあまりにもかわいいです。 –

+0

さて、それを解決するためのアップデートを見てください。 –

関連する問題