2012-07-21 11 views
5

Ich habe ein Programm (Perl), die eine große Anzahl von Threads startet (jeder verantwortlich für die Erstellung von Grafiken basierend auf Datenverarbeitung). Jeder Thread ich mit Start:Wie die maximale Anzahl der parallelen Threads in Perl zu begrenzen

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

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

Die Fäden richtig, aber nach einer Weile abfeuern, nachdem ich mehrere von ihnen Perl-Interpreter Abstürze geöffnet (ich nehme an, es in dem Speicher verwendet ist?). Also meine Lösung ist, die Anzahl der Threads zu begrenzen, die ich auf einmal öffne. Ich habe 15 ausgewählt. Und ich möchte vor jeder Erstellungszeile ein Sub hinzufügen, um zu überprüfen, ob es in Ordnung ist, den nächsten Thread auszulösen oder einen Schlaf auszuführen, während ich warte für einen zu beenden. So habe ich es versucht.

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; 
     } 
    } 
} 

Also jedes Mal, wenn ich einen neuen Thread erstellen möchte ich

&checkThreads; 

rufen Sie einfach Und das würde Sorgfalt um eine Verzögerung zu schaffen machen, während ich für einige Threads warten bis zu reinigen. Das Problem ist, dass, wenn ich das Unter nennen, der Moment, als ich die Linie treffen, wo ich überprüfen:

$task->is_running() 

das Programm beendet und nicht mehr ohne Fehler oder Warnung ausgeführt wird. Ich will nur ein Sub, das die laufenden Threads zählt, um sie zu begrenzen.

Wie kann ich diese Zählung erfolgreich durchführen?

Andere Dinge, die ich versucht habe, werten Sie die folgende Zeile:

scalar(threads->list()); 

Aber das gibt mir einen seltsamen Wert, wie es eine unblessed Referenz glaube ich, dass wie folgt aussieht:

threads=SCALAR(0x80fea8c) 
+0

btw, das ist (stringification a) gesegnet * * ref – ikegami

+1

sehr, sehr BTW - Denken Sie daran, dass Threads in Perl nicht wie Threads in anderen Programmiersprachen sind - sie sind sehr ressourcenhungrig, da jeder Thread eine COPY aller Variablen hat.In einigen Fällen sind sie immer noch nützlich, aber in allen Fällen, in denen ich Paralellisierung durchführen muss, funktioniert Forking viel besser. Es hängt nicht direkt mit deiner Frage zusammen, ich wollte dir das nur sagen. :) –

+0

Welche Version von Perl? Welche Version von Threads? Und sind deine Threads losgelöst (vielleicht in mySubName selbstlösend)? – pilcrow

Antwort

5

Thread::Semaphore bietet eine counting semaphore Parallelität zu begrenzen:

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; 

Und in Ihrer Funktion:

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

Richard Ich denke, das funktioniert, ich habe es in das Skript implementiert und es sieht so aus, als würde es meine Max-Threads kontrollieren. Gibt es eine Möglichkeit, den aktuellen Wert eines Semaphors zu sehen? Da ich es aber nach einiger Zeit ausgeführt habe, hängt mein Skript einfach bei '$ sem-> down;' – gorba

+0

Ich habe die Anzahl der Threads auf 5 reduziert und es funktioniert gut, immer noch mit 7 sieht aus wie das Programm bei Irgendwann, nicht sicher warum. Danke für den Tipp! – gorba

+1

Sie können den Währungswert des Semaphors abrufen, indem Sie das Objekt selbst dereferenzieren. Dies ist nur ein gesegneter Verweis auf den Maximalwert (Standardwert 1) minus dessen Anzahl. Um die aktuelle Anzahl der ausstehenden Threads zu erhalten, evaluieren Sie $ 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 

Mit anderen Worten, finden Sie heraus, wie viele Elemente in der Liste sind, die threads-> list() zurückgibt und Sie Ihre Anzahl haben.

Sie könnten Thread::Pool oder andere cpan-Pakete untersuchen, um zu sehen, ob jemand anderes bereits die Schwerarbeit für Sie erledigt hat.

+0

Wenn ich versuche, threads-> list() zu verwenden, bekomme ich folgendes Ergebnis: Auto/threads/lists.al kann nicht in @INC gefunden werden (@INC enthält: C: \ Programme (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C: \ Programme (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C:/Perl/lib C:/Perl/site/lib.) unter C: \ Pfad \ main3.pl Zeile 508 – gorba

+0

Wenn 'threads-> list()' eine Liste zurückgibt, können Sie die Länge leichter erfassen als mit einer Schleife ... wie '$ totalThreads = scalar (threads-> list());', Kannst du nicht? –

+0

ok es war ein Tippfehler, ich hatte threads-> lists() anstelle von threads-> list(), aber jetzt führe ich diese meine $ totalThreads; foreach mein $ thr (threads-> list()) { $ totalThreads ++; } print "Themen aktiv:". $ totalThreads. "\ n"; Und ich bekomme, was ist: Verwendung von nicht initialisierten Wert in Verkettung für die Linie, wo ich – gorba

1

Suchen Sie die Dokumentation,

my $count = threads->list(); 

funktionieren sollte, im Gegensatz zu dem, was Sie sagen. Was verwenden die Dokumente für die Version der Threads Sie sagen? Nun, Sie könnten Folgendes als Workaround verwenden.

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

Ich habe den Semaphor-Ansatz verwendet, den Richard vorgeschlagen hat, aber ich habe es ausprobiert und es gibt die Anzahl der tatsächlichen Threads in der Liste, danke! – gorba

Verwandte Themen