Czy są jakieś korzyści z używania procesora zamiast GPU?

63

Badałem procesory i karty graficzne i odkryłem, że procesory graficzne są znacznie szybsze niż procesory. Przeczytałem w tym jednym artykule , że 2-letni procesor graficzny Nvidia przewyższał procesor Intel Core I7 3,2 GHz 14 razy w pewnych okolicznościach. Jeśli procesory graficzne są tak szybkie, dlaczego programiści nie używają ich do każdej funkcji w grze? Czy procesory graficzne mogą robić coś innego niż grafika?

Daniel Pendergast
źródło
17
Jeśli grasz w grę, w której wszystko odkładasz na GPU, a procesor prawie nic nie robi, możesz zwiększyć wydajność, przywracając część obciążenia procesora.
Tetrad,
3
twój GPU jest może lepszy niż twój procesor, ale nie sądzę, że twoja karta graficzna jest lepsza niż twoja płyta główna (i nie będę porównywał systemu operacyjnego ze sterownikiem lol)
e-MEE
27
GPU is faster than a CPUjest fałszywym mitem, w który wielu ludzi wierzy po zobaczeniu testów porównawczych opartych na problemach specjalnie ukierunkowanych na GPU (ta klasa problemów nazywa się „kłopotliwie równoległymi problemami”), zobacz moją odpowiedź na pytanie SuperUser: Dlaczego wciąż używamy Procesory zamiast GPU?
Lie Ryan,
5
Jedną zaletą jest to, że każdy komputer ma procesor :)
Tim Holt,

Odpowiedzi:

50

„Czytałem, że samochody F1 są szybsze niż samochody jeżdżące po ulicach ... dlaczego ludzie nie używają samochodów F1?” Cóż ... Odpowiedź na to pytanie jest prosta: samochody F1 nie mogą się złamać ani skręcić tak szybko, jak większość samochodów (w tym przypadku najwolniejszy samochód może pokonać F1). Przypadki procesorów graficznych są bardzo podobne, są dobre w przestrzeganiu prostej linii przetwarzania, ale nie są tak dobre, jeśli chodzi o wybór różnych ścieżek przetwarzania.

Program wykonywany w GPU ma sens, gdy musi być wykonywany wiele razy równolegle, na przykład, gdy musisz zmieszać wszystkie piksele z tekstury A z pikselami z tekstury B i umieścić je wszystkie w tekstury C. To zadanie, gdy zostanie wykonane w procesor byłby przetwarzany w następujący sposób:

for( int i =0; i< nPixelCount; i++ )
     TexC[i] = TexA[i] + TexB[i];

Ale jest to powolne, gdy musisz przetworzyć wiele pikseli, więc GPU zamiast używać powyższego kodu, używa tylko następnego:

     TexC[i] = TexA[i] + TexB[i];

a następnie wypełnia wszystkie rdzenie tym programem (zasadniczo kopiując program do rdzenia), przypisując wartość idla każdego z nich. Wówczas przychodzi magia z GPU i sprawia, że ​​wszystkie rdzenie wykonują program w tym samym czasie , dzięki czemu wiele operacji jest znacznie szybszych niż program liniowy CPU.

Ten sposób pracy jest odpowiedni, gdy musisz przetwarzać w ten sam sposób bardzo dużo małych danych wejściowych, ale jest naprawdę zły, gdy musisz stworzyć program, który może mieć warunkowe rozgałęzienie. Zobaczmy teraz, co robi procesor, jeśli chodzi o sprawdzenie stanu:

  • 1: Uruchom program do pierwszej logicznej operacji
  • 2: oceń
  • 3: Kontynuuj wykonywanie od adresu pamięci wyniku porównania (jak w instrukcji asm JNZ)

