2009-12-25 26 views
15

Soy un estudiante de ingeniería aeroespacial, y estoy trabajando en un proyecto final de alto nivel. Uno de los modelos matemáticos que estoy desarrollando requiere una cantidad astronómica de datos generados por XFOIL, una popular herramienta aeroespacial utilizada para encontrar los coeficientes de sustentación y resistencia aerodinámica en los perfiles aerodinámicos. (Pero estoy divagando.)¿Cómo puedo hacer que mi script de Perl use múltiples núcleos para procesos secundarios?

Corte al grano: Tengo un script Perl que llama a XFOIL repetidamente con diferentes parámetros de entrada para generar los datos que necesito. Necesito XFOIL para ejecutar 5600 veces, y tal como está ahora mismo, toma alrededor de 100 segundos en promedio por ejecución. Hacer los cálculos, esto significa que tomará alrededor de 6.5 días para completar.

Ahora, tengo una máquina de cuatro núcleos, pero mi experiencia como programador es limitada, y realmente solo sé cómo usar Perl básico. Me gustaría ejecutar 4 instancias de XFOIL a la vez, todas en su propio núcleo. Algo como esto:

while (1){ 
    for (i = 1..4){ 
     if (! exists XFOIL_instance(i)){ 
      start_new_XFOIL_instance(i, input_parameter_list); 
     } 
    } 
} 

Así que el programa está comprobando (o, preferentemente, dormir hasta que una instancia XFOIL la despierte para comenzar una nueva instancia) si cada núcleo está ejecutando XFOIL. Si no, la instancia anterior salió y podemos comenzar una nueva instancia con la nueva lista de parámetros de entrada.

Si alguien tiene alguna idea de cómo se puede lograr esto, házmelo saber. Esto aceleraría significativamente el tiempo que necesito para generar datos y me permitirá trabajar en el proyecto aeroespacial en sí.

¡Gracias por la ayuda!

+1

Me temo que no voy a dar una respuesta completa, pero la versión corta es que definitivamente puede desechar cuatro instancias de la secuencia de comandos perl actual, y luego hacer que cada una de ellas se descuelgue constantemente para ejecutar una secuencia de comandos XFOIL. Sin embargo, al configurar la afinidad del procesador para los procesos resultantes, eso requeriría saber qué sistema operativo está usando. –

+2

¿Estás seguro de que XFOIL no encadena o usa múltiples procesadores para obtener su tiempo de ejecución en aproximadamente 100 segundos en primer lugar? – dlamblin

+0

¿Sería difícil implementar XFOIL en C/Fortran? Si no, entonces sugeriría que lo hicieras. Perl no es exactamente el Speedy Gonzalez de los lenguajes de programación ... – Zaid

Respuesta

17

Probar Parallel::ForkManager. Es un módulo que proporciona una interfaz simple para bifurcar procesos como este.

Aquí hay un código de ejemplo:

#!/usr/bin/perl 

use strict; 
use warnings; 
use Parallel::ForkManager; 

my @input_parameter_list = 
    map { join '_', ('param', $_) } 
    (1 .. 15); 

my $n_processes = 4; 
my $pm = Parallel::ForkManager->new($n_processes); 
for my $i (1 .. $n_processes) { 
    $pm->start and next; 

    my $count = 0; 
    foreach my $param_set (@input_parameter_list) {   
     $count++; 
     if (($count % $i) == 0) { 
      if (!output_exists($param_set)) { 
       start_new_XFOIL_instance($param_set); 
      } 
     } 
    } 

    $pm->finish; 
} 
$pm->wait_all_children; 

sub output_exists { 
    my $param_set = shift; 
    return (-f "$param_set.out"); 
} 

sub start_new_XFOIL_instance { 
    my $param_set = shift; 
    print "starting XFOIL instance with parameters $param_set!\n"; 
    sleep(5); 
    touch("$param_set.out"); 
    print "finished run with parameters $param_set!\n"; 
} 

sub touch { 
    my $fn = shift; 
    open FILE, ">$fn" or die $!; 
    close FILE or die $!; 
} 

Tendrá que suministrar sus propias implementaciones de las funciones del output_exists start_new_XFOIL_instance y, y usted también desea definir sus propios conjuntos de parámetros a pasar a XFOIL .

+1

Esto parece ser lo que necesito. Leeré en Parallel :: ForkManager y le contaré cómo funciona. ¡Gracias por la ayuda! Por supuesto, se agradece cualquier otra contribución de cualquier otra persona. –

+0

Si aún no lo sabía, puede instalar el módulo Parallel :: ForkManager en su directorio de inicio. Mire aquí cómo hacerlo: http://stackoverflow.com/questions/540640/how-can-i-install-a-cpan-module-into-a-local-directory –

+1

