2010-04-09 70 views
2

我正在運行一個while循環讀取文件中的每一行,然後將該行的數據分叉到子進程。後N行我要等待子進程結束,然後繼續下一個N行等在Perl中叉不工作while從文件中讀while循環

它看起來是這樣的:

while ($w=<INP>) { 

     # ignore file header 
     if ($w=~m/^\D/) { next;} 

     # get data from line 
     chomp $w; 
     @ws = split(/\s/,$w); 

     $m = int($ws[0]); 
     $d = int($ws[1]); 
     $h = int($ws[2]); 

     # only for some days in the year 
     if (($m==3)and($d==15) or ($m==4)and($d==21) or ($m==7)and($d==18)) { 

       die "could not fork" unless defined (my $pid = fork); 

       unless ($pid) { 

         some instructions here using $m, $d, $h ... 

       } 
       push @qpid,$pid; 

       # when all processors are busy, wait for child processes 
       if ($#qpid==($procs-1)) { 
         for my $pid (@qpid) { 
           waitpid $pid, 0; 
         } 
         reset 'q'; 
       } 
     } 
} 

close INP; 

這是行不通的。在第一輪處理之後,我得到一些等於0的PID,@qpid數組被混合起來,並且文件開始在(顯然)隨機的地方被讀取,跳來跳去。最終結果是文件中的大多數行讀取兩到三次。有任何想法嗎?

非常感謝提前,

S.

+2

請'使用strict'和'use warnings'。這些編譯指示很大程度上減少了調試過程中的痛苦。雖然他們對這個問題沒有幫助,但總的來說,他們確實有很大的不同。 – daotoad 2010-04-09 16:14:08

回答

4

你裏面unless ($pid)退出?

如果沒有,那麼你的孩子,在運行命令後,將新增的零$pid到陣列,一般持續運行的應該是父進程的代碼

+0

不,我不是! 解決了這個問題 非常感謝, S. – Sag 2010-04-09 15:23:11

1

我很擔心,你的算法是不是非常有效:

讓基礎工藝叉處理1到N.

如果進程2至N完成,過程1之前,則沒有新進程將被啓動,直到過程1點完成。

而不是試圖讓你的實現的錯誤細節正確,使用Parallel::ForkManager輕鬆獲得工作代碼。

use strict; 
use warnings; 
use Parallel::ForkManager; 

my $pm = Parallel::ForkManager->new($MAX_PROCESSES); 

while(my $w=<INP>) { 

    next if $w=~m/^\D/;  # ignore file header 

    chomp $w; 

    next unless match_dates($w, 
     { m => 3, d => 15 }, 
     { m => 7, d => 18 }, 
     { y => 2008  }, # Added this to show match_dates() capability. 
    ); 

    my $pid = $pm->start and next; 

     .. Do stuff in child here .. 

    $pm->finish; # Terminate child 
} 

close INP; 

# Returns true if ANY of the supplied date templates matches for ALL keys defined in that template. 
sub match_dates { 
    my $string = shift; 

    my %target; 
    @target{qw(m d y)} = split(/\s/,$string); 

    DATE: 
    for my $date (@_) { 

     my @k = keys %$match; 
     my $count = 0; 

     for(@k) { 
      next DATE unless $date{$_} == $target{$_}; 
      $count++; 
     } 

     return 1 if $count == @k; # All keys match 

    } 

    return; 
}