2011-12-25 24 views
9

Grafika jest jednym z tych "żenująco równoległych" problemów. Haskell ma być naprawdę, bardzo dobry do przetwarzania równoległego. Więc moje pytanie brzmi:Równoległe przetwarzanie grafiki w Haskell

  1. Jaki jest najlepszy sposób na wyrzucenie jak największej liczby rdzeni procesora przy problemie z renderowaniem?

  2. Czy można zamiast tego wykonać procesor GPU?

Przez „renderowania problemu”, mam na myśli problemy, takie jak:

  • kolor każdego piksela jest czysta funkcja jego współrzędnych.

  • Zaczynamy od istniejącego "obrazu wejściowego", a każdy kolor "wyjściowego" piksela jest czystą funkcją odpowiedniego piksela wejściowego, lub może małej okolicy takich pikseli.


Odnośnie # 1: To wygląda na to trywialne, ale w rzeczywistości tak nie jest. Istnieje kilka możliwych opcji struktury danych, w których przechowywane są obliczone piksele (co wpływa na sposób, w jaki można uzyskać do niego dostęp i jak łatwo można zrzucić wynik na dysk lub ekran). Istnieje kilka sposobów wykonania na wielu rdzeniach. I tak dalej.

Wydaje mi się, że Data Parallel Haskell byłby idealnym wyborem dla tego typu rzeczy. Jednak ostatnio sprawdziłem, DPH jeszcze nie działa. To wszystko. Nawet zakładając, że to działało, prawdopodobnie tworzysz równoległą tablicę do przechowywania pikseli, a potem będziesz musiał/musiała kopiować piksele, aby wyświetlić je na ekranie lub zapisać na dysku.

Chciałbym spróbować iskrzyć każdy pojedynczy piksel, ale to chyba zbyt drobnoziarniste. Mogłem uczynić piksele listą i użyć jednej z równoległych strategii list. Czy mógłbym uczynić z niego niezamkniętą tablicę (unboxed?) I napisać jakiś ręczny kod, by rozpocząć iskry. Mogę też iść z jawnymi wątkami i zmiennymi tablicami. Mogę też mieć kilka wątków roboczych, które przesyłają wartości pikseli przez kanał do głównego wątku, który umieszcza wyniki we właściwym miejscu. Lub ...

Podsumowując, istnieje tu zaskakująca liczba możliwości i nie jestem pewien, który jest najlepszy.


Odnośnie # 2: Oczywiście tego typu problemu jest cała przyczyna że istnieją GPU w pierwszej kolejności. Oczywiście GPU idealnie nadaje się do atakowania tego rodzaju problemów. Moje pytanie brzmi bardziej "czy trudno jest to zrobić z Haskell?"

+1

Nie sądzę, że może on jeszcze kierować procesory graficzne, ale celem usługi Data Parallel Haskell jest umożliwienie wykonywania tego typu zadań. –

Odpowiedz

7

Jeśli można mieszać języki, to OpenCL jest bardzo wszechstronny. Chociaż język OpenCL jest bardzo bliski bycia C (więc zdecydowanie , nie Haskell), możesz napisać swój kod jądra w bardziej lub mniej funkcjonalnym stylu i myśleć o tym, jak odwzorowywać jądro na współrzędne przestrzenne. Zaletą robienia rzeczy w ramach głównego nurtu programowania równoległego, takiego jak OpenCL, jest to, że możesz oprzeć się na rosnącej ilości wiedzy, zarówno HPC, jak i grafików zgromadzonych przez lata w wielu domenach aplikacji. Retargeting pomiędzy procesorem a GPU jest w większości bezbolesny, ale musisz pamiętać o typach danych (np. Niektóre procesory graficzne nie obsługują podwójnej precyzji).

Napisałem a tutorial on calling into OpenCL from Haskell. Opiera się na stosunkowo nowych powiązaniach OpenCL (w hakowaniu istnieje kilka wiązań OpenCL, nie mogę zaświadczyć o ich względnej jakości).

+0

Sądzę, że naprawdę zadawałem tu dwa pytania: jak efektywnie korzystać z procesora i jak efektywnie korzystać z GPU. Połączony wpis na blogu przydaje się do wyjaśnienia, jak używać GPU z OpenCL lub OpenGL. Akceptuję to jako odpowiedź na całe pytanie. – MathematicalOrchid

5

Istnieje raw OpenCL bindings, ale jeśli chcesz coś, co pomaga uruchomić wysokim poziomie kodu - fałdy i zamki oraz mapy i tak dalej - na GPU dziś przyjrzeć accelerate (CUDA backend) i GPipe (OpenGL backend , do prac graficznych, nieco bitrotten w dzisiejszych czasach, niestety).

Jeśli chodzi o struktury reprezentujące renderowany obraz, to niezapisana tablica jest prawdopodobnie najlepszym rozwiązaniem: jest najbardziej dopasowana do sprzętu i generalnie nie wykonuje czystych "przyrostowych" aktualizacji renderowania.

2

Krótka odpowiedź na pytanie 1, w przypadku braku bardziej szczegółowo, to:

  1. Wpisz swój kod jako normalne, przy użyciu biblioteki wektor lub macierz przetwarzanie.

  2. Jeśli biblioteka nie robi tego za Ciebie, wstaw odpowiednie połączenia "par" lub kombinatory w oparciu o to, aby wyliczyć farmy na wiele procesorów.

+2

Spójrz na użycie Repa do swoich wektorów - łatwo jest uzyskać operacje Repa, aby użyć N procesorów. –