Jest to bardzo szybkie dla procesora jako ustawienia indeksu, ale dla GPU, aby zrobił to samo, jest to o wiele bardziej skomplikowane. Ponieważ moc z GPU pochodzi z wykonywania tej samej instrukcji w tym samym czasie (są to rdzenie SIMD), muszą być zsynchronizowane, aby móc skorzystać z architektury układu. Konieczność przygotowania GPU do obsługi oddziałów oznacza mniej więcej:

  • 1: Utwórz wersję programu, która następuje tylko za gałąź A, wypełnij ten kod we wszystkich rdzeniach.
  • 2: Wykonaj program do pierwszej logicznej operacji
  • 3: Oceń wszystkie elementy
  • 4: Kontynuuj przetwarzanie wszystkich elementów następujących po gałęzi A, kolejkuj wszystkie procesy, które wybrały ścieżkę B (dla której nie ma programu w rdzeniu!). Teraz wszystkie te rdzenie, które wybrały ścieżkę B, będą bezczynne !! - najgorszym przypadkiem jest wykonanie jednego rdzenia i każdy inny rdzeń tylko czeka.
  • 5: Po zakończeniu przetwarzania wszystkich As, aktywuj wersję programu gałęzi B (kopiując ją z buforów pamięci do niewielkiej pamięci podstawowej).
  • 6: Wykonaj gałąź B.
  • 7: W razie potrzeby zmieszaj / scal oba wyniki.

Ta metoda może się różnić w zależności od wielu rzeczy (np. Niektórych bardzo małychgałęzie są w stanie działać bez potrzeby tego rozróżnienia), ale teraz już możesz zrozumieć, dlaczego rozgałęzienie byłoby problemem. Pamięci podręczne GPU są bardzo małe, nie można po prostu uruchomić programu z pamięci VRAM w sposób liniowy, musi on kopiować małe bloki instrukcji do rdzeni, które mają zostać wykonane, a jeśli masz wystarczającą liczbę rozgałęzień, twój procesor graficzny zostanie w większości zablokowany niż wykonanie jakikolwiek kod, co nie ma sensu, gdy pojawia się podczas wykonywania programu, który podąża tylko za jedną gałęzią, jak większość programów - nawet jeśli działa w wielu wątkach. W porównaniu z przykładem F1 byłoby to jak otwieranie spadochronów hamujących w każdym zakręcie, a następnie wysiadanie z samochodu, aby spakować je z powrotem do samochodu, aż do następnego zakrętu, w którym chcesz ponownie skręcić lub znaleźć czerwony semafor (następny zakręt najprawdopodobniej).

Wtedy oczywiście istnieje problem, że inne architektury są tak dobre w zadaniach logicznych, o wiele tańsze i bardziej niezawodne, znormalizowane, lepiej znane, energooszczędne itp. Nowsze karty wideo są mało kompatybilne ze starszymi bez emulacji oprogramowania, używają między nimi różnych instrukcji asm, nawet pochodzących od tego samego producenta, i że na razie większość aplikacji komputerowych nie wymaga tego rodzaju architektury równoległej, a nawet jeśli ich potrzebują, mogą korzystać ze standardowych api, takich jak OpenCL as wspomniane przez eBiznes lub za pośrednictwem interfejsu graficznego. Prawdopodobnie za kilka dziesięcioleci będziemy dysponować procesorami graficznymi, które mogą zastąpić procesory, ale nie sądzę, że nastąpi to w najbliższym czasie.

Polecam dokumentację z aplikacji AMD, która dużo wyjaśnia ich architekturę GPU, a także o instrukcjach NVIDIA w instrukcjach CUDA, co bardzo mi pomogło w zrozumieniu tego. Nadal nie rozumiem niektórych rzeczy i mogę się mylić, prawdopodobnie ktoś, kto wie więcej, może potwierdzić lub zaprzeczyć moim oświadczeniom, co byłoby dobre dla nas wszystkich.

