Odpowiedzi:
To jest skomplikowane pytanie, które zadajesz. Bez wiedzy o naturze twoich wątków trudno powiedzieć. Kilka rzeczy do rozważenia przy diagnozowaniu wydajności systemu:
Jest procesem / wątkiem
Wszystkie te trzy zasoby są skończone i każdy może ograniczyć wydajność systemu. Musisz sprawdzić, które (razem 2 lub 3) Twoja konkretna sytuacja pochłania.
Możesz użyć ntop
i iostat
oraz vmstat
do zdiagnozowania, co się dzieje.
"Dlaczego to się dzieje?" jest dość łatwy do odpowiedzi. Wyobraź sobie, że masz korytarz, w którym zmieści się cztery osoby obok siebie. Chcesz przenieść wszystkie śmieci z jednego końca na drugi koniec. Najbardziej efektywna liczba osób to 4.
Jeśli masz 1-3 osoby, tracisz przestrzeń na korytarzu. Jeśli masz 5 lub więcej osób, przynajmniej jedna z tych osób cały czas utknęła w kolejce za inną osobą. Dodanie coraz większej liczby osób po prostu zatyka korytarz, nie przyspiesza to aktywności.
Chcesz mieć tyle osób, ile możesz zmieścić, nie powodując żadnych kolejek. To, dlaczego masz kolejkę (lub wąskie gardła), zależy od pytań zawartych w odpowiedzi SLM.
4
jest to najlepszy numer.
Częstym zaleceniem jest n + 1 wątków, gdzie n jest liczbą dostępnych rdzeni procesora. W ten sposób n wątków może pracować z procesorem, podczas gdy 1 wątek czeka na dyskowe operacje we / wy. Posiadanie mniejszej liczby wątków nie wykorzysta w pełni zasobu procesora (w pewnym momencie zawsze będzie czekało na We / Wy), posiadanie większej liczby wątków spowoduje, że wątki będą walczyły o zasoby procesora.
Wątki nie są wolne, ale mają narzuty kontekstowe i - jeśli dane muszą być wymieniane między wątkami, co zwykle ma miejsce - różne mechanizmy blokujące. Jest to warte kosztu tylko wtedy, gdy masz więcej dedykowanych rdzeni procesora do uruchamiania kodu. Na jednordzeniowym procesorze pojedynczy proces (bez osobnych wątków) jest zwykle szybszy niż jakiekolwiek wykonane wątki. Wątki nie magicznie przyspieszają procesora, to po prostu dodatkowa praca.
Jako drugi podkreśliło ( SLM odpowiedź , EightBitTony odpowiedź ) jest to skomplikowane pytanie i bardziej, że nie opisują co thred robisz i jak to zrobić.
Ale definitywne dodanie większej liczby wątków może pogorszyć sytuację.
W dziedzinie obliczeń równoległych istnieje prawo Amdahla, które może mieć zastosowanie (lub nie może, ale nie opisuj szczegółów swojego problemu, więc ...) i może dać ogólny wgląd w tę klasę problemów.
Istotą prawa Amdahla jest to, że w każdym programie (w dowolnym algorytmie) zawsze jest procent, który nie może być uruchomiony równolegle ( część sekwencyjna ), i jest inny procent, który może być uruchomiony równolegle ( część równoległa ) [Oczywiście te dwie porcje sumują się do 100%].
Te części można wyrazić jako procent czasu wykonania. Na przykład 25% czasu może być poświęcone na ściśle sekwencyjne operacje, a pozostałe 75% czasu spędzone jest na działaniu, które można wykonać równolegle.
(Zdjęcie z Wikipedii )
Prawo Amdahla przewiduje, że dla każdej podanej równoległej części (np. 75%) programu możesz przyspieszyć wykonywanie tylko do tej pory (np. Maksymalnie 4 razy), nawet jeśli używasz coraz większej liczby procesorów do wykonania pracy.
Zasadą jest, że im więcej z was program nie może przekształcić w równoległe wykonywanie, tym mniej można uzyskać za pomocą większej liczby jednostek wykonawczych (procesorów).
Biorąc pod uwagę, że używasz wątków (a nie fizycznych procesorów), sytuacja może być jeszcze gorsza. Pamiętaj, że wątki mogą być przetwarzane (w zależności od implementacji i dostępnego sprzętu, np. Procesorów / rdzeni) współdzielących ten sam fizyczny procesor / rdzeń (jest to forma wielozadaniowości, jak wskazano w innej odpowiedzi).
Ta teoretyczna prognoza (o czasach procesora) nie uwzględnia innych praktycznych wąskich gardeł jako
może to być łatwo czynnikiem ograniczającym w praktycznych zastosowaniach.
Winowajcą powinno być tutaj „PRZEŁĄCZANIE KONTEKSTU”. Jest to proces zapisywania stanu bieżącego wątku, aby rozpocząć wykonywanie innego wątku. Jeśli pewna liczba wątków ma ten sam priorytet, należy je przełączać do momentu zakończenia wykonywania.
W twoim przypadku, gdy jest 50 wątków, zachodzi dużo przełączania kontekstu w porównaniu z uruchomieniem tylko 10 wątków.
Ten narzut czasowy wprowadzony z powodu przełączania kontekstu powoduje, że twój program działa wolno
ps ax | wc -l
zgłasza 225 procesów i wcale nie jest mocno obciążona). Skłaniam się ku zgadywaniu @ EightBitTony; unieważnienie pamięci podręcznej jest prawdopodobnie większym problemem, ponieważ za każdym razem, gdy opróżniasz pamięć podręczną, procesor musi czekać eony na kod i dane z pamięci RAM.
Aby naprawić metaforę EightBitTony:
"Dlaczego to się dzieje?" jest dość łatwy do odpowiedzi. Wyobraź sobie, że masz dwa baseny, jeden pełny i jeden pusty. Chcesz przenieść całą wodę z jednego na drugi i mieć 4 wiadra . Najbardziej efektywna liczba osób to 4.
Jeśli masz 1-3 osoby, tracisz dostęp do niektórych wiader . Jeśli masz 5 lub więcej osób, przynajmniej jedna z nich utknęła i czeka na wiadro . Dodawanie coraz większej liczby osób ... nie przyspiesza aktywności.
Więc chcesz mieć tyle osób, ile jest w stanie wykonać trochę pracy (użyj wiadra) jednocześnie .
Osoba tutaj jest wątkiem, a wiadro reprezentuje dowolny zasób wykonania, który stanowi wąskie gardło. Dodanie kolejnych wątków nie pomaga, jeśli nic nie mogą zrobić. Ponadto powinniśmy podkreślić, że przekazywanie wiadra od jednej osoby do drugiej jest zwykle wolniejsze niż pojedyncza osoba, która niosą wiadro na tę samą odległość. Oznacza to, że dwa wątki na przemian na rdzeniu zwykle wykonują mniej pracy niż pojedynczy wątek działający dwa razy dłużej: wynika to z dodatkowej pracy wykonanej w celu przełączania między dwoma wątkami.
To, czy ograniczającym zasobem wykonawczym (segmentem) jest procesor, rdzeń, czy hiper-wątkowy potok instrukcji, zależy od tego, która część architektury jest czynnikiem ograniczającym. Zauważ też, że zakładamy, że wątki są całkowicie niezależne. To jest tylko w przypadku, gdy mają one żadnych danych (i uniknąć kolizji cache).
Jak zasugerowało kilka osób, dla We / Wy ograniczającym zasobem może być liczba użytecznych operacji kolejkowania we / wy: może to zależeć od wielu czynników sprzętowych i jądra, ale może być znacznie większe niż liczba rdzenie. Tutaj przełącznik kontekstu, który jest tak kosztowny w porównaniu do kodu związanego z wykonaniem, jest dość tani w porównaniu do kodu związanego z We / Wy. Niestety myślę, że metafora wymknie się spod kontroli, jeśli spróbuję to uzasadnić wiadrami.
Należy zauważyć, że optymalne zachowanie z kodem związanym z We / Wy zwykle nadal ma najwyżej jeden wątek na potok / rdzeń / procesor. Należy jednak napisać asynchroniczny lub synchroniczny / nieblokujący kod we / wy, a stosunkowo niewielka poprawa wydajności nie zawsze uzasadnia dodatkową złożoność.
PS. Mój problem z oryginalną metaforą korytarza zdecydowanie sugeruje, że powinieneś mieć 4 kolejki ludzi, z 2 kolejkami niosącymi śmieci i 2 wracającymi, by zebrać więcej. Następnie można zrobić każdą kolejkę prawie tak długo, jak na korytarzu i dodanie ludzie zrobili przyspieszenia algorytmu (w zasadzie odwrócił cały korytarz na taśmociągu).
W rzeczywistości ten scenariusz jest bardzo podobny do standardowego opisu związku między opóźnieniem a rozmiarem okna w sieci TCP, dlatego wyskoczył na mnie.
Jest to dość proste i łatwe do zrozumienia. Mając więcej wątków niż obsługuje procesor, tak naprawdę serializujesz, a nie równolegle. Im więcej wątków masz, tym wolniejszy będzie Twój system. Twoje wyniki są w rzeczywistości dowodem tego zjawiska.