James, muchas gracias por su ayuda. Instalé Parallel :: ForkManager por línea de comandos hace un momento, creo que ya estoy funcionando. Todavía estoy tratando de descubrir las complejidades del módulo y cómo quiero que se comporte en condiciones de error, pero una ejecución preliminar en mi computadora portátil de doble núcleo me lleva a pensar que lo he descubierto, al menos el idea básica, de todos modos. Muchas gracias de nuevo! –

3

Parece que puede usar Gearman para este proyecto.

www.gearman.org

Gearman es una cola de trabajos. Puede dividir su flujo de trabajo en muchas mini partes.

Recomendaría usar amazon.com o incluso sus servidores de subastas para completar este proyecto.

Gastar 10 centavos por hora de computación o menos, puede acelerar significativamente su proyecto.

Usaría Gearman localmente, asegúrese de tener una ejecución "perfecta" para 5-10 de sus subjobs antes de entregárselo a una granja de computación de Amazon.

3

Perl threads aprovechará múltiples núcleos y procesadores. El principal pro de los hilos es que es bastante fácil compartir datos entre los hilos y coordinar sus actividades. Un proceso bifurcado no puede devolver datos fácilmente al padre ni coordinarse entre ellos.

Los principales inconvenientes de los subprocesos de Perl es que son relativamente caros de crear en comparación con un tenedor, deben copiar todo el programa y todos sus datos; debes tenerlos compilados en tu Perl; y pueden tener errores, cuanto más viejo sea el Perl, más errores tendrán los hilos. Si su trabajo es costoso, el tiempo de creación no debería importar.

Aquí hay un ejemplo de cómo puede hacerlo con hilos. Hay muchas maneras de hacerlo, este usa Thread::Queue para crear una gran lista de trabajo que sus hilos de trabajo pueden compartir. Cuando la cola está vacía, los hilos salen. Las principales ventajas son que es más fácil controlar cuántos subprocesos están activos y no es necesario crear un subproceso nuevo y costoso para cada bit de trabajo.

Este ejemplo coloca todo el trabajo en la cola a la vez, pero no hay ninguna razón por la que no pueda agregar a la cola sobre la marcha. Si tuviera que hacer eso, usaría dequeue en lugar de dequeue_nb, que esperará para obtener más información.

use strict; 
use warnings; 

use threads; 
use Thread::Queue; 

# Dummy work routine 
sub start_XFOIL_instance { 
    my $arg = shift; 
    print "$arg\n"; 
    sleep 1; 
} 

# Read in dummy data 
my @xfoil_args = <DATA>; 
chomp @xfoil_args; 

# Create a queue to push work onto and the threads to pull work from 
# Populate it with all the data up front so threads can finish when 
# the queue is exhausted. Makes things simpler. 
# See https://rt.cpan.org/Ticket/Display.html?id=79733 
my $queue = Thread::Queue->new(@xfoil_args); 

# Create a bunch of threads to do the work 
my @threads; 
for(1..4) { 
    push @threads, threads->create(sub { 
     # Pull work from the queue, don't wait if its empty 
     while(my $xfoil_args = $queue->dequeue_nb) { 
      # Do the work 
      start_XFOIL_instance($xfoil_args); 
     } 

     # Yell when the thread is done 
     print "Queue empty\n"; 
    }); 
} 

# Wait for threads to finish 
$_->join for @threads; 

__DATA__ 
blah 
foo 
bar 
baz 
biff 
whatever 
up 
down 
left 
right 
+0

Veo que mi comentario anterior (o su respuesta anterior) ha sido eliminado, de todos modos gracias por actualizar su respuesta. Tengo curiosidad acerca de si, si comprueba que los subprocesos pueden aprovechar múltiples procesadores y núcleos, de ser así, ¿cómo lo verificó? =) – user454322

+0

@ user454322 Después de ver tu comentario, escribí un pequeño script para hacer un ciclo infinito en un grupo de hilos y usé Activity Monitor en OS X para ver que los cuatro núcleos estaban siendo utilizados.Tiene razón acerca de que el modelo de subprocesamiento es un nuevo intérprete de Perl por hilo real. Anteriormente, tenía en mente que todo estaba emulado en un solo proceso. – Schwern

+0

He publicado http://stackoverflow.com/questions/12536064/how-does-perls-threading-system-work, si tiene la oportunidad, eche un vistazo. – user454322

0

Consideró gnu parallel parallel. Le permitirá ejecutar varias instancias de instalación de su programa con diferentes entradas y llene sus núcleos de CPU cuando comiencen disponibles. A menudo es una forma muy simple y eficiente de lograr la paralelización de tareas simples.

0

Esto es bastante viejo, pero si alguien todavía está buscando respuestas adecuadas a esta pregunta, es posible que desee considerar Perl Many-Core-Engine (MCE)

Cuestiones relacionadas