2010-08-15 14 views
14

W szczególności, zamierzam użyć TPL, aby uruchomić (i czekać) procesów zewnętrznych. Czy TPL traktuje całkowite obciążenie maszyny (zarówno CPU, jak i I/O) przed podjęciem decyzji o rozpoczęciu kolejnego zadania (stąd - w moim przypadku - inny proces zewnętrzny)?Czy biblioteka zadań (lub PLINQ) uwzględnia inne procesy?

Na przykład:

Mam około 100 plików multimedialnych, które muszą być zakodowane lub transkodowanie (na przykład z WAV do FLAC lub FLAC, MP3). Kodowanie odbywa się poprzez uruchomienie zewnętrznego procesu (np. FLAC.EXE lub LAME.EXE). Każdy plik trwa około 30 sekund. Każdy proces jest w większości związany z procesorem, ale jest tam trochę wejść/wyjść. Mam 4 rdzenie, więc najgorszy przypadek (transkodowanie przez podłączenie dekodera do kodera) nadal wykorzystuje tylko 2 rdzenie. Chciałbym zrobić coś takiego:

Parallel.ForEach(sourceFiles, 
    sourceFile => 
     TranscodeUsingPipedExternalProcesses(sourceFile)); 

Czy uruchomi to 100 zadań (a więc 200 procesów zewnętrznych konkurujących o procesor)? A może zobaczy, że procesor jest zajęty i robi 2-3 operacje na raz?

+0

Oczywiście, prawdopodobnie powinienem podłączyć "TaskCompletionSource" do zdarzenia "Process.Exited", a następnie użyć metody 'TranscodeAsync', która zwraca' Task'. Wtedy nie będzie blokowania. Wtedy mogę mieć drobniejszą kontrolę nad zadaniami, pozostając w kontakcie z OC. –

Odpowiedz

21

W tym miejscu napotkasz kilka problemów. Mechanizm unikania głodu w harmonogramie zobaczy twoje zadania jako zablokowane, ponieważ czekają na procesy. Trudno będzie odróżnić zaklejoną nitkę od tej, która czeka na zakończenie procesu. W rezultacie może planować nowe zadania, jeśli Twoje zadania są uruchamiane lub przez dłuższy czas (patrz poniżej). Hierarchia skoczków powinna uwzględniać całkowite obciążenie systemu, zarówno z aplikacji, jak i innych. Po prostu stara się zmaksymalizować wykonaną pracę, więc zwiększy ilość pracy do momentu, aż całkowita przepustowość systemu przestanie rosnąć, a następnie się wycofa. Nie sądzę, że będzie to miało wpływ na Twoją aplikację, ale prawdopodobnie problem unikania stavation.

można znaleźć więcej szczegółów, jak to wszystko działa w Parallel Programming with Microsoft®.NET, Colin Campbell, Ralph Johnson, Ade Miller, Stephen Toub (wcześniejszy projekt jest online).

„Basen wątek .NET automatycznie zarządza liczbę pracownika wątków w puli Dodaje i usuwa wątki według wbudowaną heurystyki Basen wątek .NET ma dwa główne mechanizmy wstrzykiwanie wątki. A. mechanizm głód unikania który dodaje pracownikowi wątki jeśli nie widzi postępy poczyniono przy kolejce przedmiotów i hillclimbing heurystyki, która stara się zmaksymalizować wydajność podczas korzystania jako kilku wątków, jak to możliwe.

celem uniknięcia głodu jest zapobieganie Ten rodzaj impasu może wystąpić, gdy pracownik odczyt czeka na zdarzenie synchronizacji , które może zostać spełnione tylko przez element pracy, który wciąż oczekuje na kolejkę globalną lub lokalną puli wątków. Jeśli liczba wątków roboczych byłaby stała , a wszystkie te wątki były zablokowane w podobny sposób, system nie byłby w stanie dokonać dalszego postępu. Dodanie nowego wątku roboczego rozwiązuje problem.

