„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ść i
dla 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.