Implementowanie algorytmów za pomocą shaderów obliczeniowych vs. shaderów potokowych

10

Dzięki dostępności shaderów obliczeniowych zarówno dla DirectX, jak i OpenGL można teraz zaimplementować wiele algorytmów bez przechodzenia przez potok rasteryzacji i zamiast tego użyć obliczeń ogólnego przeznaczenia na GPU, aby rozwiązać problem.

W przypadku niektórych algorytmów wydaje się, że staje się to intuicyjnym rozwiązaniem kanonicznym, ponieważ z natury nie są oparte na rasteryzacji, a shadery oparte na rasteryzacji wydawały się obejściem dla wykorzystania mocy GPU (prosty przykład: tworzenie tekstury szumu. Tu nie trzeba rasteryzować quada ).

Biorąc pod uwagę algorytm, który można wdrożyć na dwa sposoby, czy istnieją ogólne (potencjalne) korzyści w zakresie wydajności w porównaniu do korzystania z shaderów obliczeniowych w porównaniu z normalną trasą? Czy są wady, na które powinniśmy uważać (na przykład czy istnieje jakiś niezwykły narzut związany z przełączaniem się z / w celu obliczania shaderów w czasie wykonywania)?

Czy są jakieś inne zalety lub wady do rozważenia przy wyborze między tymi dwoma?

TravisG
źródło
Jeśli tag wydajności jest rzeczywiście istotny, rozważ obejrzenie tego filmu z artykułu Game Engine Gems „Cloth Simulation” z Marco Fratarcangeli: youtube.com/watch?v=anNClcux4JQ . Możesz przeczytać komentarze i dowiedzieć się niezręcznej rzeczy: implementacja oparta na GLSL / shaderze była szybsza niż przy użyciu CUDA lub OpenCL (ten ostatni z powodu słabej obsługi sterowników w 2010 roku). Istnieją pewne różnice niskiego poziomu, które ... robią różnicę.
teodron
@teodron Nie mam dostępnych klejnotów GPU i nie mogę znaleźć kodu źródłowego. Czy autor rzeczywiście używał shaderów wierzchołków GLSL + pikseli, czy używał shaderów obliczeniowych GLSL?
TravisG
Tak! Przed CUDA tak społeczność implementowała funkcje GPGPU. Oto link do OpenCloth, aby zobaczyć, jak można to osiągnąć za pomocą czystego GLSL OR Cuda: code.google.com/p/opencloth/source/browse/trunk/…
teodron

Odpowiedzi:

7

Nie ma właściwej odpowiedzi, jeśli zamierzasz bezpośrednio skorzystać z obliczeń shadrsów obliczeniowych / GPGPU, jest to w dużym stopniu zależne od rodzaju wdrażanego algorytmu, shadery obliczeniowe i CUDA / OpenCL to bardziej ogólne podejście do pokonania niektórych ograniczeń włamania do starych języków cieniowania. najważniejsze korzyści, które otrzymasz:

  • Dostęp do informacji przestrzennej. w starym hacku GLSL (no cóż, to był hack!) daje niewiele informacji na temat fragmentów sąsiadów, ponieważ używa współrzędnych tekstury. W shaderach obliczeniowych / CUDA / OpenCL dostęp do informacji przestrzennych jest znacznie bardziej elastyczny, teraz możesz zaimplementować algorytmy takie jak wyrównanie histogramu na GPU z nieuporządkowanym dostępem do tekstury / bufora.
  • Zapewnia synchronizację wątków i atomikę .
  • Przestrzeń obliczeniowa: stary hack GLSL utrwali połączenie przestrzeni obliczeniowej wierzchołków / fragmentów z modułem cieniującym. Moduł cieniujący fragmentów będzie działał z liczbą fragmentów, moduł cieniujący wierzchołków będzie działał z liczbą wierzchołków. W module obliczeniowym definiujesz własną przestrzeń.
  • Skalowalność : twój moduł cieniujący / CUDA / OpenCL może skalować się do liczby dostępnych GPU SM (wieloprocesor strumieniowy) dostępnych w przeciwieństwie do twojego starego modułu cieniującego GLSL, który powinien być wykonywany na tym samym SM. (Na podstawie komentarzy Nathana Reeda twierdzi, że to nieprawda, a shadery powinny być skalowane tak dobrze, jak powinny być shadery obliczeniowe. Nadal nie jestem pewien, choć muszę sprawdzić dokumentację).
  • Przełączanie kontekstu : Powinno być trochę przełączania kontekstu, ale powiedziałbym, że zależy to od aplikacji, więc najlepiej jest profilować aplikację.

