2011-11-29 14 views
5

Dizide yüzlerce dosya adı var. Dizideki her 4 dosya için bir alt işlem oluşturmak istiyorum ve bu çocuğun bu 4 dosyanın her birine bir şeyler yapmasını istiyorum. (100 dosya ile, 25 işlem oluşturacağım.)Perl'de fork() nasıl kullanılır?

Çatal olduğunda satırların işlendiği sırayı anlamakta sorun yaşıyorum. Ben böyle bir şey yapabileceğini düşünüyordum, ama ben sıkışmış alıyorum:

foreach $file (@files) { 
if ($f++ % 4 == 0) { 
    my $pid = fork(); 

    if ($pid) { 
    push(@childs, $pid); 
    } 
    elsif ($pid == 0) { 
    ... do stuff to $file ... 
    } 
} 

Bunun doğru olduğunu sanmıyorum ve birinin bana doğru yönde işaret edebilir umut ediyorum. Teşekkürler.

cevap

11

fork'u kullanmayla ilgili sorununuza ek olarak, @files dizininizi daha küçük dört dosya kümesine bölme konusunda da sorun yaşarsınız. Böyle Belki bir şey:

for (my $i = 0; $i < @files; $i += 4) { 

    # take a slice of 4 elements from @files 
    my @files4 = @files[$i .. $i + 3]; 

    # do something with them in a child process 
    if (fork() == 0) { 
     ... do something with @files4 ... 
     exit; # <--- this is very important 
    } 
} 

# wait for the child processes to finish 
wait for 0 .. @files/4; 
+1

'(benim @ dos- yalarının4 = ek yeri (@files, 0, 4)) {' (@files tahrip olsa) iken – ysth

+0

4 ile '$' artırdığınız için, dilimleme sırasında 4 ile çarpmanız gerekmiyor, değil mi? – itzy

+2

'Listeyi kullanın :: Gen 'by'; benim $ files4 için (by 4 => @files) {$ files4 ile bir şeyler yapın} ' –

1

i grubun bir diziye ve izin çocuk idare edeceğini grup

my $group = [] 
foreach my $file (@files) { 
    push @$group, $file; 

    if(scalar(@$group) % 4 == 0) { 
     my $pid = fork; 
     die "Unable to fork!" unless defined $pid; 
     push @childs, $pid if $pid; 
     children_work($group) unless $pid; 
     $group = []; 
    }   
} 

sub children_work { 
    my $group = shift; 

    // child, work with $group 
    exit(0); 
} 
3

Kullanım Parallel::ForkManager

bu hala 100 süreçlerini oluşturur
use Parallel::ForkManager qw(); 

my $pm = Parallel::ForkManager->new(int(@files/4)); 
for my $file (@files) { 
    my $pid = $pm->start and next; 

    ... do something with $file ... 

    $pm->finish; # Terminates the child process 
} 

Not sadece eşzamanlı olarak 25 ile sınırlar.

gerçekten sadece 25 süreçleri istiyorsanız, aşağıdakileri kullanabilirsiniz:

use List::Util   qw(min); 
use Parallel::ForkManager qw(); 

my $pm = Parallel::ForkManager->new([email protected]); 
while (@files) { 
    my @batch = @files[0..min(4, $#files)]; 
    my $pid = $pm->start and next; 

    for my $file (@batch) { 
     ... do something with $file ... 
    } 

    $pm->finish; # Terminates the child process 
} 
İlgili konular