2010-03-11 4 views
2

J'ai un script qui utilise Parallel::ForkManager. Cependant, le processus wait_all_children() prend un temps incroyablement long même après que tous les processus fils soient terminés. La façon dont je sais est en imprimant des timestamps (voir ci-dessous). Est-ce que quelqu'un a une idée de ce qui pourrait causer cela (j'ai 16 cœurs de processeur sur ma machine)?Perl Parallel :: ForkManager wait_all_children() prend trop de temps

my $pm = Parallel::ForkManager->new(16); 
for my $i (1..16) { 
    $pm->start($i) and next; 

    ... do something within the child-process ... 

    print (scalar localtime), " Process $i completed.\n"; 
    $pm->finish(); 
} 
print (scalar localtime), " Waiting for some child process to finish.\n"; 
$pm->wait_all_children(); 
print (scalar localtime), " All processes finished.\n"; 

De toute évidence, je reçois le message Waiting for some child process to finish d'abord, avec un horodatage, disons, 7:08:35. Ensuite, je vais obtenir une liste de Process i completed messages, avec le dernier à 7:10:30. Cependant, je ne reçois pas le message All Processes finished jusqu'à 7:16:33 (!). Pourquoi ce délai de 6 minutes entre 7h10 et 7h16? THX!

+0

Est-ce le code que vous utilisez? Il y a une erreur de syntaxe pas si subtile. –

+0

Correction de cette erreur. – Zhang18

Répondre

8

J'ai essayé ceci:

#!/opt/perl/bin/perl 

use strict; use warnings; 

use Parallel::ForkManager; 

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

for my $i (1..16) { 
    $pm->start($i) and next; 
    sleep rand 20; 
    printf "%s : Process %d completed\n", scalar localtime, $i; 
    $pm->finish; 
} 

printf "%s: Waiting for some child to finish\n", scalar localtime; 
$pm->wait_all_children; 

printf "%s: All processes finished.\n", scalar localtime; 

je suis arrivé:

[[email protected] Src]$ ./y.pl 
Thu Mar 11 17:14:16 2010 : Process 3 completed 
Thu Mar 11 17:14:16 2010: Waiting for some child to finish 
Thu Mar 11 17:14:18 2010 : Process 8 completed 
Thu Mar 11 17:14:18 2010 : Process 14 completed 
<snip>...</snip> 
Thu Mar 11 17:14:34 2010 : Process 12 completed 
Thu Mar 11 17:14:34 2010: All processes finished.

Je perl 5.10.1 sur Linux avec la version Parallel::ForkManager0.7.5.

Par conséquent, je conclus que tout problème que vous rencontrez se passe en conséquence de ce qui se passe lorsque vous

# ... do something within the child-process ... 

Mise à jour: Le problème est, vous imprimez la Process finished message avant l'appel finish. Essayez la version suivante:

#!/opt/perl/bin/perl 

use strict; use warnings; 

use Parallel::ForkManager; 

my $pm = Parallel::ForkManager->new(16); 
$pm->run_on_finish(sub { 
    printf "%s : Process completed: @_\n", scalar localtime 
}); 

for my $i (1..16) { 
    $pm->start($i) and next; 
    sleep rand 20; 
    $pm->finish; 
} 

printf "%s: Waiting for some child to finish\n", scalar localtime; 
$pm->wait_all_children; 

printf "%s: All processes finished.\n", scalar localtime; 

Voir Callbacks in Parallel::ForkManager documentation pour plus d'informations. Si le délai disparaît, alors le symptôme que vous observez est dû au fait que vous étiez en train de dire que le processus de fourchettes était terminé avant que cela ne soit fait.

+0

Vous avez raison, Sinan. J'ai oublié de mentionner que ce retard ne m'arrive pas à chaque fois. Cela n'arrive que si chacun de mes processus enfants prend beaucoup de temps et de nombreuses ressources système à terminer. Ce qui me dérange, cependant, c'est que quoi qu'il arrive chez les enfants, après l'impression du dernier «processus que j'ai terminé», cela ne devrait plus être pertinent. Mais voici une sortie réelle que j'ai eu: 08:02:43: En attendant des enfants ... 08:06:00: le groupe 1 est terminé. ... 08:06:12: le groupe 16 est terminé. 08:07:03: Tout est fait. Je me demande si je devrais libérer explicitement de la mémoire/ressource qui bloque l'attente? – Zhang18

+0

@ Zhang18 Voir ma réponse mise à jour en utilisant le rappel 'run_on_finish'. –

+0

Je vois. Donc, si j'imprime l'horodatage via run_on_finish(), j'obtiens ce que vous attendez (c'est-à-dire qu'il n'y a pas de temps d'attente supplémentaire dû à wait_for_children). Cependant, ma question devient alors pourquoi le processus de l'enfant ne serait pas considéré comme «fini» par la fourche même si littéralement j'ai atteint cette déclaration d'impression à l'intérieur de la boucle? Pour être sûr, je ne fais rien de fantaisie avec la tâche dans la boucle. C'est juste un tas de calculs arithmatiques plus quelques requêtes de base de données et E/S de fichiers. Le retard semble provenir de la méthode $ pm-> finish() qui ne parvient pas à récupérer l'heure de fin réelle du processus enfant. – Zhang18

Questions connexes