Optymalna liczba wątków na rdzeń

281

Powiedzmy, że mam 4-rdzeniowy procesor i chcę uruchomić jakiś proces w jak najkrótszym czasie. Proces ten jest idealnie równoległy, więc mogę uruchomić jego fragmenty na nieskończonej liczbie wątków, a każdy wątek zajmuje tyle samo czasu.

Ponieważ mam 4 rdzenie, nie oczekuję żadnego przyspieszenia, uruchamiając więcej wątków niż rdzenie, ponieważ pojedynczy rdzeń jest w stanie uruchomić tylko jeden wątek w danym momencie. Nie wiem dużo o sprzęcie, więc to tylko przypuszczenie.

Czy jest korzyść z uruchamiania równoległego procesu na większej liczbie wątków niż na rdzeniach? Innymi słowy, czy mój proces zakończy się szybciej, wolniej czy w mniej więcej tym samym czasie, jeśli uruchomię go przy użyciu 4000 wątków zamiast 4 wątków?

Julia
źródło

Odpowiedzi:

254

Jeśli twoje wątki nie wykonują operacji we / wy, synchronizacji itp. I nic innego nie działa, 1 wątek na rdzeń zapewni Ci najlepszą wydajność. Jednak nie jest to prawdopodobne. Dodanie większej liczby wątków zwykle pomaga, ale po pewnym czasie powoduje pewne pogorszenie wydajności.

Nie tak dawno temu przeprowadzałem testy wydajności na dwurdzeniowej maszynie z uruchomioną aplikacją ASP.NET na Mono pod całkiem przyzwoitym obciążeniem. Graliśmy z minimalną i maksymalną liczbą wątków, a na koniec okazało się, że dla tej konkretnej aplikacji w tej konkretnej konfiguracji najlepsza przepustowość wynosiła między 36 a 40 wątków. Wszystko poza tymi granicami działało gorzej. Lekcja wyciągnięta? Gdybym był tobą, testowałbym z inną liczbą wątków, aż znajdziesz odpowiednią liczbę dla swojej aplikacji.

Jedno jest pewne: wątki 4k potrwają dłużej. To dużo przełączników kontekstu.

Gonzalo
źródło
21
Myślę, że odpowiedź Gonzalo jest dobra. Chciałbym tylko dodać, że powinieneś eksperymentować i mierzyć. Twój program będzie się różnił od jego lub mojego, a także od kogokolwiek innego i tylko pomiary zachowania twojego programu odpowiedzą poprawnie na twoje pytania. Realizacja programów równoległych (lub współbieżnych) nie jest obszarem, w którym można wyciągnąć dobre wnioski z samych pierwszych zasad.
High Performance Mark
5
Odpowiedź +1, +: zaskakuje mnie, że posiadanie o wiele większej liczby wątków niż rdzeni powoduje lepszą wydajność, chociaż ma sens, jeśli więcej wątków oznacza większy udział czasu w porównaniu do wątków konkurencyjnych. Byłoby miło, gdyby moja aplikacja mogła wykryć różnice w wydajności i automatycznie dostroić się do optymalnej liczby wątków.
Juliet,
12
Nie powinno cię to dziwić w prawdziwym świecie. Wątki blokują czekanie na zasoby IO, takie jak dostęp do dysku, sieć itp., A także czekanie na zasoby inne niż IO, takie jak inne wątki, na zakończenie korzystania ze wspólnych zmiennych. To, co naprawdę chcesz osiągnąć, to minimalna liczba wątków, tak aby zawsze mógł działać co najmniej jeden wątek na rdzeń.
patros,
4
1 wątek na rdzeń nie jest optymalny. Musi być nieco więcej, najlepiej dwa razy więcej, ponieważ pozwoli to na uruchomienie innego wątku, jeśli wątek zostanie tymczasowo zablokowany. Nawet jeśli tylko w pamięci. Jest to ważniejsze, jeśli masz systemy (P4, I7, Sun Rock itp.) Wyposażone w SMT / HT)
Marco van de Voort,
1
Dlatego w mojej odpowiedzi „To bardzo prawdopodobne, że tak nie jest”. Znalezienie właściwej liczby zależy od aplikacji i architektury, na której działa.
Gonzalo
129

Zgadzam się z odpowiedzią @ Gonzalo. Mam proces, który nie wykonuje operacji we / wy, a oto, co znalazłem:

