2011-11-29 39 views
5

Tengo cientos de nombres de archivos en una matriz. Quiero crear un proceso hijo para cada 4 archivos en la matriz y hacer que ese niño haga algunas cosas en cada uno de esos 4 archivos. (Entonces, con 100 archivos, crearé 25 procesos).¿Cómo usar tenedor() en Perl?

Tengo problemas para entender el orden en que se procesan las líneas cuando hay un tenedor. Estaba pensando en lo que podía hacer algo como esto, pero estoy quedarse atascado:

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

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

no creo que esto es correcto, y yo estoy esperando que alguien me puede apuntar en la dirección correcta. Gracias.

Respuesta

11

Además de su problema al usar fork, también parece tener problemas para particionar su matriz @files en conjuntos más pequeños de cuatro archivos. Tal vez algo como esto:

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

'while (mis @ files4 = empalme (@files, 0, 4)) {' (@files destruye, sin embargo) – ysth

+0

Dado que estás incrementando '$ i' en 4, no necesitas multiplicarlo por 4 al cortar, ¿no? – itzy

+2

'use List :: Gen 'by'; para mis $ archivos4 (por 4 => archivos @) {hacer algo con @ $ archivos4} ' –

1

i agruparía a una matriz, y dejar que el niño manejar ese grupo

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

Uso Parallel::ForkManager

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 
} 

Tenga en cuenta que esto todavía crea 100 procesos, simplemente lo limita a 25 concurrentes.

Si realmente quiere sólo 25 procesos, puede utilizar el siguiente:

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 
}