2012-07-21 28 views
5

Tengo un programa (Perl) que inicia una gran cantidad de subprocesos (cada uno a cargo de crear gráficos basados ​​en el procesamiento de datos). Cada hilo que comience a usar:Cómo limitar el número máximo de subprocesos paralelos en Perl

my @threads //list to store threads that have been launched 

push @threads,threads->create(\mySubName,params...); 

Los hilos disparan correctamente, pero después de un tiempo, después de que yo he abierto varios de ellos se estrella intérprete de Perl (supongo que tiene que ver con la memoria?). Así que mi solución es limitar el número de hilos que abro a la vez, elegí 15. Y quiero agregar un sub antes de cada línea de creación para verificar si está bien disparar el siguiente hilo o dormir mientras espero para que uno termine Así es como traté de hacerlo.

sub checkThreads{ 
    my $addThread = 0; 
    until($addThread){ 
     my $totalThreads = 0; 
     foreach my $task (@threads){ 
      if($task->is_running()){$totalThreads++;} 
     } 
     if($totalThreads <= 15){ 
      print "Ok to add new thread, carry on!\n"; 
      $addthread = 1; 
     }else{ 
      print "Waiting for $totalThreads threads to fire next one...\n"; 
      sleep 2; 
     } 
    } 
} 

Así que cada vez que quiero crear un nuevo hilo acabo llamarían

&checkThreads; 

Y eso sería tener cuidado para crear un retraso mientras espero a que algunos hilos para limpiar. El problema es que cuando llamo a ese sub, el momento en que golpeó la línea donde puedo comprobar:

$task->is_running() 

el programa sale y deja de funcionar sin ningún tipo de error o advertencia. Solo quiero un sub que cuente los hilos de ejecución para limitarlos.

¿Cómo puedo realizar este recuento con éxito?

Otras cosas que he tratado están evaluando la línea siguiente:

scalar(threads->list()); 

Pero eso me da un valor raro, como si es una referencia sin bendecir Creo que se parece a:

threads=SCALAR(0x80fea8c) 
+0

por cierto, eso es (stringification de una) * bendijo * ref – ikegami

+1

muy, muy cierto - tenga en cuenta que los hilos en perl no son como hilos en otros lenguajes de programación - tienen muchos recursos, ya que cada hilo tiene una COPIA de todas las variables.Todavía son útiles en algunos casos, pero en todos los casos en los que tengo que hacer una paralelización, el bifurcado funciona mucho mejor. No está relacionado directamente con tu pregunta, solo quería decírtelo. :) –

+0

¿Qué versión de Perl? ¿Qué versión de hilos? ¿Y sus hilos están desacoplados (tal vez separados en mySubName)? – pilcrow

Respuesta

5

Thread::Semaphore proporciona una counting semaphore para limitar la concurrencia:

my $sem = Thread::Semaphore->new(15); # max 15 threads 
my @threads = map { 
    # request a thread slot, waiting if none are available: 
    $sem->down; 
    threads->create(\&mySubName, @params) 
} 0..100; 
$_->join for @threads; 

Y en su función:

sub mySubName { 
    do_stuff(); 
    # release slot: 
    $sem->up; 
} 
+0

Richard Creo que esto está funcionando, lo implementé en el script y parece que de hecho está controlando mis hilos máximos, ¿hay alguna manera de poder ver el valor actual que tiene un semáforo? Porque lo ejecuté pero después de hacerlo un rato, mi script se cuelga en '$ sem-> down;' – gorba

+0

Reduje la cantidad de hilos a 5 y funciona bien, aún con 7 parece que el programa se para en algún punto, no estoy seguro por qué. ¡Gracias por el consejo! – gorba

+1

Puede obtener el valor de moneda del semáforo desreferenciando el objeto mismo, que es solo una bendita referencia al valor máximo (valor predeterminado de 1) menos sus recuentos. Entonces, para obtener el número actual de subprocesos pendientes, evalúe '$ max - $$ sem'. –

0
man perlthrtut 

What Threads Are Running? 
    "threads->list()" returns a list of thread objects, one for each thread 
    that's currently running and not detached. Handy for a number of 

En otras palabras, descubra cuántos elementos hay en la lista que threads-> list() devuelve y tiene su conteo.

Es posible que desee investigar Thread::Pool u otros paquetes de cpan para ver si alguien más ya ha hecho el trabajo pesado por usted.

+0

Cuando intento usar threads-> list(), obtengo el siguiente resultado: No puedo encontrar auto/hilos/listas.al en @INC (@INC contiene: C: \ Archivos de programa (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C: \ Archivos de programa (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C:/Perl/lib C:/Perl/site/lib.) en C: \ path \ main3.pl línea 508 – gorba

+0

Si 'threads-> list()' devuelve una lista, puede capturar la longitud más fácilmente que con un bucle ... como '$ totalThreads = escalar (hilos-> lista());', no puedes? –

+0

ok, era un error tipográfico, tenía hilos-> listas() en lugar de hilos-> lista(), pero ahora ejecuto este my $ totalThreads; foreach my $ thr (threads-> list()) { $ totalThreads ++; } print "Subprocesos activos:". $ totalThreads. "\norte"; Y lo que consigo es: Uso del valor no inicializado en la concatenación de la línea donde puedo imprimir – gorba

1

Mirando los documentos,

my $count = threads->list(); 

debería funcionar, al contrario de lo que dice. ¿Qué documentación usa la versión de los hilos que usa? Bueno, podrías usar lo siguiente como una solución alternativa.

my $count =() = threads->list(); 
+0

Utilicé el enfoque de semáforo que propuso Richard, pero probé esto y da el recuento de los hilos reales en la lista, ¡gracias! – gorba

Cuestiones relacionadas