wprowadź opis zdjęcia tutaj

Zauważ, że wszystkie wątki działają na jednej tablicy, ale w różnych zakresach (dwa wątki nie mają dostępu do tego samego indeksu), więc wyniki mogą się różnić, jeśli działały na różnych tablicach.

Maszyna 1.86 to MacBook Air z dyskiem SSD. Drugi Mac to iMac z normalnym dyskiem twardym (myślę, że to 7200 obr / min). Maszyna z systemem Windows ma również dysk twardy 7200 obr./min.

W tym teście optymalna liczba była równa liczbie rdzeni w maszynie.

Motasim
źródło
14
+1 dla wykresu. Najwyraźniej najlepszy jest 1 wątek na rdzeń, ale interesujące jest to, że system czterordzeniowy wydaje się nie mieć wyższych liczb wątków (w każdym razie <100), jak robią to inni.
Jim Garrison,
46
-1 dla wykresu! Płynne krzywe dzięki współrzędnym x o wartości całkowitej? Dziki skok z 1 2 3 na 10 20 30 na 50 100? I współrzędne y, które dla wielokrotności stanowią wielokrotność 10 plus 2. To robi Excel, prawda?
Spacedman
5
@Spacedman Tak to jest. Gładkie łuki mają znacznie ładniejszy wygląd IMHO. : D
Motasim
22
@PascalvKooten, Problemem nie jest to, że wygląda ładnie, to oszukuje na pierwszy rzut oka. Przede wszystkim oś Y zaczyna się od 42, wyolbrzymiając widoczną różnicę między testowanymi maszynami. Po drugie, dziwny postęp wartości osi x sugeruje, że „zajęty czas” nie skaluje się liniowo z „liczbą wątków”, jest to szczególnie prawdziwe w przypadku niebieskiej linii. Myślę, że problem, z którym mają do czynienia inni (w tym ja), polega na tym, że wprowadza w błąd dane.
pauluss86,
13
@Spacedman Krytyka na wykresie jest najbardziej absurdalną rzeczą, na jaką natknąłem się w ciągu ostatnich 24 godzin. Wykres pomaga. Dużo. Kropka. Czy można to zrobić lepiej? Nikogo to nie obchodzi. Gładka krzywa zamiast dyskretnej? To jest twój problem ???? Zakładam, że wszyscy z was nigdy nie uwzględniliby takiego wykresu w swojej odpowiedzi, ponieważ nie macie dodatkowego czasu / energii, aby wyglądać dobrze. O to mi chodzi.
tyrex,
50

Wiem, że to pytanie jest dość stare, ale sytuacja ewoluowała od 2009 roku.

Należy teraz wziąć pod uwagę dwie rzeczy: liczbę rdzeni i liczbę wątków, które mogą działać w każdym rdzeniu.

W przypadku procesorów Intel liczba wątków jest definiowana przez Hyperthreading, który wynosi zaledwie 2 (jeśli są dostępne). Ale Hyperthreading skraca czas wykonania o dwa, nawet jeśli nie używasz 2 wątków! (tj. 1 potok współdzielony między dwoma procesami - jest to dobre, gdy masz więcej procesów, w przeciwnym razie nie jest tak dobre. Więcej rdzeni jest zdecydowanie lepszych!)

Na innych procesorach możesz mieć 2, 4 lub nawet 8 wątków. Więc jeśli masz 8 rdzeni, z których każdy obsługuje 8 wątków, możesz mieć 64 procesy działające równolegle bez przełączania kontekstu.

„Brak przełączania kontekstu” nie jest oczywiście prawdą, jeśli używasz standardowego systemu operacyjnego, który będzie przełączał kontekst dla wszelkiego rodzaju innych rzeczy poza twoją kontrolą. Ale to jest główny pomysł. Niektóre systemy operacyjne umożliwiają przydzielanie procesorów, więc tylko Twoja aplikacja ma dostęp / użycie tego procesora!