Pablo Ariel
źródło
6
dziwna analogia, ale dobrze, że tak the fastest isn't always the fastest.
Lie Ryan,
1
Dzięki! Myślę, że to interesujący temat, ponieważ wiąże wiele koncepcji programowania gier ze sposobem działania sprzętu, który jest nieco zapomniany w krainie współczesnych języków wysokiego poziomu. Jest jeszcze kilka rzeczy, które chciałbym dodać, ale napisanie odpowiedzi zajęło już trochę czasu, więc postaram się ją później zaktualizować, na przykład możliwości procesorów w trybie „chronionym”, szybkość magistrali pamięci itp., Ale mam nadzieję, że to wyjaśnienie pewne wady techniczne wykonywania wszystkiego w GPU.
Pablo Ariel,
6
Analogia byłaby znacznie lepsza, gdyby była dokładna. Samochody F1 mają ogromne zdolności hamowania, które pozwalają im utrzymywać wysoką prędkość na zakrętach zamiast hamować z dużym wyprzedzeniem. Szybkie pokonywanie zakrętów jest również lepsze dzięki dużym opadom, chociaż promień skrętu prawdopodobnie nie jest zbyt dobry na parkingach. Lepsze powody mogą obejmować brak miejsca do przechowywania, lusterko wsteczne, klimatyzację, tempomat, ochronę przed żywiołami, siedzenia pasażera, zawieszenie i prześwit do obsługi złych dróg lub różne inne rzeczy powszechne w pojazdach osobowych.
GargantuChet,
5
@Pablo Ariel Odpowiadam na stwierdzenie: „Samochody F1 nie mogą się złamać ani skręcić tak szybko, jak większość samochodów”. Sugerujesz, że bolidy F1 mogą przyspieszać tylko w linii prostej i nie są zbyt dobre na zakrętach lub podczas hamowania. Ale samochody F1 mogą hamować znacznie szybciej niż „większość samochodów” i są doskonałe na szybkich zakrętach.
GargantuChet,
4
Analogia jest bardziej dokładna, jeśli myślisz raczej w Dragsterach niż w samochodach F1
Agustin Meriles,
32

Procesory graficzne są bardzo dobre do zadań równoległych. Co jest świetne ... jeśli wykonujesz równoległe zadania.

Gry są mniej ważne równoległego rodzaju aplikacji. Pomyśl o głównej pętli gry. AI (załóżmy, że gracz jest traktowany jako specjalny przypadek AI) musi reagować na kolizje wykryte przez fizykę. Dlatego musi działać później. A przynajmniej fizyka musi wywoływać procedury AI w granicach systemu fizyki (co z wielu powodów nie jest dobrym pomysłem). Grafika nie może działać, dopóki fizyka się nie uruchomi, ponieważ to fizyka aktualizuje pozycję obiektów. Oczywiście AI również musi działać przed renderowaniem, ponieważ AI może odradzać nowe obiekty. Dźwięki muszą być uruchamiane za sterowaniem AI i odtwarzaczem

Ogólnie rzecz biorąc, gry mogą się nawiązywać na kilka sposobów. Grafika może być wydzielona w wątku; pętla gry może przesunąć wiązkę danych w wątku graficznym i powiedzieć: renderuj to. Może dokonać podstawowej interpolacji, dzięki czemu główna pętla gry nie musi być zsynchronizowana z grafiką. Dźwięk to kolejny wątek; pętla gry mówi „zagraj w to” i jest odtwarzana.

Potem wszystko zaczyna boleć. Jeśli masz złożone algorytmy ścieżkowania (takie jak RTS), możesz je wątkować. Algorytmy mogą zająć kilka ramek, ale będą one przynajmniej współbieżne. Poza tym jest to dość trudne.

Więc patrzysz na 4 wątki: grę, grafikę, dźwięk i być może długoterminowe przetwarzanie AI. To nie jest dużo. A to nie jest prawie wystarczająco dla kart graficznych, które mogą mieć setki wątków w locie na raz. To właśnie zapewnia GPU ich wydajność: możliwość korzystania ze wszystkich tych wątków jednocześnie. A gry po prostu tego nie potrafią.

Być może teraz będziesz w stanie przejść „szeroki” dla niektórych operacji. Na przykład AI są zwykle niezależne od siebie. Abyś mógł przetwarzać kilkadziesiąt AI jednocześnie. Aż do momentu, kiedy faktycznie będziesz musiał uzależnić je od siebie. Więc masz kłopoty. Obiekty fizyki są podobnie niezależne ... chyba że istnieje ograniczenie między nimi i / lub zderzają się z czymś. Potem stają się bardzo zależni.