Celem heurystyki wspinaczki górskiej jest poprawa wykorzystania rdzeni, gdy wątki są blokowane przez I/O lub inne warunki oczekiwania , które powodują zatrzymanie procesora. Domyślnie zarządzana pula wątków ma jeden wątek roboczy dla każdego rdzenia. Jeśli jeden z tych wątków roboczych zostanie zablokowany , istnieje szansa, że ​​rdzeń może być niedostatecznie wykorzystany, w zależności od ogólnego obciążenia komputera w zakresie .Logika wtrysku nici nie rozróżnia wątku, który jest zablokowany, oraz wątku , który wykonuje długotrwałą operację wymagającą dużej mocy obliczeniowej. Dlatego za każdym razem, gdy globalne lub lokalne koleje puli wątków zawierają oczekujące pozycje pracy, aktywne elementy pracy, które trwają długo (ponad pół sekundy), mogą wywołać tworzenie nowych wątków robota puli wątków .

Pula wątków .NET ma możliwość wstrzyknięcia wątków co jeden czas zakończenia pracy lub co 500 milisekund, w zależności od tego, która z nich jest krótsza niż . Puli wątków używa tej okazji, aby spróbować dodać wątki (lub zabranie ich), kierując się informacjami zwrotnymi z poprzednich zmian w liczbę wątków. Jeśli dodawanie wątków pomaga zwiększyć przepustowość, pula wątków dodaje więcej; w przeciwnym razie zmniejsza liczbę wątków roboczych . Technika ta nazywana jest heurystyką wspinaczki górskiej. Dlatego jednym z powodów, aby zadbać o pojedyncze zadania, jest uniknięcie "wykrywania głodu" pod numerem , ale innym powodem, aby je niedługo było, aby dać puli wątków więcej możliwości zwiększenia przepustowości o dostosowując liczbę wątków. Im krótszy jest czas wykonywania poszczególnych zadań, tym częściej pula wątków może mierzyć przepustowość, a dostosowuje odpowiednio liczbę wątków.

Aby to zrobić, zastanów się nad ekstremalnym przykładem. Załóżmy, że masz kompleksową symulację finansową z 500 procesorami wymagającymi intensywnego przetwarzania . Każda z nich zajmuje średnio dziesięć minut średnio . Jeśli utworzysz zadania najwyższego poziomu w globalnej kolejce dla każdej z tych operacji, po około pięciu minutach puli wątków wzrośnie do 500 wątków roboczych. Powodem jest to, że pula wątków widzi wszystkie zadania jako zablokowane i zaczyna dodawać nowe wątki z szybkością około dwóch wątków na sekundę.

Co jest nie tak w przypadku 500 wątków roboczych? Zasadniczo nic, jeśli masz do dyspozycji 500 rdzeni i ogromną ilość pamięci systemowej . W rzeczywistości jest to długoterminowa wizja obliczeń równoległych. Jeśli jednak nie masz zbyt wielu rdzeni na komputerze, jesteś w sytuacji, gdy wiele wątków rywalizuje o przesunięcia czasowe. Ta sytuacja znana jest jako nadmierna liczba subskrypcji procesora. Umożliwienie wielu procesorom wymagającym intensywnego przetwarzania do konkurowania o czas w jednym rdzeniu zwiększa obciążenie kontekstowe przełączaniem , co może poważnie zmniejszyć ogólną przepustowość systemu . Nawet jeśli nie zabraknie pamięci, wydajność w tej sytuacji może być o wiele, dużo gorsza niż w obliczeniach sekwencyjnych. (Każdy przełącznik kontekstowy zajmuje od 6000 do 8 000 cykli procesora). Koszt przełączania kontekstu nie jest jedynym źródłem kosztów ogólnych. Zarządzany wątek w .NET zużywa mniej więcej megabajt przestrzeni stosu , niezależnie od tego, czy jest ona używana do wykonywania aktualnie używanych funkcji. Proces tworzenia nowego wątku trwa około 200 000 cykli procesora, a do wycofania wątku potrzeba około 100 000 cykli. Są to kosztowne operacje.

Dopóki twoje zadania nie trwają minut, algorytm wspinania się w wątku ostatecznie zorientuje się, że ma zbyt wiele wątków i sam wycina.Jeśli jednak masz zadania, które zajmują wątek roboczy przez wiele sekund lub minut lub godzin, ten odrzuci heurystykę puli wątków iw tym momencie musisz rozważyć alternatywę.

