2012-07-21 17 views
5

Mam program (Perl), który uruchamia ogromną ilość wątków (każdy odpowiedzialny za tworzenie grafiki w oparciu o przetwarzanie danych). Każdy wątek zacząć używać:Jak ograniczyć maksymalną liczbę równoległych wątków w perlu

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

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

Nitki wystrzelić poprawnie, ale po jakimś czasie, gdy mam otwarte kilka z nich ulega awarii Perl interpreter (zakładam, że jest związany z pamięci?). Więc moim rozwiązaniem jest ograniczenie liczby wątków, które otwieram na raz, wybrałem 15. I chcę dodać sub przed każdą linią utwórz, aby sprawdzić, czy można wystrzelić kolejny wątek lub wykonać uśpienie podczas oczekiwania dla jednego do końca. Tak właśnie próbowałem to zrobić.

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

Więc za każdym razem Chcę utworzyć nowy wątek chciałbym po prostu zadzwoń

&checkThreads; 

A to zadbać, aby tworzyć opóźnienie podczas czekam na niektóre wątki, aby oczyścić. Problemem jest to, że gdy zgłoszę że sub moment uderzę linię gdzie mogę sprawdzić:

$task->is_running() 

program wychodzi i przestanie działać bez jakiegokolwiek błędu lub ostrzeżenia. Chcę tylko sub, który liczy działające wątki, aby je ograniczyć.

Jak mogę skutecznie wykonać tę liczbę?

Inne rzeczy próbowałem oceniamy następującą linię:

scalar(threads->list()); 

Ale to daje mi wartość dziwne, jak to jest unblessed odniesienia wierzę, że wygląda tak:

threads=SCALAR(0x80fea8c) 
+0

btw, to (stringification od a) * błogosławiony * ref – ikegami

+1

bardzo BTW - pamiętajmy, że wątki w perlu nie przypominają nici w innych językach programowania - są bardzo głodne zasobów, ponieważ każdy wątek ma KOPIĘ wszystkich zmiennych.Wciąż są przydatne w niektórych przypadkach, ale w każdym przypadku, w którym muszę wykonać paralelację, rozwidlenia działają znacznie lepiej. Nie jest to bezpośrednio związane z twoim pytaniem, chciałem ci tylko powiedzieć. :) –

+0

Jaka wersja Perla? Jaką wersję wątków? I czy twoje wątki są odłączone (być może samo-odłączające się w mySubName)? – pilcrow

Odpowiedz

5

Thread::Semaphore zapewnia counting semaphore ograniczyć współbieżności:

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; 

iw swojej funkcji:

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

Richard Myślę, że to działa, zaimplementowałem go w skrypcie i wygląda na to, że kontroluje moje maksymalne wątki, czy jest sposób, w jaki mogę zerknąć na obecną wartość, jaką posiada semafor? Ponieważ go uruchomiłem, ale po przejściu przez jakiś czas mój skrypt po prostu zawiesił się na '$ sem-> down;' – gorba

+0

Obniżyłem ilość wątków do 5 i działa dobrze, wciąż z 7 wygląda jak program zatrzymuje się na w pewnym sensie, nie wiem dlaczego. Dzięki za wskazówkę! – gorba

+1

Możesz uzyskać wartość waluty semafora, usuwając odwołanie do samego obiektu, co jest po prostu błogosławionym odniesieniem do wartości maksymalnej (domyślnie 1) minus jej wartości. Aby uzyskać aktualną liczbę zaległych wątków, należy wykonać '$ 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 

Innymi słowy, dowiedz się, ile pozycji znajduje się na liście, którą wątki-> lista() zwraca i masz swoją liczbę.

Być może zechcesz zbadać Thread::Pool lub inne pakiety cpan, aby sprawdzić, czy ktoś już wykonał dla ciebie ciężki lifting.

+0

Kiedy próbuję użyć thread-> list(), otrzymuję następujący wynik: Nie mogę zlokalizować auto/threads/lists.al w @INC (@INC zawiera: C: \ Program Files (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C: \ Program Files (x86) \ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C:/Perl/lib C:/Perl/site/lib.) w C: \ ścieżka \ main3.pl line 508 – gorba

+0

Jeśli 'threads-> list()' zwraca listę, możesz przechwycić długość łatwiej niż z pętlą ... jak '$ totalThreads = skalar (threads-> list());', nie możesz? –

+0

ok to był literówka, miałem wątki-> listy() zamiast wątków-> list(), ale teraz uruchamiam to my $ totalThreads; foreach my $ thr (threads-> list()) { $ totalThreads ++; } wydrukuj "Wątki aktywne:". $ totalThreads. "\ n"; I co mam to: Wykorzystanie wartości niezainicjowanych w konkatenacji do linii, gdzie mogę wydrukować – gorba

1

Patrząc Dokumentów,

my $count = threads->list(); 

powinny działać, wbrew temu, co mówisz. Co używają dokumenty dla wersji wątków , którą używasz? Cóż, możesz użyć poniższego jako obejścia.

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

Użyłem podejścia semaforowego, które zaproponował Richard, ale wypróbowałem to i daje liczbę rzeczywistych wątków na liście, dzięki! – gorba

Powiązane problemy