views:

274

answers:

5

What modules should I look at for doing multithreading in Perl?

I'm looking to do something fairly low performance; I want threads is to run multiple workers simultaneously, with each of them sleeping for varying amounts of time.

+7  A: 

If performance isn't a big issue, then forking multiple processes will probably be a lot easier than dealing with threads. I frequently use Parallel::ForkManager which is very simple, but very good at what it does.

friedo
+7  A: 

Most recent versions of Perl have threading support. Run perl -V:usethreads to see if it is available in your system.

$ perl -V:usethreads
usethreads='define'

perldoc threads gives a pretty good introduction to using them.

mobrule
Never use ithreads for anything.
jrockway
+5  A: 

It sounds like you don't need preemptive multithreading; in which case, look at POE's cooperative model. Since your code will only yield to other threads when you decide, and you'll only have one thread running at a time, development and debugging will be much easier.

derobert
Worth noting is that while POE doesn't implicitly support multithreading or multiprocessing, `POE::Wheel::Run` lets you run a piece of code in a forked process, translating its I/O and exit status into POE events. Sometimes it's a very useful thing to wrap around blocking code.
hobbs
I second that _
xxxxxxx
A: 

Coro is a nice module for cooperative multitasking.

99% of the time, this is what you need if you want threads in Perl.

If you want threads to speed up your code when multiple cores are available, you are going down the wrong path. Perl is 50x slower than other languages. Rewriting your code to run on two CPUs means that it now only runs 25x slower than other languages ... on one CPU. Better to spend the effort porting the slow parts to a different language.

But if you just don't want IO to block other "threads", then Coro is exactly what you want.

jrockway
There is also development speed.
Alexandr Ciornii
I am tired of this argument :) There are many things I can hack together as quickly in Haskell as in Perl, and Haskell runs much faster than perl.
jrockway
+5  A: 

There are lots of reasons why you might not want to multithread. If you do want to multithread, however, the following code might serve as a helpful example. It creates a number of jobs, puts those in a thread-safe queue, then starts some threads that pull jobs from the queue and complete them. Each thread keeps pulling jobs from the queue in a loop until it sees no more jobs. The program waits for all the thread to finish and then prints the total time that it spent working on the jobs.

#!/usr/bin/perl

use threads;
use Thread::Queue;
use Modern::Perl;

my $queue= Thread::Queue->new;
my $thread_count= 4;
my $job_count= 10;
my $start_time= time;
my $max_job_time= 10;

# Come up with some jobs and put them in a thread-safe queue. Each job
# is a string with an id and a number of seconds to sleep. Jobs consist
# of sleeping for the specified number of seconds.
my @jobs= map {"$_," . (int(rand $max_job_time) + 1)} (1 .. $job_count);
$queue->enqueue(@jobs);

# List the jobs
say "Jobs IDs: ", join(", ", map {(split /,/, $_)[0]} @jobs);

# Start the threads
my @threads= map {threads->create(sub {function($_)})} (1 .. $thread_count);

# Wait for all the threads to complete their work
$_->join for (@threads);

# We're all done
say "All done! Total time: ", time - $start_time;

# Here's what each thread does. Each thread starts, then fetches jobs
# from the job queue until there are no more jobs in the queue. Then,
# the thread exists.
sub function {
  my $thread_id= shift;
  my ($job, $job_id, $seconds);
  while($job= $queue->dequeue_nb) {
    ($job_id, $seconds)= split /,/, $job;
    say "Thread $thread_id starting on job $job_id ",
      "(job will take $seconds seconds).";
    sleep $seconds;
    say "Thread $thread_id done with job $job_id.";
  }
  say "No more jobs for thread $thread_id; thread exiting.";
}
Donnie