Z własnego doświadczenia wynika, że ​​jeśli masz dużo wejść / wyjść, wiele wątków jest dobrym rozwiązaniem. Jeśli masz bardzo ciężką pracę wymagającą dużej ilości pamięci (odczyt źródła 1, odczyt źródła 2, szybkie obliczenia, zapis), posiadanie większej liczby wątków nie pomaga. Znowu zależy to od tego, ile danych jednocześnie odczytujesz / zapisujesz (tj. Jeśli używasz SSE 4.2 i odczytujesz wartości 256 bitów, co zatrzymuje wszystkie wątki w ich kroku ... innymi słowy, 1 wątek jest prawdopodobnie o wiele łatwiejszy do wdrożenia i prawdopodobnie prawie tak szybko, jeśli nie szybciej. Zależy to od architektury procesu i pamięci, niektóre zaawansowane serwery zarządzają osobnymi zakresami pamięci dla oddzielnych rdzeni, więc oddzielne wątki będą szybsze, zakładając, że dane są poprawnie zapisane ... i dlatego, na niektórych architektur, 4 procesy będą działać szybciej niż 1 proces z 4 wątkami).

Alexis Wilke
źródło
4
Prawdopodobnie są jeszcze inne, ale ten, o którym wiem, to procesor POWER firmy IBM. Mieli systemy z 4 lub 8 wątkami na procesory. Teraz mogą podkręcać więcej rdzeni, więc zamiast tego oferują 2 wątki na rdzeń ...
Alexis Wilke
Jest to stare, ale większość procesorów Intel i5, i7 ma wielowątkowe procesory, na przykład procesory i7 zwykle mają 4 rdzenie, ale 8 wątków.
Edgar.A
4
Procesory nie mają wątków. Mają rdzenie fizyczne i logiczne. Dzięki hyperthreadingowi pojedynczy rdzeń fizyczny działa jak dwa rdzenie logiczne. Miałem technologię, która nalegała, aby procesory posiadające wątki były rzeczywistością, więc narysowałem zdjęcie na tablicy procesora z wystającym wrzecionem nici.
@TechnikEmpire Spójrz na ten intel.com/content/www/us/en/processors/core/… , być może wtedy możesz skontaktować się z intelem i narysować również ich wątki.
g7k
24

Rzeczywista wydajność będzie zależeć od tego, ile dobrowolnego poddania się da każdy wątek. Na przykład, jeśli wątki w ogóle NIE wykonują operacji we / wy i nie używają żadnych usług systemowych (tj. Są w 100% powiązane z procesorem), wówczas 1 wątek na rdzeń jest optymalny. Jeśli wątki robią coś, co wymaga oczekiwania, musisz eksperymentować, aby określić optymalną liczbę wątków. 4000 wątków spowodowałoby znaczne obciążenie związane z planowaniem, więc prawdopodobnie nie jest to również optymalne.

Jim Garrison
źródło
21

Odpowiedź zależy od złożoności algorytmów używanych w programie. Wymyśliłem metodę obliczania optymalnej liczby wątków, wykonując dwa pomiary czasów przetwarzania Tn i Tm dla dwóch dowolnych liczb wątków „n” i „m”. W przypadku algorytmów liniowych optymalna liczba wątków będzie wynosić N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).

Proszę przeczytać mój artykuł dotyczący obliczeń optymalnej liczby dla różnych algorytmów: pavelkazenin.wordpress.com

pkazen
źródło
4
Dlaczego jest to przegłosowane? Przykro mi, ale to najlepsza odpowiedź na to pytanie. gonzalo odnosi się do odważnej części pytania, a pkazen odnosi się do tytułu. Obie odpowiedzi są bardzo przydatne, ale odpowiedź pkazen jest istotna, ponieważ mamy systematyczną metodę przybliżania liczby wątków. Podaje nawet wzór na algorytmy linea.
tobiak777
1
Nie przegłosowałem, ale gdybym to zrobił, byłoby to na podstawie tego, że nie ma prawdziwego wyjaśnienia, dlaczego i jak optymalna liczba wątków może być związana ze złożonością algorytmu, z wyjątkiem przeczytania całego połączonego artykułu, który jest długim czytaniem (ze względu na złożoność artykułu). Poza tym niektóre aspekty tego artykułu nie są dla mnie jasne, co najważniejsze, w jaki sposób wyniki eksperymentalne potwierdzają teorię.
Codebling
Ponadto uważam, że w tych obliczeniach założono, że masz nieskończoną liczbę rdzeni procesora. Chociaż jest to zdecydowanie cenna informacja, pytanie dotyczy prawdziwych maszyn z małą liczbą rdzeni.
Navneeth,
9

Myślałem, że dodam tutaj inną perspektywę. Odpowiedź zależy od tego, czy pytanie zakłada słabe skalowanie, czy silne skalowanie.