Plus, jest fakt, że GPU po prostu nie ma dostępu do danych wejściowych użytkownika, co, jak rozumiem, jest w pewnym sensie ważne dla gier. Trzeba by to zapewnić. Nie ma też bezpośredniego dostępu do plików ani żadnej prawdziwej metody rozmowy z systemem operacyjnym; więc znowu musiałby istnieć jakiś sposób, aby to zapewnić. Aha i całe to przetwarzanie dźwięku? Procesory graficzne nie emitują dźwięków. Muszą więc wrócić do procesora, a potem do układu dźwiękowego.

Aha, kodowanie GPU jest okropne. Trudno to naprawić, a to, co jest „właściwe” dla jednej architektury GPU, może być bardzo, bardzo złe dla innej. I to nie tylko przejście z AMD na NVIDIA; które mogą być przełączane z GeForce 250 na GeForce 450. To zmiana w podstawowej architekturze. I może łatwo sprawić, że kod nie będzie działał poprawnie. C ++, a nawet C są niedozwolone; najlepsze, co dostajesz, to OpenCL, który jest trochę jak C, ale bez niektórych subtelności. Jak rekurencja . Zgadza się: brak rekurencji na GPU.

Debugowanie? Och, mam nadzieję, że nie podobają ci się funkcje debugowania twojego IDE, ponieważ z pewnością nie będą one dostępne. Nawet jeśli korzystasz z GDB, pocałuj się na pożegnanie. Musisz uciekać się do printfdebugowania ... poczekaj, nie ma printfna GPU. Będziesz musiał pisać w lokalizacjach pamięci, a program pośredniczący procesora je odczyta.

Zgadza się: ręczne debugowanie. Powodzenia z tym.

Te przydatne biblioteki, których używasz w C / C ++? A może jesteś bardziej facetem .NET, korzystającym z XNA i tak dalej. Lub cokolwiek. To nie ma znaczenia, ponieważ nie możesz użyć żadnego z nich na GPU. Musisz kodować wszystko od zera. A jeśli masz już bazę kodu, ciężko: czas przepisać cały ten kod.

Więc tak. To jest okropne w przypadku każdej złożonej gry. I to by nawet nie działało, ponieważ gry po prostu nie są wystarczająco równoległe, aby to mogło pomóc.

Nicol Bolas
źródło
21

Dlaczego nie jest tak łatwo odpowiedzieć - ważne jest, aby pamiętać, że procesory graficzne to wyspecjalizowane procesory, które tak naprawdę nie są przeznaczone do ogólnego użytku, jak zwykły procesor. Ze względu na tę specjalizację nie jest zaskakujące, że procesor graficzny może przewyższyć procesor w zakresie zadań, dla których został specjalnie zaprojektowany (i zoptymalizowany), ale niekoniecznie oznacza to, że może zastąpić pełną funkcjonalność i wydajność uogólnionego procesora.

Podejrzewam, że programiści nie robią tego z różnych powodów, w tym:

  • Chcą, aby grafika była możliwie szybka i najwyższej jakości, a używanie cennych zasobów GPU może w to przeszkadzać.

  • Konieczne może być napisanie kodu specyficznego dla GPU, co prawdopodobnie spowoduje dodatkową złożoność ogólnego programowania gry (lub aplikacji).

  • Karta graficzna zwykle nie ma dostępu do zasobów, takich jak karty sieciowe, klawiatury, myszy i joysticki, więc i tak nie jest w stanie poradzić sobie z każdym aspektem gry.

W odpowiedzi na drugą część pytania: Tak, istnieją inne zastosowania. Na przykład projekty takie jak SETI @ Home (i prawdopodobnie inne projekty BOINC) używają procesorów graficznych (takich jak nVidia) do szybkich złożonych obliczeń:

  Uruchom SETI @ home na GPU NVIDIA
  http://setiathome.berkeley.edu/cuda.php

( Podoba mi się twoje pytanie, ponieważ stanowi ciekawy pomysł ).

Randolf Richardson
źródło
18

