 # (Do see 'Performance' / 'Properties of the loop body' below)  [,$finishSub]))
In order to track progress, an optional
$finishSub can be provided. It will be called whenever a child finishes. The return value from the
$conditionSub is remembered and provided to the
$finishSub as a reference:
my $i = 0; my %returnValues = $pl->while ( sub { $i++ < 10 ? $i : 0 }, sub { return ($i, sqrt($i)); }, sub { my ($i) = @_; printf "Child %d has finished\n", $i; } );
. Also, if two different children set a value for the same key, a random one of them will be seen by the parent.).
If you want some measure of exception handling you can use eval in the child like this:
my %errors; $pl->share( \%errors ); my %returnValues = $pl->foreach( [ 0..9 ], sub { # Again, this is executed in a forked child eval { die "Bogus error" if $_ == 3; $_ => sqrt($_); }; if ($@) { $errors{$_} = $@; } }); # Now test %errors. $errors{3} should exist as the only element
Also, be sure not to call exit() in the child. That will just exit the child and that doesn't work. Right now, exit just makes the parent fail no-so-nicely. Patches to this that handle exit somehow are welcome.
Keep in mind that a child process is forked every time while or foreach calls the provided sub. For use of Parallel::Loops to make sense, each invocation needs to actually do some serious work for the performance gain of parallel execution to outweigh the overhead of forking and communicating between the processes. So while sqrt() in the example above is simple, it will actually be slower than just running it in a standard foreach loop because of the overhead.
Also, if each loop sub returns a massive amount of data, this needs to be communicated back to the parent process, and again that could outweigh parallel performance gains unless the loop body does some heavy work too.
On the same VMware host, I ran this script in Debian Linux and Windows XP virtual machines respectively. The script runs a "no-op" sub in 1000 child processes two in parallel at a time
my $pl = Parallel::Loops->new(2); $pl->foreach( [1..1000], sub {} );
For comparison, that took:
7.3 seconds on Linux 43 seconds on Strawberry Perl for Windows 240 seconds on Cygwin for Windows
On some platforms the fork() is emulated. Be sure to read perlfork.
E.g. on Windows, select is only supported for sockets, and not for pipes. So we use temporary files to store the information sent from the child to the parent. This adds a little extra overhead. See perlport for other platforms where there are problems with select. Parallel::Loops tests for a working select() and uses temporary files otherwise.".
See the git source on github
All right reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Peter Valdemar Mørch <peter@morch.com>