MULTIPROCESO PERL FORK

1) INTRODUCCIÓN.
Muchas veces realizamos acciones que pueden hacerse en paralelo,
por ejemplo generar 6 tomos de un libro en latex. Cada tomo puede generarse
de forma independiente.

El objetivo es que si se tienen 4 procesadores cada procesador genere
un libro, y cuando termine siga generando otro libros.

La conclusión es que tarda 1/3 parte menos de tiempo en realizar
las tareas.

Esta basado en el programa jigl, que genera albunes de fotos, a una
velocidad de vértigo) el cual consulte las fuentes
para poder hacer mi propio script.

2) SCRIPT EN PERL

#!/usr/bin/perl -w
# Por Paco Aldarias
# Fecha: 12/12/2010
# Pasado en: jigl
# Script que genera tomos en paralelo

use Cwd;

my $MP_MAX_JOBS = mp_detect_cpu();
print «Número procesadores: $MP_MAX_JOBS»;
my $startDir = cwd;

&main();

###########################################################
sub mp_detect_cpu
{
my $r = `grep processor /proc/cpuinfo |wc -l`;
mp_debug(«Detected $r cpu.n»);
return $r;
}
###########################################################
sub mp_debug($)
{
print «mp[$$]: «. $_[0];
}
###########################################################
sub mp_wait_jobs($)
{
my($n) = @_;

while(1){
my $running = scalar(keys %mp_jobs);
mp_debug(«$running job(s) currently running.n»);

last if $running <= $n; mp_debug(«Waiting…n»); # Wait for a job to finish. my $c = wait(); my $rc = $?; mp_debug(«-> $c ($rc)n»);

# Sanity checks.
if($c < 0){
print «mp: wait() returned $c. Strange!n»;
}

if(!exists $mp_jobs{$c}){
print «mp: wait() returned $c, but job is not»
.» in mp_jobs. Strange!n»;
}

# Check the return code and die if non-zero.
die $mp_jobs{$c} if $rc;

# Forget job.
delete $mp_jobs{$c};
}
}
###########################################################
sub mp_wait_for_free_slot()
{
mp_wait_jobs($MP_MAX_JOBS – 1);
}
###########################################################
sub mp_wait_for_all_jobs()
{
mp_wait_jobs(0);
}
###########################################################
sub mp_launch($$)
{
my($cmd, $die_msg) = @_;

# Wait for a free slot first.
mp_wait_for_free_slot();

# Ok, fork.
my $r = fork();

if(!$r){
# We are in the child.
# Do the job.
mp_debug(«Running $cmd n»);
exec($cmd);

} else {
# We are in the father.
# Remember the child as well as the die msg.
mp_debug(«Launched $r.n»);
$mp_jobs{$r} = $die_msg;
}
}

######################################################3
sub main {

my @carpetas=`find . -type d -name «tic1tomo?-*» | cut -d «/» -f2`;

foreach $c (@carpetas) {

#Eliminamos saltos de linea.
$c =~ s/n//g;
$c =~ s/ //g;

my @f = split(«-«,$c);

print «Carpeta: $c Fichero: $f[0]n»;

chdir $startDir;
chdir «./».$c;
$cmd = «pdflatex -interaction nonstopmode /home/paco/Dropbox/ceed1011/apuntes/».$c.»/».$f[0].».tex -output-directory /home/paco/Dropbox/ceed1011/apuntes/».$c.»/»;
print «Comando: $c»;
$dieMsg = «Mensaje Errorn»;
mp_launch($cmd, $dieMsg);

}

mp_wait_for_all_jobs();

}
######################################3