Procesory są bardziej elastyczne, na ogół łatwiej je programować, mogą one uruchamiać pojedyncze wątki znacznie szybciej.

Chociaż współczesne układy GPU można zaprogramować tak, aby rozwiązywały praktycznie każde zadanie, uzyskują przewagę prędkości tylko wtedy, gdy mogą wykorzystać architekturę równoległą. Zwykle dzieje się tak w przypadku wysoce powtarzalnych „prostych” zadań. Duża część kodu, który piszemy, rozgałęzia się zbyt nieprzewidywalnie, aby działała wydajnie na GPU.

Ponadto możesz poświęcić dużo czasu na optymalizację kodu dla różnych układów graficznych. Chociaż OpenCL jest dostępny, aby ten sam kod działał na wielu różnych układach graficznych, wymienisz część przewagi szybkości na ten luksus.

Z perspektywy programisty gier na ogół chcielibyśmy, aby nasza gra działała na komputerach z mniejszymi kartami graficznymi. Niektóre zintegrowane układy nie mają wymaganej programowalności, ale jeśli tak, są tak wolne, że nie pobiją procesora o bardzo dużą marżę, nawet w przypadku zadań, w których powinny być dobre. I oczywiście, jeśli użyjesz niskiej klasy procesora graficznego do gry, będziesz bardzo potrzebował mocy obliczeniowej z renderowania grafiki.

Rzeczywiście perspektywy są świetne, ale kiedy tworzysz grę zamiast łamać hasła, praktyczne problemy w większości przypadków przeważają nad korzyściami.

aaaaaaaaaaaa
źródło
6

Procesory graficzne są bardzo trudne do zaprogramowania. Powinieneś poszukać howto, aby posortować listę na GPU . Wiele tez ma na to ochotę.

Użycie procesora z jednym wątkiem jest łatwe, użycie wielu wątków jest trudniejsze, użycie wielu komputerów z biblioteką równoległą, ponieważ PVM lub MPI jest trudne, a użycie GPU jest najtrudniejsze.

Ellis
źródło
4

Poza tym, na co odpowiedział Randolf Richardson, istnieją pewne funkcje, których procesory GPU nie są w stanie obsłużyć samodzielnie. Na przykład niektóre polecenia zarządzania pamięcią grafiki są przetwarzane przez CPU, ponieważ GPU nie może ich obsłużyć.

Jest jeszcze jeden ważny powód: GPU jest przeznaczona do obliczeń wielowątkowych. Oznacza to, że twórcy GPU mogą łatwo dodawać rdzenie, gdy chcą zwiększyć moc obliczeniową. Ale jest wiele zadań, których nie można podzielić na mniejsze problemy, takie jak obliczenie n-tej liczby z serii Fibonacciego . W takich sytuacjach procesor jest znacznie szybszy, ponieważ jest bardziej zoptymalizowany do zadań jednowątkowych.

Ali1S232
źródło
4

Istnieje wiele odpowiedzi sugerujących, że procesory graficzne są szybsze tylko dlatego, że obsługują zadania równolegle. To trochę przesadza. Procesory graficzne mogą być bardziej wydajne z innych powodów, takich jak możliwość bardziej restrykcyjnego dostępu do pamięci, nieobsługiwanie tylu typów danych, możliwość posiadania bardziej wydajnego zestawu instrukcji itp. Wczesne procesory graficzne mogą nadal rysować tylko 1 piksel w pewnego czasu, ale ważny był fakt, że mogli wykonać 1 w każdym cyklu.

Prawdziwa różnica polega na tym, że są to 2 różne typy maszyn, które są przystosowane do wykonywania dobrze w różnych kategoriach zadań, które wydają się podobne, ale w rzeczywistości są całkiem różne. To jak porównywanie samolotu do samochodu. Samolot ma znacznie wyższą prędkość maksymalną, ale ma więcej ograniczeń dotyczących sposobu użytkowania. W sytuacjach, w których możesz odbyć tę samą podróż z dowolnym rodzajem, samolot wydaje się lepszy.

