Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a multiprocessing module for Perl?

Is there a multiprocessing module for Perl? Something that has similar functionality to what's offered by Python's multiprocessing module.

I understand I could build similar functionality using Perl, but I'm looking for something already implemented.

like image 958
jkysam Avatar asked Oct 28 '11 15:10

jkysam


People also ask

What is multiprocessing module?

multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads.

Is multiprocessing a standard library?

multiprocess leverages multiprocessing to support the spawning of processes using the API of the python standard library's threading module. multiprocessing has been distributed as part of the standard library since python 2.6.

When would you use a multiprocessing pool?

Use the multiprocessing. Pool class when you need to execute many short- to modest-length tasks throughout the duration of your application. Use the multiprocessing. Pool class when you need to execute tasks that may or may not take arguments and may or may not return a result once the tasks are complete.

What is multiprocessing dummy?

multiprocessing. dummy replicates the API of multiprocessing but is no more than a wrapper around the threading module. That means you're restricted by the Global Interpreter Lock (GIL), and only one thread can actually execute CPU-bound operations at a time. That's going to keep you from fully utilizing your CPUs.


2 Answers

forks provides the same awesome interface as threads, but uses processes instead of threads.

use forks;  # Or: use threads;
use Thread::Queue;

my $q = Thread::Queue->new();

my @workers;
for (1..NUM_WORKERS) {
   push @workers, async {
      while (defined(my $job = $q->dequeue())) {
         ...
      }
   };
}

$q->enqueue(...);

$q->enqueue(undef) for @workers;
$_->join for @workers;

Comparing forks with Forks::Super.

Keep in mind, these are suppose to the be the cases where Forks::Super excels!

use Forks::Super;
sub do_something { my @args = @_; ... }
$process = fork { sub => \&do_something, args => [@args] };
$process->wait;

can be written as

use forks;
sub do_something { my @args = @_; ... }
$process = async { do_something(@args) };
$process->join;

---

use Forks::Super;
my $x = 42;
my @y = ();
my %z = ();
sub do_something_else {
    $x = 19;
    @y = qw(foo bar);
    %z = (foo => 'bar');
}
$process = fork { sub => 'do_something_else', share => [\$x, \@y, \%z ] };
$process->wait;

can be written as

use forks;
use forks::shared;
my $x :shared = 42;
my @y :shared = ();
my %z :shared = ();
sub do_something_else {
    $x = 19;
    @y = qw(foo bar);
    %z = (foo => 'bar');
}
$process = async { do_something_else() };
$process->join;

---

use Forks::Super;
use IO::Handle;
pipe my $child_read, my $parent_write;
pipe my $parent_read, my $child_write;
$parent_write->autoflush(1);
$child_write->autoflush(1);
sub square {
    while (my $x = <$child_read>) {
        chomp($x);
        print {$child_write} $x ** 2, "\n";
    }
    close $child_write;
}
$process = fork { sub => 'square' };
print { $parent_write } "9\n";
chomp( my $result = <$parent_read> );  # 81
close $parent_write;
$process->wait;

can be written as

use forks;
use Threads::Queue;
my $req = Threads::Queue->new();
my $resp = Threads::Queue->new();
sub square { $_[0] ** 2 }
$process = async {
    while (defined(my $x = $req->dequeue())) {
        $resp->enqueue( square($x) );
    }
};
$req->enqueue(9);
my $result = $resp->dequeue();  # 81
$resp->enqueue(undef);
$process->join;

---

use Forks::Super;
sub square_root {
    sleep 1 && seek STDIN,0,1 while eof(STDIN); # ok, this is a workaround for an existing bug :-(
    while (my $x = <STDIN>) {
        chomp($x);
        print sqrt($x), "\n";
    }
}
$process = fork { sub => 'square_root', child_fh => 'in,out,block' };
$process->write_stdin("81\n");
chomp( $result = $process->read_stdout() );  # 9
$process->close_fh('stdin');
$process->wait;

can be written as

use forks;
use Threads::Queue;
my $req = Threads::Queue->new();
my $resp = Threads::Queue->new();
$process = async {
    while (defined(my $x = $req->dequeue())) {
        $resp->enqueue( sqrt($x) );
    }
};
$req->enqueue(81);
my $result = $resp->dequeue();  # 9
$resp->enqueue(undef);
$process->join;
like image 166
ikegami Avatar answered Nov 05 '22 15:11

ikegami


I think Forks::Super comes pretty close. It has a few features for running an arbitrary subroutine (or external command) in a background process, monitoring and signalling the background process, and making interprocess communication a little less painful.

use Forks::Super;

sub do_something { my @args = @_; ... }
$process = fork { sub => \&do_something, args => [@args] };
$process->wait;


my $x = 42;
my @y = ();
my %z = ();
sub do_something_else {
    $x = 19;
    @y = qw(foo bar);
    %z = (foo => 'bar');
}
$process = fork { sub => 'do_something_else', share => [\$x, \@y, \%z ] };
$process->wait;
# $x, @y, and %z are now updated with changes made in background process


# create your own pipes to use for IPC
use IO::Handle;
pipe my $child_read, my $parent_write;
pipe my $parent_read, my $child_write;
$parent_write->autoflush(1);
$child_write->autoflush(1);
sub square {
    while (my $x = <$child_read>) {
        print {$child_write} $x ** 2, "\n";
    }
    close $child_write;
}
$process = fork { sub => 'square' };
print {$parent_write} "9\n";
my $result = <$parent_read>;    # should be "81\n";
close $parent_write;

# or use the standard I/O handles for IPC
sub square_root {
    sleep 1 && seek STDIN,0,1 while eof(STDIN); # ok, this is a workaround for an existing bug :-(
    while (my $x = <STDIN>) {
        print sqrt($x), "\n";
    }
}
$process = fork { sub => 'square_root', child_fh => 'in,out,block' };
$process->write_stdin("81\n");
$result = $process->read_stdout(); #  =>  "9\n"

Both the multiprocessing module and Forks::Super have a lot of features. Which ones are you specifically interested in?

I am the author of Forks::Super and my goal is to include any features for parallel processing that people find useful, so if there's a feature in multiprocessing that you want in Perl, let me know.

like image 28
mob Avatar answered Nov 05 '22 13:11

mob