Jak uzyskać 100% użycie procesora z programu w C.

79

To dość interesujące pytanie, więc pozwól mi ustawić odpowiednią scenę. Pracuję w National Museum of Computing i właśnie udało nam się uruchomić super komputer Cray Y-MP EL z 1992 roku i naprawdę chcemy zobaczyć, jak szybko może działać!

Zdecydowaliśmy, że najlepszym sposobem na zrobienie tego jest napisanie prostego programu w C, który obliczałby liczby pierwsze i pokazywałby, ile czasu to zajęło, a następnie uruchomienie programu na szybkim, nowoczesnym komputerze stacjonarnym i porównanie wyników.

Szybko wymyśliliśmy ten kod, aby policzyć liczby pierwsze:

Który na naszym dwurdzeniowym laptopie z systemem Ubuntu (Cray działa z UNICOS) działał idealnie, uzyskując 100% wykorzystanie procesora i zajmując około 10 minut. Kiedy wróciłem do domu, zdecydowałem się wypróbować go na moim nowoczesnym komputerze do gier z sześciordzeniowym rdzeniem i tutaj pojawiają się nasze pierwsze problemy.

Po raz pierwszy dostosowałem kod do uruchamiania w systemie Windows, ponieważ właśnie tego używał komputer do gier, ale ze smutkiem stwierdziłem, że proces pobierał tylko około 15% mocy procesora. Pomyślałem, że to musi być Windows to Windows, więc uruchomiłem Live CD Ubuntu, myśląc, że Ubuntu pozwoli na uruchomienie procesu z pełnym potencjałem, tak jak to miało miejsce wcześniej na moim laptopie.

Jednak mam tylko 5% wykorzystania! Więc moje pytanie brzmi: jak mogę dostosować program do działania na moim automacie do gier w systemie Windows 7 lub Linux na żywo przy 100% wykorzystaniu procesora? Inną rzeczą, która byłaby świetna, ale niekonieczna, jest to, że produktem końcowym może być jeden plik .exe, który można łatwo dystrybuować i uruchamiać na komputerach z systemem Windows.

Wielkie dzięki!

PS Oczywiście ten program tak naprawdę nie działał ze specjalistycznymi procesorami Crays 8 i to jest zupełnie inna kwestia… Jeśli wiesz cokolwiek o optymalizacji kodu do pracy na super komputerach Cray z lat 90-tych, daj nam znać!

komiwojażer
źródło
8
Nie mogę uwierzyć, że nie ma tagu Unicos . ;)
Edward Thomson
32
To dziwne, że ten jeden program wątek zabrał 100% użycia procesora na dwurdzeniowy procesor)))
mikithskegg
24
Czy tylko ja nie uważam tego pytania za interesujące? Chodź, uruchom program jednowątkowy na maszynie n-rdzeniowej i zapytaj, dlaczego używa 1 / n procesora, jest po prostu ... nieważne, po prostu przegłosowałem :-)
Gunther Piez
16
@drhirsch Cóż, pytanie pokazuje wysiłek badawczy. Dałem +1 za to - nawet jeśli w OP brakuje czegoś fundamentalnego w obliczeniach wielordzeniowych.
Mysticial
9
@drhirsch Na stronie jest wiele nieciekawych pytań. Jednak interesujące czy nie jest subiektywne. Być może brakuje mu podstaw, a to nie jest subiektywne. Jak powiedział Mystical, pokazuje wysiłek badawczy i nie jest tak łatwo odpowiedzieć, jak mogłoby się wydawać.
Carl

Odpowiedzi:

81

Jeśli chcesz mieć 100% procesor, musisz użyć więcej niż 1 rdzenia. Aby to zrobić, potrzebujesz wielu wątków.

Oto wersja równoległa korzystająca z OpenMP:

Musiałem zwiększyć limit, aby 1000000na moim komputerze zajęło to więcej niż 1 sekundę.

Wynik:

Maszyna obliczyła wszystkie 78498 liczb pierwszych poniżej 1000000 w 29,753 sekundy

Oto Twój 100% procesor:

wprowadź opis obrazu tutaj