Z Wikipedii :

Słabe skalowanie: jak zmienia się czas rozwiązania w zależności od liczby procesorów dla ustalonego rozmiaru problemu na procesor.

Silne skalowanie: jak zmienia się czas rozwiązania w zależności od liczby procesorów dla ustalonego całkowitego rozmiaru problemu.

Jeśli pytanie zakłada słabe skalowanie, wystarczy odpowiedź @ Gonzalo. Jeśli jednak pytanie zakłada silne skalowanie, jest coś więcej do dodania. W silnym skalowaniu zakładasz stały rozmiar obciążenia, więc jeśli zwiększysz liczbę wątków, zmniejszy się rozmiar danych, na których każdy wątek musi pracować. W nowoczesnych procesorach dostęp do pamięci jest drogi i lepiej byłoby zachować lokalność, przechowując dane w pamięci podręcznej. Dlatego prawdopodobną optymalną liczbę wątków można znaleźć, gdy zestaw danych każdego wątku mieści się w pamięci podręcznej każdego rdzenia (nie wchodzę w szczegóły omawiania, czy jest to pamięć podręczna L1 / L2 / L3 systemu).

Dzieje się tak nawet wtedy, gdy liczba wątków przekracza liczbę rdzeni. Załóżmy na przykład, że w programie jest 8 dowolnych jednostek (lub jednostek AU), które będą wykonywane na 4-rdzeniowej maszynie.

Przypadek 1: uruchom z czterema wątkami, przy czym każdy wątek musi ukończyć 2AU. Każdy wątek zajmuje 10 sekund ( z dużą ilością braków w pamięci podręcznej ). Przy czterech rdzeniach całkowity czas wyniesie 10s (10s * 4 wątki / 4 rdzenie).

Przypadek 2: uruchom z ośmioma wątkami, w których każdy wątek musi ukończyć 1AU. Każdy wątek zajmuje tylko 2 sekundy (zamiast 5 sekund ze względu na zmniejszoną liczbę braków pamięci podręcznej ). Przy czterech rdzeniach całkowity czas wyniesie 4 s (2 s * 8 wątków / 4 rdzenie).

Uprościłem problem i zignorowałem koszty ogólne wspomniane w innych odpowiedziach (np. Przełączniki kontekstu), ale mam nadzieję, że rozumiesz, że korzystniejsze może być posiadanie większej liczby wątków niż dostępna liczba rdzeni, w zależności od rozmiaru danych, które „ mam do czynienia z.

someneat
źródło
7

4000 wątków jednocześnie jest dość wysoka.

Odpowiedź brzmi: tak i nie. Jeśli robisz dużo blokowania I / O w każdym wątku, to tak, możesz pokazać znaczne przyspieszenie, wykonując do 3 lub 4 wątków na logiczny rdzeń.

Jeśli jednak nie robisz dużo blokowania, dodatkowe obciążenie związane z gwintowaniem tylko spowolni. Więc użyj profilera i zobacz, gdzie są wąskie gardła w każdym możliwym równoległym fragmencie. Jeśli wykonujesz ciężkie obliczenia, więcej niż 1 wątek na procesor nie pomoże. Jeśli wykonujesz dużo transferu pamięci, to też nie pomoże. Jeśli wykonujesz wiele operacji we / wy, na przykład w celu uzyskania dostępu do dysku lub dostępu do Internetu, tak, wiele wątków pomoże w pewnym stopniu lub przynajmniej sprawi, że aplikacja będzie bardziej responsywna.

Earlz
źródło
7

Reper.

Zaczynam zwiększać liczbę wątków dla aplikacji, zaczynając od 1, a następnie przechodzę do czegoś takiego jak 100, przeprowadzam trzy-pięć prób dla każdej liczby wątków i buduję sobie wykres prędkości działania w stosunku do liczby wątków .

Powinieneś upewnić się, że czterordzeniowy przypadek jest optymalny, z późniejszymi nieznacznymi wzrostami czasu działania, ale może nie. Może się zdarzyć, że twoja aplikacja ma ograniczone pasmo, tzn. Zestaw danych, który ładujesz do pamięci, jest ogromny, dostajesz wiele braków pamięci podręcznej itp., Dzięki czemu 2 wątki są optymalne.

Nie możesz wiedzieć, dopóki nie przetestujesz.

mmr
źródło
3