Cóż, moim zdaniem , jeśli chcesz pójść drogą shaderów obliczeniowych, chociaż niektóre algorytmy mogą być bardziej odpowiednie, istnieją pewne względy, które należy wziąć pod uwagę:

  1. Kompatybilność sprzętowa i wsteczna . Shadery obliczeniowe są dostępne tylko na nowszym sprzęcie, a jeśli wybierasz produkt komercyjny (np. Grę), musisz spodziewać się, że wielu użytkowników może nie być w stanie uruchomić Twojego produktu.
  2. Zwykle potrzebujesz dodatkowej wiedzy na temat architektury GPU / procesora , programowania równoległego i wielowątkowości (np . Współużytkowanie pamięci, spójność pamięci, synchronizacja wątków, atomika i jej wpływ na wydajność), której zwykle nie potrzebujesz przy użyciu zwykłych programów do cieniowania.
  3. Zasoby edukacyjne , z doświadczenia wynika, że ​​zasoby obliczeniowe są znacznie mniejsze dla shaderów obliczeniowych, OpenCL i CUDA (które również oferują interoperacyjność OpenGL) niż zwykła trasa shaderów.
  4. Narzędzia do debugowania , przy braku odpowiedniego debugowania, tworzenie narzędzi może stać się znacznie trudniejsze niż większość shaderów, przynajmniej shadery można debugować wizualnie.
  5. Oczekuję, że shadery obliczeniowe będą zapewniać lepszą wydajność niż ten sam algorytm w innych shaderach; jeśli zostały one wykonane prawidłowo, biorąc pod uwagę rzeczy z punktu 2, ponieważ zostały one zaprojektowane tak, aby uniknąć dodatkowych kroków w renderowaniu grafiki. Ale nie mam żadnych konkretnych dowodów na poparcie mojego roszczenia.
  6. Powinieneś również rozważyć CUUDA / OpenCL dla GPGPU, jeśli jedziesz tą drogą.

Niemniej jednak jestem pewien, że będzie to świetne na przyszłość i będzie świetnym doświadczeniem edukacyjnym. Powodzenia!

concept3d
źródło
Myślę, że OP może zadawać następujące pytania: po co rozwiązywać problemy za pomocą czystych shaderów GLSL, a nie kodować je w CUDA? Istnieje artykuł Gem Game Programming Gem dotyczący symulacji tkanin, w którym autor właśnie to robi. A hacky stary sposób GLSL jest lepszy niż CUDA pod względem wydajności. Prawdopodobnie powinieneś wskazać dlaczego, jeśli masz pojęcie, dlaczego.
teodron
2
Nie sądzę, aby twój punkt skalowalności był poprawny - moduły cieniujące wierzchołki i fragmenty są tak samo zdolne do skalowania w całym GPU, jak jednostki cieniujące. W rzeczywistości obliczenia modułów cieniujących mogą być trudniejsze do skalowania, ponieważ rozmiar grupy wątków i użycie pamięci współdzielonej mogą nakładać dodatkowe ograniczenia na liczbę wątków modułu cieniującego w danym momencie.
Nathan Reed,
2
Ponadto, jeśli wypełniasz teksturę (np. Generujesz szum lub robisz jakiś inny algorytm proceduralny), z mojego doświadczenia wynika, że ​​fragmentator fragmentów będzie szybszy niż moduł obliczeniowy, jeśli po prostu oceniasz formułę na każdym pikselu. Domyślam się, że jest tak, ponieważ kolejność fragmentów odpowiada wewnętrznej kolejności pikseli sąsiadująco / swizzled, dzięki czemu uzyskuje się lepszą lokalizację pamięci niż moduł obliczeniowy, który nie jest świadomy tej kolejności. Shadery obliczeniowe są szybsze tylko wtedy, gdy możesz użyć ich specjalnych funkcji, np. Pamięci współużytkowanej, aby znacznie przyspieszyć działanie względem shadera fragmentów.
Nathan Reed,
2
OK, ostatni komentarz. :) Myślę, że większość obecnych procesorów graficznych ma jakiś przełącznik kontekstowy lub tryb, gdy przechodzę z grafiki na obliczenia i odwrotnie. Więc jeśli uruchomisz jakieś shadery graficzne, a następnie wyślesz shader obliczeniowy, a następnie uruchomisz więcej shaderów graficznych itp., Podczas przełączania w przód i w tył poniosą Państwo pewien wzrost wydajności. Musisz to profilować, ale może to być kolejny powód, by trzymać się shaderów graficznych w konkretnym przypadku.
Nathan Reed,
@NathanReed dziękuję za komentarze, zaktualizuję swoją odpowiedź.
concept3d