Mam dość słuchania, jak ludzie zalecają używanie tylko jednego wątku na procesor, podczas gdy wiele programów używa do 100 na proces! Weźmy na przykład niektóre popularne programy
vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50
Za każdym razem, gdy zamieszczam pytanie związane z wątkiem, prawie za każdym razem przypomina mi się, że nie powinienem używać więcej niż jednego wątku na procesor, a wszystkie programy, o których wspomniałem powyżej, psują się w moim systemie z jednym procesorem.
Odpowiedzi:
Być może w HPC, gdzie chcesz maksymalnej wydajności - ale poza tym najgłupsza rzecz, jaką dziś słyszałem!
Powinieneś użyć liczby wątków odpowiednich dla projektu programu i nadal dawać zadowalającą wydajność.
W przypadku serwera WWW uzasadnione może być uruchomienie wątku dla każdego połączenia przychodzącego (chociaż istnieją lepsze sposoby dla bardzo mocno obciążonych serwerów).
Dla ide, każde narzędzie działające w swoim własnym wątku nie jest nierozsądne. Podejrzewam, że wiele wątków zgłoszonych dla .Net IDE to np. Logowanie i zadania we / wy uruchamiane w ich własnych wątkach, aby mogły być dalej odblokowane.
źródło
Porada dotycząca jednego wątku na rdzeń ma zastosowanie, gdy celem jest szybkość poprzez równoległe wykonywanie.
Zupełnie innym i równie ważnym powodem jest prostota kodu, który musi reagować na nieprzewidziane zdarzenia. Więc jeśli program musi nasłuchiwać na 100 gniazdach i wydaje się, że poświęca każdemu z nich pełną uwagę, jest to idealne zastosowanie do wątkowania. Innym przykładem jest interfejs użytkownika, w którym jeden wątek obsługuje zdarzenia interfejsu użytkownika, podczas gdy inny wykonuje przetwarzanie w tle.
źródło
Potrzebujesz jednego wątku dla każdego obliczenia, które może przebiegać z inną szybkością niż inne obliczenia.
W przypadku równoległych obliczeń związanych z procesorem, które występują w dużych blokach pracy, zwykle potrzebujesz jednego wątku na procesor, ponieważ gdy wszystkie są zajęte, więcej wątków nie pomaga i po prostu tworzy narzut harmonogramu. Jeśli bloki pracy mają nieregularne rozmiary w czasie lub są generowane dynamicznie w czasie wykonywania (często zdarza się, gdy masz do przetworzenia duże złożone struktury danych), możesz chcieć dołączyć te bloki do wielu wątków, więc harmonogram zawsze ma duży ustawić, aby wybrać, kiedy zakończy się jakiś blok pracy, aby wszystkie procesory były zajęte.
W przypadku obliczeń związanych z we / wy zazwyczaj potrzebujesz jednego wątku dla każdego niezależnego „kanału” we / wy, ponieważ komunikują się one z różnymi prędkościami, a wątki blokowane na kanale nie uniemożliwiają postępów innym wątkom.
źródło
Ogólna zasada dla wątków polega na tym, że chcesz mieć co najmniej jeden „aktywny” (zdolny do wykonania poleceń natychmiast podany czas procesora) wątek roboczy dla każdej „jednostki wykonawczej” dostępnej na komputerze. „Jednostka wykonawcza” to jeden logiczny procesor instrukcji, więc czterordzeniowy, czterordzeniowy serwer Xeon z hiperwątkiem miałby 32 EU (4 chipy, 4 rdzenie na chip, każdy z hiperwątkiem). Twój średni Core i7 miałby 8.
Jeden wątek na UE to najpełniejsze wykorzystanie mocy procesora, pod warunkiem że wątki będą zawsze w stanie roboczym; prawie nigdy tak nie jest, ponieważ wątki potrzebują dostępu do pamięci niebuforowanej, dysku twardego, portów sieciowych itp., na które muszą czekać i które nie wymagają aktywnej uwagi procesora. W ten sposób możesz jeszcze bardziej zwiększyć ogólną wydajność dzięki większej ilości wątków ustawionych w kolejce i gotowych do użycia. To kosztuje. gdy procesor przełącza wątek, musi buforować rejestry wątku, wskaźnik wykonania i inne informacje o stanie, zwykle przechowywane w najgłębszych działaniach UE i bardzo szybko dostępne, umożliwiając innym UE w tym układzie procesora na pobranie go. Wymaga również wątków w systemie operacyjnym, aby zdecydować, na który wątek należy przełączyć. Wreszcie, kiedy UE zmienia wątki, traci przyrost wydajności potoku, z którego korzysta większość architektur procesorów; musi przepłukać rurociąg przed przełączeniem wątków. Ponieważ jednak wszystko to zajmuje średnio o wiele mniej czasu niż zwykłe czekanie, aż dysk twardy, a nawet pamięć RAM wróci z informacjami, jest to warte kosztów.
Jednak ogólnie rzecz biorąc, gdy przekroczysz dwukrotnie liczbę „aktywnych” wątków w porównaniu z UE, system operacyjny zaczyna spędzać więcej czasu na wątkach planowania w UE, a UE spędza więcej czasu na przełączaniu się między nimi, niż faktycznie spędza na uruchamianiu aktywnych wątków programów. To jest punkt braku ekonomii skali; uruchomienie wielowątkowego algorytmu potrwa dłużej, jeśli w tym momencie dodasz dodatkowy wątek.
Ogólnie rzecz biorąc, chcesz zachować co najmniej tyle wątków w swoim programie, ile masz UE na komputerze, ale chcesz uniknąć ponad dwukrotnej liczby tych, które nie czekają ani nie śpią.
źródło
Powinieneś użyć jednego wątku do:
Każdy procesor musi być zajęty.
Każde wejście / wyjście, które możesz użytecznie jednocześnie wstrzymać, którego nie możesz wykonać w sposób nieblokujący. (Na przykład czyta z dysku lokalnego).
Każde zadanie wymagające dedykowanego wątku, na przykład wywołanie do biblioteki, która nie ma nieblokującego interfejsu lub gdzie interfejsy nieblokujące są nieodpowiednie. Obejmuje to zadania takie jak monitorowanie zegara systemowego, liczniki czasu odpalania i tak dalej.
Kilka dodatkowych w celu ochrony przed nieoczekiwanym blokowaniem, takim jak błędy strony.
Kilka dodatkowych w celu ochrony przed oczekiwanym blokowaniem, których nie warto optymalizować, na przykład w niekrytycznym kodzie. (Na przykład, jeśli bardzo rzadko musisz wykonać żądanie DNS, prawdopodobnie nie warto podejmować wysiłku, aby wykonywać żądania DNS asynchronicznie. Po prostu utwórz kilka dodatkowych wątków i ułatw swoje życie).
Jeśli zastosujesz zasadę „jeden wątek na procesor”, cały kod ma krytyczne znaczenie dla wydajności. Każdy kod, który z jakiegoś powodu blokuje, oznacza, że proces nie może korzystać z tego procesora. To sprawia, że programowanie jest trudniejsze bez powodu.
źródło
Możesz albo spawnować procesy i wątki, aby umożliwić wykorzystanie systemu wielordzeniowego \ wieloprocesorowego dla jednego programu, w którym to przypadku nie zyskujesz (przynajmniej dla jednego programu) posiadania większej liczby wątków \ procesów niż rdzeni.
Lub możesz mieć procedury odpytujące o zdarzenie, które zwykle blokuje dalsze wykonywanie. Zamiast powiązać procesor z odpytywaniem, możesz zamiast tego utworzyć wątek, który będzie siedział w stanie bezczynności, dopóki odpowiednie zdarzenie go nie obudzi. Ta metoda jest bardzo często stosowana w serwerach WWW i kolejkach zdarzeń GUI. Większość programów chce mieć jakiś centralny magazyn danych (nawet jeśli jest to jego kod wykonania programu), do którego mają dostęp wszystkie wątki, więc sądzę, że właśnie dlatego używają łączenia wątków nad procesami.
źródło
Wspomniane aplikacje rzadko uruchamiają te dziesiątki wątków jednocześnie. Większość z nich po prostu tam siedzi, ponieważ są w puli wątków . Aplikacja wysyła różne zadania do kolejki, która jest czyszczona przez wątki w puli wątków.
Dlaczego więc basen jest tak duży? Ponieważ często wątki muszą czekać na inne zasoby, takie jak dysk, sieć, użytkownik, inny wątek itp. Podczas wątku należy uruchomić inne wątki, aby w pełni wykorzystać procesor. Właściwe dobranie puli jest jednak trudne. Za mało wątków, a stracisz wydajność, ponieważ procesor nie jest w pełni wykorzystywany podczas oczekiwania na coś. Zbyt wiele wątków, a stracisz wydajność z powodu przełączania się między nimi.
źródło