Mistyczne
źródło
1
@ cha0site Tak, głównie odpowiedziałem na pytanie dotyczące automatu do gier. Istnieją zdecydowanie bardziej interesujące sposoby na ustalenie procesora. Jednym z bardziej znanych testów porównawczych, które zrobiłem, jest moja odpowiedź na to pytanie - które spowodowało przegrzanie 2 z 4 maszyn, które testowałem.
Mysticial
1
@Mystical Offtopic: Jaki sprzęt używasz? Mój Hex-Core AMD @ 3,2 Ghz zrobił to w 92 sekundy ...
bag-man,
1
@ Owen: Ma Core i7 2600K ... Jestem zazdrosny.
cha0site
19
Augh! Za ... dużo ... różu!
Mateen Ulhaq
2
@MohammadFadin en.wikipedia.org/wiki/Parallel_computing Zasadniczo musisz być w stanie przetwarzać wiele zadań równolegle, aby móc korzystać z komputera wielordzeniowego.
Mysticial
24

Uruchamiasz jeden proces na maszynie wielordzeniowej - więc działa tylko na jednym rdzeniu.

Rozwiązanie jest dość łatwe, ponieważ po prostu próbujesz przypiąć procesor - jeśli masz N rdzeni, uruchom program N razy (oczywiście równolegle).

Przykład

Oto kod, który uruchamia program NUM_OF_CORESrównolegle. Jest to kod POSIXy - używa fork- więc powinieneś go uruchomić pod Linuksem. Jeśli to, co czytam o Cray, jest poprawne, może być łatwiej przenieść ten kod niż kod OpenMP w drugiej odpowiedzi.

Wynik

cha0site
źródło
Ach tak, jakbyś musiał uruchomić Prime95, masz wiele jego instancji ... Z pewnością jest sposób, aby jeden proces używał wielu rdzeni? Podobnie jak programy do łamania skrótów.
bag-man
Cóż, jeden proces może wykorzystywać wątki do przetwarzania wieloprocesowego, ale nie sądzę, żeby o to ci chodziło, ponieważ wątek jest w tym kontekście prawie oddzielnym procesem. To, o czym tak naprawdę mówimy, to „głowy egzekucji”, czy to wątki, czy procesy. Więc nie, nie ma sposobu, aby program jednowątkowy działał na wielu rdzeniach, musisz go przepisać. Czasami jest to naprawdę trudne. A czasami jest to faktycznie niemożliwe.
cha0site
Cóż, myślę, że nie będzie to tak trudne, jak sprawienie, by program działał również dla Cray. Biorąc pod uwagę, że jestem w tym całkiem nowy (Co mnie zdradziło: P), od czego byłoby dobre miejsce, aby zacząć?
bag-man
@Owen: Cóż, UNICOSwygląda na to, że jest trochę podobny do Uniksa (Wikipedia tak uważa), więc prawdopodobnie tak fork(). Myślę, że powinieneś się nauczyć, jak tego używać.
cha0site
2
Oooh! Teraz, gdy masz przykład, dałeś +1. :)
Mysticial
7

naprawdę chcemy zobaczyć, jak szybko to może jechać!

Twój algorytm generowania liczb pierwszych jest bardzo nieefektywny. Porównaj to z primegenem, który generuje 50847534 liczby pierwsze do 1000000000 w zaledwie 8 sekund na Pentium II-350.

Aby łatwo zużyć wszystkie procesory, możesz rozwiązać kłopotliwie równoległy problem, np. Obliczyć zbiór Mandelbrota lub użyć programowania genetycznego, aby pomalować Mona Lisę w wielu wątkach (procesach).

Innym podejściem jest pobranie istniejącego programu porównawczego dla superkomputera Cray i przeniesienie go na nowoczesny komputer PC.

jfs
źródło
Nie ma znaczenia, że ​​algorytm jest nieefektywny, ponieważ celem nie jest obliczenie liczb pierwszych, ale wykonanie ogólnie trudnego zadania i sprawdzenie, o ile lepiej lub gorzej radzi sobie z nim niż nowoczesny komputer stacjonarny. Wydajny algorytm utrudniłby to porównanie, a nawet zrujnowałby wyniki, jeśli jest tak dobry, że celowo wykorzystuje nowoczesne funkcje / dziwactwa procesora.
Numeron
5

Powodem, dla którego otrzymujesz 15% na szesnastkowym procesorze rdzeniowym, jest to, że twój kod wykorzystuje 1 rdzeń w 100%. 100/6 = 16,67%, co przy użyciu średniej ruchomej z harmonogramowaniem procesu (proces działałby z normalnym priorytetem) można łatwo określić jako 15%.

Dlatego, aby użyć 100% procesora, musiałbyś użyć wszystkich rdzeni swojego procesora - uruchom 6 równoległych ścieżek kodu wykonawczego dla procesora z rdzeniem szesnastkowym i uzyskaj tę skalę aż do liczby procesorów, które ma twoja maszyna Cray :)

