Как использовать fork () в Perl? - PullRequest
6 голосов
/ 30 ноября 2011

У меня есть сотни имен файлов в массиве. Я хочу создать дочерний процесс для каждых 4 файлов в массиве и сделать так, чтобы этот дочерний элемент сделал что-то для каждого из этих четырех файлов. (Итак, из 100 файлов я создам 25 процессов.)

У меня возникли проблемы с пониманием порядка, в котором обрабатываются строки при наличии разветвления. Я думал, что смогу сделать что-то подобное, но я застреваю:

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

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

Я не думаю, что это правильно, и я надеюсь, что кто-то может указать мне правильное направление. Спасибо.

Ответы [ 3 ]

12 голосов
/ 30 ноября 2011

Помимо проблем с использованием fork, вам также кажется, что у вас есть проблемы с разбиением массива @files на более мелкие наборы из четырех файлов. Может быть, что-то вроде этого:

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;
4 голосов
/ 30 ноября 2011

Использовать 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
}

Обратите внимание, что при этом все еще создается 100 процессов, просто ограничивается 25 одновременными.25 процессов, вы можете использовать следующие:

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

my $pm = Parallel::ForkManager->new(0+@files);
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
}
1 голос
/ 30 ноября 2011

Я бы сгруппировался в массив, и пусть дочерний процесс обрабатывает эту группу

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...