Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Simple Parallel Processing Question

by bichonfrise74 (Vicar)
on Jan 22, 2009 at 01:03 UTC ( [id://737999]=perlquestion: print w/replies, xml ) Need Help??

bichonfrise74 has asked for the wisdom of the Perl Monks concerning the following question:

I was playing with this script and all I want to happen is to make 2 child processes run at the same time. After they are finish, another 2 child processes will run again. What is happening is that all the child processes are running at the same time and in the end, the parents waits for all of them to finish.

This can simply be done in Parallel::ForkManager but I cannot download and install it in our system for security reason.
#!/usr/bin/perl use strict; my @array = qw(a b c d e f g h); my @childs; for (1 .. 10) { my $pid = fork(); if ($pid) { push (@childs, $pid); } else ($pid == 0) { print "@array\n\n"; sleep 10; exit (0); } print "Running another child process - $pid.\n"; } print "All child processes have been ran.\n"; print "@childs\n"; foreach (@childs) { waitpid ($_, 0); } print "All child processes are finished.\n";

Replies are listed 'Best First'.
Re: Simple Parallel Processing Question
by tilly (Archbishop) on Jan 22, 2009 at 01:34 UTC
Re: Simple Parallel Processing Question
by runrig (Abbot) on Jan 22, 2009 at 01:51 UTC
    Parallel::ForkManager is a pure perl module. There is hardly any installing involved. You can just copy and paste the source code into any file of your own making. You can copy or install it to any directory, it doesn't have to be in the regular system library directory (but then you would need to set PERL5LIB or use the 'use lib' directive). You can copy the code directly into your own script if you wanted to. If you can write code, you can use the module.
      That is true, I could just copy the module and rename it as something else and copy it directly into my script.

      But if someone asked me to explain each line of the code, I will not be confident enough to answer it. Plus if someone finds out that I copied it from a CPAN module, then I would be in trouble because I will be violating our 'policy' and it would be considered as plagiarism, right?

      In fact, the policy is really weird because all open source codes need to be reviewed first by our senior developers therefore it will take time to be able to install and implement this module.

      And as someone mentioned, if I 'copied' a small snippet from the web, then it would be fine because it is just 'small'. So, I agree the policy is weird.
        "That is true, I could just copy the module and rename it as something else and copy it directly into my script."

        Don't even rename it. Dump it in any directory you feel fit and use lib.

        "Plus if someone finds out that I copied it from a CPAN module, then I would be in trouble because I will be violating our 'policy' and it would be considered as plagiarism, right?"

        And now you make it sound like it's a school/homework project. The module in question is licensed under the same terms as Perl, so if using Perl is considered plagiarism, yes.

        "And as someone mentioned, if I 'copied' a small snippet from the web, then it would be fine because it is just 'small'."

        The size of the snippet doesn't matter. If you don't know what it does exactly, the security issue still applies. I'd personally trust CPAN modules more than random "snippets".

        --
        b10m
Re: Simple Parallel Processing Question
by hbm (Hermit) on Jan 22, 2009 at 02:09 UTC
    There's this, if you have IO::Socket:
    # Perl Cookbook, 1st Edition, pg. 626 use strict; use IO::Socket; use Symbol; use POSIX qw(:signal_h :errno_h :sys_wait_h); my $PREFORK = 2; # number of kids to maintain my %kids = (); # child process ids my $kids = 0; # number of children my @jobs = qw(a b c d e f g h); sub REAPER { $SIG{CHLD} = \&REAPER; my $pid = waitpid(-1, &WNOHANG); if ($pid == -1) { # ignore - no child waiting } elsif (&WIFEXITED($?)) { $kids--; delete($kids{$pid}); } else { # false alarm } $SIG{CHLD} = \&REAPER; # in case of unreliable signals } sub HUNTSMAN { local($SIG{CHLD}) = 'IGNORE'; kill 'INT' => keys %kids; exit; } sub HEADCOUNT { $PREFORK +=5; print "I have $kids kids; increasing to $PREFORK...\n"; } # install signal handlers $SIG{CHLD} = \&REAPER; $SIG{INT} = \&HUNTSMAN; $SIG{HUP} = \&HEADCOUNT; print "starting $PREFORK users...\n"; for (1 .. $PREFORK) { &make_new_child(shift(@jobs)); } # and maintain population while (scalar @jobs) { # or 'while (1)' for perpetual sleep; # wait for a signal for ($kids .. $PREFORK) { &make_new_child(shift(@jobs)); } } sub make_new_child { my $pid; my $sigset; sleep 3; # block signal for fork $sigset = POSIX::SigSet->new(SIGINT); sigprocmask(SIG_BLOCK, $sigset) or die("Can't block SIGINT for fork +: $!\n"); die "fork: $!" unless defined ($pid = fork); if ($pid) { # parent records child and returns sigprocmask(SIG_UNBLOCK, $sigset) or die("Can't unblock SIGINT f +or fork: $!\n"); $kids{$pid} = 1; $kids++; return; } else { # child must *not* return from this subroutine $SIG{INT} = 'DEFAULT'; # make it kill us as before $SIG{HUP} = 'IGNORE'; # only parent needs this #unblock signals sigprocmask(SIG_UNBLOCK, $sigset) or die("Can't unblock SIGINT f +or fork: $!\n"); # do something my $job = shift; print "I am $$, doing job $job\n"; sleep 10; exit; } }

    I used basically the same to stress an application by perpetually spawning connections and adding heat with HUP.

    Update: Sorry! When I cut-and-pasted this, I missed three essential lines. See the three lines after the comment, "Install signal handlers".

    Update2: I clarified my reference to the Cookbook. I now have the 2nd Edition, which doesn't have the same recipe.

      Hi,

      I tried to run your script but I'm getting this output...
      starting 2 users... I am 23687, doing job a I am 23688, doing job b
      I looked into the code and it should continue doing job c, d, etc... but it simply stopped after this. Any thoughts?
Re: Simple Parallel Processing Question
by JavaFan (Canon) on Jan 22, 2009 at 01:48 UTC
    This can simply be done in Parallel::ForkManager but I cannot download and install it in our system for security reason.
    But the security reasons don't prevent your from copying code from a website (like Perlmonks)? Do the security reasons prevent you from copying the code of Parallel::ForkManager from here?
      My experience suggests that when management says "security" and implements a stupid policy, they are extremely unlikely to respond well to any employees who demonstrate how stupid the policy is.

      Secondly copying the code and inserting it into the codebase carries very real intellectual property risks. Copying a freely available snippet from a website carries far smaller risks, particularly when the author is available to give permission.

      So yeah, it is a stupid rule. But I wouldn't recommend breaking it in an obvious way.

Re: Simple Parallel Processing Question
by zentara (Archbishop) on Jan 22, 2009 at 15:11 UTC
    An oldie but goodie....
    #!/usr/bin/perl #by Abigail of perlmonks.org #Some times you have a need to fork of several children, but you want +to #limit the maximum number of children that are alive at one time. Here #are two little subroutines that might help you, mfork and afork. They + are very similar. #They take three arguments, #and differ in the first argument. For mfork, the first #argument is a number, indicating how many children should be forked. +For #afork, the first argument is an array - a child will be #forked for each array element. The second argument indicates the maxi +mum #number of children that may be alive at one time. The third argument +is a #code reference; this is the code that will be executed by the child. +One #argument will be given to this code fragment; for mfork it will be an + increasing number, #starting at one. Each next child gets the next number. For afork, the + array element is #passed. Note that this code will assume no other children will be spa +wned, #and that $SIG {CHLD} hasn't been set to IGNORE. mfork (10,10,\&hello); sub hello{print "hello world\n";} print "all done now\n"; ################################################### sub mfork ($$&) { my ($count, $max, $code) = @_; foreach my $c (1 .. $count) { wait unless $c <= $max; die "Fork failed: $!\n" unless defined (my $pid = fork); exit $code -> ($c) unless $pid; } 1 until -1 == wait; } ################################################## sub afork (\@$&) { my ($data, $max, $code) = @_; my $c = 0; foreach my $data (@$data) { wait unless ++ $c <= $max; die "Fork failed: $!\n" unless defined (my $pid = fork); exit $code -> ($data) unless $pid; } 1 until -1 == wait; } #####################################################

    I'm not really a human, but I play one on earth Remember How Lucky You Are

      This is wonderfully simple! Where yesterday I processed sequentially like this:

      ... foreach (@jobs) { &process($_); } ...

      Today, in parallel with just a few changes ripped from 'afork':

      ... foreach (@jobs) { die "Fork failed: $!\n" unless defined (my $pid = fork); exit &process($_) unless $pid; } 1 until -1 == wait; ...

      And restrained parallel with three more lines:

      ... my $max = 4; my $c = 0; foreach (@jobs) { wait unless ++$c <= $max; die "Fork failed: $!\n" unless defined (my $pid = fork); exit &process($_) unless $pid; } 1 until -1 == wait; ...

      I wonder where the once-prominent abigail is today...

      This is exactly what I need. I made some modification and it works like a charm.

      Thanks!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://737999]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (1)
As of 2024-04-25 19:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found