Pierwsza opcja polega na rozłożeniu aplikacji na krótsze zadania , które kończą się wystarczająco szybko, aby pomyślnie pomyślnie utworzyć pulę wątków , sterując liczbą wątków w celu uzyskania optymalnej przepustowości. Drugą możliwością jest zaimplementowanie własnego obiektu harmonogramu zadań obiektu, który nie wykonuje wstrzyknięcia nici. Jeśli twoje zadania mają długi czas trwania, nie potrzebujesz wysoce zoptymalizowanego harmonogramu zadań, ponieważ koszt planowania będzie nieistotny w porównaniu z czasem wykonania zadania. Program deweloperski MSDN® ma przykład implementacji prostego harmonogramu zadań , który ogranicza maksymalny stopień współdziałania . Aby uzyskać więcej informacji, zobacz sekcję "Dalsze czytanie" pod koniec tego rozdziału na stronie .

W ostateczności można użyć metody SetMaxThreads do skonfigurowania klasy pula wątków z górnej granicy liczby wątków roboczych, zwykle równej liczby rdzeni (jest to nieruchomość Environment.ProcessorCount) . Ta górna granica dotyczy cały proces, w tym wszystkie AppDomains „

+0

+1 Przeciążenie 'Parallel.ForEach', które bierze obiekt' ParallelOptions' z 'MaxDegreeOfParallelism 'może również pomóc. –

+0

+1 Nie znajduję wersji online książki – Paparazzi

+0

Książka jest tutaj. http://msdn.microsoft.com/en-us/library/ff963553.aspx –

2

Odpowiedź jest krótka:.. Nie

Wewnętrznie OC wykorzystuje standardowy ThreadPool zaplanować swoje zadania Więc faktycznie pytając czy. ThreadPool bierze pod uwagę obciążenie maszyny, a nie ogranicza się tylko do liczby wątków w puli wątków, nic poza tym.

Czy możliwe jest raportowanie procesów zewnętrznych? z powrotem do aplikacji, gdy są gotowe, w takim przypadku nie musisz na nie czekać (utrzymując wątki zajęte).

-1

Przeprowadzono test za pomocą TPL/ThreadPool, aby zaplanować dużą liczbę zadań wykonujących zapętlone obroty. Za pomocą zewnętrznej aplikacji załadowałem jeden z rdzeni do 100% używając koligacji proc. Liczba aktywnych zadań nigdy się nie zmniejszyła.

Co więcej, uruchomiłem wiele wystąpień tej samej aplikacji z włączoną technologią TNET obsługującą ten sam procesor. Liczba wątków dla wszystkich aplikacji była taka sama i nigdy nie spadła poniżej liczby rdzeni, mimo że mój komputer był prawie nie do użytku.

A więc teoria na bok, TPL używa liczby dostępnych rdzeni, ale nigdy nie sprawdza rzeczywistego obciążenia. Bardzo słaba realizacja w mojej opinii.

+0

Myślę, że TPL przydziela _minimum_ pewną liczbę wątków równą liczbie rdzeni. Sprawdza obciążenie i może zwiększać liczbę wątków, ale nie zmniejsza liczby wątków poniżej tego minimum. –

+0

Zgadza się. To domyślne minimum. To policjant.Czy oczekujesz od programistów tworzenia kodu, który monitoruje całkowite obciążenie procesora, wyłączając naszą działającą aplikację i odpowiednio zmniejsza minimalną i maksymalną liczbę wątków zużywanych przez pulę wątków? A może powinniśmy ręcznie ustawić minimum od początku do 1? A może 2? Lub CPU Count/2? I nie, nie monitoruje rzeczywistego obciążenia procesora. Monitoruje tylko własne wątki. To wszystko. – MoonStom

+0

Coś, co mi się zdarza, to to, że TPL jest chciwa, może wznieść się do punktu nadmiernej subskrypcji procesora, jeśli przyniesie korzyści z wykonania zadań, więc masz rację, TPL monitoruje zadania/sek, a nie obciążenie procesora, które ma pewne wady. Chodzi mi o to, że Microsoft nie spodziewał się, że deweloperzy zmienią powinowactwo procesora podczas używania TPL. –

Powiązane problemy