Carl
źródło
Problem z robieniem tego polega na tym, że w jaki sposób mogę uzyskać wyraźny obraz prędkości każdej maszyny? Najwyraźniej Cray ma również "procesory wektorowe", więc wymaga więcej pracy, aby działał poprawnie
bag-man
Nie wiem. Prawdopodobnie różnice w procesach planowania.
Carl
2

Bądź również bardzo świadomy sposobu ładowania procesora. Procesor może wykonywać wiele różnych zadań i chociaż wiele z nich jest zgłaszanych jako „ładowanie procesora w 100%”, każdy z nich może wykorzystywać w 100% różne części procesora. Innymi słowy, bardzo trudno jest porównać dwa różne procesory pod kątem wydajności, a zwłaszcza dwie różne architektury procesorów. Wykonanie zadania A może faworyzować jeden procesor nad innym, podczas wykonywania zadania B może być łatwo odwrotnie (ponieważ dwa procesory mogą mieć różne zasoby wewnętrzne i mogą wykonywać kod w bardzo różny sposób).

To jest powód, dla którego oprogramowanie jest tak samo ważne dla optymalnego działania komputerów, jak sprzęt. Jest to rzeczywiście bardzo prawdziwe również w przypadku „superkomputerów”.

Jedną miarą wydajności procesora mogą być instrukcje na sekundę, ale z drugiej strony instrukcje nie są tworzone jednakowo na różnych architekturach procesora. Inną miarą może być wydajność pamięci podręcznej we / wy, ale infrastruktura pamięci podręcznej też nie jest równa. Wtedy miarą mogłaby być liczba instrukcji przypadających na jeden zużywany wat, ponieważ dostarczanie i rozpraszanie mocy jest często czynnikiem ograniczającym podczas projektowania komputera klastrowego.

Twoje pierwsze pytanie powinno więc brzmieć: który parametr wydajności jest dla Ciebie ważny? Co chcesz zmierzyć? Jeśli chcesz zobaczyć, która maszyna uzyskuje najwięcej FPS w Quake 4, odpowiedź jest prosta; Twój sprzęt do gier to zrobi, ponieważ Cray nie może w ogóle uruchomić tego programu ;-)

Pozdrawiam, Steen

Steen Schmidt
źródło
2

TLDR; Przyjęta odpowiedź jest zarówno nieefektywna, jak i niekompatybilna. Podążanie za algo działa 100x szybciej.

Nie można uruchomić kompilatora gcc dostępnego na MAC omp . Musiałem zainstalować llvm (brew install llvm ). Ale nie widziałem, aby bezczynność procesora spadała podczas uruchamiania wersji OMP.

Oto zrzut ekranu podczas działania wersji OMP. wprowadź opis obrazu tutaj

Alternatywnie, użyłem podstawowego wątku POSIX, który można uruchomić za pomocą dowolnego kompilatora c i zobaczyłem prawie cały procesor zużyty, gdy nos of thread=no of cores = 4 (MacBook Pro, Intel Core i5 2,3 GHz). Oto program -

Zwróć uwagę, jak zużywa się cały procesor - wprowadź opis obrazu tutaj

PS - Jeśli zwiększysz liczbę wątków, rzeczywiste użycie procesora spadnie (spróbuj utworzyć liczbę wątków = 20), ponieważ system zużywa więcej czasu na przełączanie kontekstu niż rzeczywiste przetwarzanie.

Nawiasem mówiąc, moja maszyna nie jest tak mocna jak @mystical (zaakceptowana odpowiedź). Ale moja wersja z podstawową obsługą wątków POSIX działa znacznie szybciej niż wersja OMP. Oto wynik -

wprowadź opis obrazu tutaj

PS Zwiększ obciążenie wątków do 2,5 miliona, aby zobaczyć zużycie procesora, ponieważ trwa ono krócej niż sekundę.

sapy
źródło
0

Spróbuj zsynchronizować swój program używając np. OpenMP. Jest to bardzo proste i skuteczne ramy tworzenia programów równoległych.

mikithskegg
źródło
0

Aby szybko ulepszyć jeden rdzeń, usuń wywołania systemowe, aby ograniczyć przełączanie kontekstów. Usuń te linie:

Pierwsza jest szczególnie zła, ponieważ w każdej iteracji będzie generować nowy proces.

Joel
źródło
0

Po prostu spróbuj spakować i rozpakować duży plik, nic tak jak ciężkie operacje we / wy nie mogą używać procesora.

Nima Mohammadi
źródło