Kylotan
źródło
Analogia na temat samolotu jest bardzo dobra (+1), ale w odniesieniu do procesorów obsługujących różne typy danych, jest to właściwie koncepcja języka wyższego poziomu, ponieważ procesory (przynajmniej w przestrzeni Intela) zwykle mają do czynienia dane w bardzo podstawowych formach (np. bity, bajty, słowa, dwory itp.). Istnieją pewne instrukcje w ścisłej pętli dotyczące skanowania lub kopiowania danych zakończonych bajtem zerowym, ale dane w tych przypadkach tak naprawdę nie są rozpoznawane przez CPU jako szczególny typ (inny niż fragment danych zakończony zerem) w kontekście tych pętli).
Randolf Richardson
@Randolf: Procesory mają różne instrukcje i rejestry, które obsługują różne typy danych niskiego poziomu (np. Podpisane vs. niepodpisane, całki vs. zmiennoprzecinkowe). Tak jest w przypadku 8086 i rzeczywiście większości współczesnych architektur, i to nie jest całkowicie za darmo.
Kylotan,
Jestem pewien, że nadal wykonują dużo przetwarzania liniowego w architekturze bazowej. Od strony programowania wymaga tylko instrukcji do GPU, ale rdzenie nie działają dokładnie równolegle ze względu na ich zależność od innego sprzętu, który nie jest równoległy, taki jak odczyt z pamięci, prawdopodobnie GPU może dostarczyć dane do jednego rdzenia na czas.
Pablo Ariel,
3

Deweloperzy nie używać GPU dla wszystkich funkcji są dobrzy. Używają procesorów do wszystkich funkcji, w których są dobrzy. Co sprawia, że ​​myślisz, że nie?

Procesory graficzne są dobre w zadaniach, które mogą być masowo sparaliżowane i wymagają ogromnych ilości obliczeń przy niskim zapotrzebowaniu na pamięć lub wysokiej korelacji czasowej przy niewielkim podejmowaniu decyzji. Obejmuje to renderowanie obrazów, symulacje fizyki (cząstki, zderzenie, materiał, woda, odbicie) i tak dalej. Właśnie dlatego nowoczesne gry wykorzystują procesor graficzny.

Procesory są dobre w zadaniach, które nie są dobrze równoległe i wymagają ogromnej ilości decyzji. Mogą tolerować wysokie wymagania dotyczące pamięci, nawet przy umiarkowanej korelacji czasowej. Obejmuje to sztuczną inteligencję, interfejs użytkownika, dyskowe i sieciowe operacje we / wy itd. Właśnie dlatego nowoczesne gry wykorzystują procesor.

David Schwartz
źródło
1

Readback to kolejny powód, dla którego mogę od czasu do czasu preferować procesor. Nie pod względem przepustowości (ponieważ GPU-> przepustowość procesora nie jest tak dużym problemem na nowoczesnym sprzęcie), ale pod względem zablokowania rurociągu. Jeśli chcesz pobrać wyniki z obliczeń i zrobić z nimi coś interesującego lub przydatnego, użycie GPU nie jest mądrym wyborem (w ogólnym przypadku - będą specjalne przypadki, w których może pozostać odpowiednie), ponieważ czytanie zawsze będzie wymagało GPU, aby zatrzymać cokolwiek robi, opróżnić wszystkie oczekujące polecenia i poczekać na zakończenie odczytu. Może to zabić wydajność w zakresie, w jakim nie tylko niweczy korzyści wynikające z używania GPU, ale może być znacznie wolniejsze.

Maximus Minimus
źródło
0

To jest stary wątek, ale ten niedawno opublikowany artykuł może odpowiedzieć na to pytanie. Ten artykuł, opublikowany w ACM Computing Surveys 2015, pokazuje, że każdy z procesorów i procesorów graficznych ma swoje unikalne zalety, a zatem niniejszy dokument stanowi uzasadnienie dla odejścia od paradygmatu „CPU vs. GPU” do paradygmatu „CPU-GPU Cooperative Computing”.

Badanie heterogenicznych technik obliczeniowych CPU-GPU

użytkownik984260
źródło