Przekonasz się, ile wątków możesz uruchomić na swoim komputerze, uruchamiając polecenie htop lub ps, które zwraca liczbę procesów na twoim komputerze.

Możesz użyć strony man o komendzie „ps”.

man ps

Jeśli chcesz obliczyć liczbę wszystkich procesów użytkowników, możesz użyć jednego z następujących poleceń:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Obliczanie liczby procesów użytkownika:

  1. ps --User root | wc -l

Możesz także użyć „htop” [Dokumentacja] :

Instalowanie na Ubuntu lub Debian:

sudo apt-get install htop

Instalowanie na Redhat lub CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Jeśli chcesz skompilować htop z kodu źródłowego, znajdziesz go tutaj .

Saeed Zahedian Abroodi
źródło
2

Idealny jest 1 wątek na rdzeń, o ile żaden z wątków się nie zablokuje.

Jeden przypadek, w którym może nie być to prawdą: na rdzeniu działają inne wątki, w którym to przypadku więcej wątków może dać Twojemu programowi większy wycinek czasu wykonania.

patros
źródło
Zależy to od tego, czy chcesz, aby procesy działające w tle działały jak bzdury, gdy aplikacja jest uruchomiona. W tym przypadku możesz po prostu ustawić priorytet dla każdego wątku w czasie rzeczywistym i uzyskać maksymalną moc. Ale użytkownicy lubią wielozadaniowość.
Earlz
2
Mamy do czynienia z magiczną, idealnie równoległą aplikacją. Gdybym kiedykolwiek stworzył coś takiego, czułbym się uprawniony do zatrzymania procesora tak bardzo, jak chcę.
patros,
2

Jednym z przykładów wielu wątków („puli wątków”) w porównaniu do jednego na rdzeń jest implementacja serwera WWW w systemie Linux lub Windows.

Ponieważ gniazda są odpytywane w Linuksie, wiele wątków może zwiększyć prawdopodobieństwo, że jeden z nich odpytuje odpowiednie gniazdo we właściwym czasie - ale ogólny koszt przetwarzania będzie bardzo wysoki.

W systemie Windows serwer zostanie zaimplementowany przy użyciu portów zakończenia we / wy - IOCP - które spowodują zdarzenie aplikacji: jeśli system we / wy zakończy działanie, system operacyjny uruchamia wątek rezerwowy, aby go przetworzyć. Po zakończeniu przetwarzania (zwykle z inną operacją We / Wy, jak w przypadku pary żądanie-odpowiedź) wątek wraca do portu IOCP (kolejki), aby czekać na następne zakończenie.

Jeśli żadne operacje we / wy nie zostały zakończone, przetwarzanie nie jest konieczne i wątek nie jest uruchamiany.

Rzeczywiście, Microsoft zaleca nie więcej niż jeden wątek na rdzeń w implementacjach IOCP. Dowolne I / O mogą być dołączone do mechanizmu IOCP. W razie potrzeby wniosek może również zostać wysłany przez MKOl.

Olof Forshell
źródło
Nie wiem, o którym Linuxie mówisz, ale moje bloki, dopóki nie nadejdzie połączenie. Sugeruję przeczytanie kilku rzeczy na temat select () i FD_SET () oraz podobnych funkcji / makr.
Alexis Wilke
Ok, więc nie ma postaci asynchronicznej, która zwraca się natychmiast?
Olof Forshell,
Ze strony podręcznika select ():timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke,
0

mówiąc z obliczeń i punktu widzenia związanego z pamięcią (obliczenia naukowe) 4000 wątków spowoduje, że aplikacja będzie działać bardzo wolno. Częścią problemu jest bardzo duży narzut związany z przełączaniem kontekstu i najprawdopodobniej bardzo słaba lokalizacja pamięci.

Ale zależy to również od Twojej architektury. Z miejsca, w którym słyszałem, procesory Niagara powinny być w stanie obsłużyć wiele wątków na jednym rdzeniu za pomocą zaawansowanej techniki tworzenia potoków. Jednak nie mam doświadczenia z tymi procesorami.

Anycorn
źródło
0

Mam nadzieję, że ma to sens, sprawdź wykorzystanie procesora i pamięci i ustaw wartość progową. Jeśli wartość progowa zostanie przekroczona, nie zezwalaj na tworzenie nowego wątku, w przeciwnym razie zezwól ...

M. Gopal
źródło