2012-02-16 13 views
6

Używanie różnych strumieni dla jądra CUDA umożliwia równoczesne wykonywanie jądra. Zatem strumienie n na strumieniach n mogłyby teoretycznie działać jednocześnie, jeśli pasują do sprzętu, prawda?Równoczesne wykonywanie jądra CUDA z wieloma jądrami na strumień

Teraz mam do czynienia z następującym problemem: Nie ma n odrębnych jąder, ale n*m gdzie jądra m muszą być wykonane w kolejności. Na przykład n=2 i m=3 doprowadzi do następującego schematu wykonania strumieni:

Stream 1: <<<Kernel 0.1>>> <<<Kernel 1.1>>> <<<Kernel 2.1>>> 
Stream 2: <<<Kernel 0.2>>> <<<Kernel 1.2>>> <<<Kernel 2.2>>> 

My to naiwny założenie, że ziarna i x.0 Y.1 powinien wykonywać jednocześnie (z teoretycznego punktu widzenia) lub co najmniej nie kolejno (z praktycznego punktu widzenia). Ale moje pomiary pokazują mi, że tak nie jest i wydaje się, że wykonywane jest kolejne wykonanie (tj. K0.0, K1.0, K2.0, K0.1, K1.1, K2.1). Samo jądro jest bardzo małe, więc jednoczesne wykonywanie nie powinno stanowić problemu.

Teraz moim podejściem byłoby dokonanie pewnego rodzaju wysyłki, aby upewnić się, że jądra są umieszczane w układzie przeplatanym w harmonogramie na GPU. Ale gdy mamy do czynienia z dużą liczbą strumieni/ziaren, może to przynieść więcej szkody niż pożytku.

W porządku, przechodząc od razu do punktu: Jakie byłoby odpowiednie (lub przynajmniej odmienne) podejście do rozwiązania tej sytuacji?

Edytuj: Pomiary są wykonywane przy użyciu zdarzeń CUDA. Zmierzyłem czas potrzebny do pełnego rozwiązania obliczeń, mi. GPU musi obliczyć wszystkie jądra n * m. Założeniem jest: W przypadku równoczesnego uruchamiania jądra czas wykonania jest z grubsza (idealnie) czas potrzebny do wykonania wszystkich ziaren w kolejności, przy czym musi istnieć możliwość jednoczesnego wykonywania dwóch lub większej liczby ziaren. Zapewniam to, używając teraz tylko dwóch różnych strumieni.

Mogę zmierzyć wyraźną różnicę w zakresie czasów wykonania między wykorzystaniem strumieni zgodnie z opisem i wysyłaniem przeplatanych jąder, i. E .:

Loop: i = 0 to m 
    EnqueueKernel(Kernel i.1, Stream 1) 
    EnqueueKernel(Kernel i.2, Stream 2) 

porównaniu

Loop: i = 1 to n 
    Loop: j = 0 to m 
     EnqueueKernel(Kernel j.i, Stream i) 

ostatnie prowadzi do dłuższych okresów pracy.

Edytuj nr 2: Zmieniono numery Strumienia na początek o 1 (zamiast 0, patrz komentarze poniżej).

Edit # 3: Sprzęt jest NVIDIA Tesla M2090 (tj Fermi, obliczyć zdolność 2.0)

+0

Prawdopodobnie potrzebujesz pewnych operacji podstawowych synchronizacji strumienia, aby wymusić żądaną kolejność wykonywania. Ale czy mógłbyś nieco poszerzyć swoje pomiary w pytaniu i czy możesz również potwierdzić, że kiedy piszesz "Strumień 0", nie oznacza to dosłownie strumienia 0 CUDA? – talonmies

+0

Wyjaśniłem pomiar (przynajmniej mam taką nadzieję). W przypadku strumieni mam na myśli instancje 'cudaStream_t' opisane w [CUDA C Programming Guide] (http://developer.download.nvidia.com/compute/DevZone/docs/html/C/doc/CUDA_C_Programming_Guide.pdf), sekcja 3.2.5 (Asynchronous Concurrent Execution). –

+2

Być może źle zrozumiałeś to, o co prosiłem - mam na myśli jeden z twoich strumieni CUDA 0, ponieważ strumień 0 (strumień domyślny) jest synchroniczny. – talonmies

Odpowiedz

5

Na Fermi (aka Compute Capability 2.0) sprzętu to najlepiej przeplatać jądro uruchamia się wielu strumieni zamiast uruchamiać wszystkie jądra do jednego strumienia, następnie do następnego strumienia itp. Dzieje się tak, ponieważ sprzęt może natychmiastowo uruchomić jądra do różnych strumieni, jeśli istnieją wystarczające zasoby, a jeśli kolejne uruchomienia są do tego samego strumienia, często wprowadzane jest opóźnienie, zmniejszając współbieżność. To jest powód, dla którego twoje pierwsze podejście działa lepiej, i to podejście należy wybrać.

Włączenie profilowania może również wyłączyć współbieżność na Fermi, więc należy zachować ostrożność.Uważaj również na użycie zdarzeń CUDA podczas pętli uruchamiania, ponieważ mogą one przeszkadzać - najlepiej, aby czas na całą pętlę za pomocą zdarzeń, jak na przykład robisz.

+0

Czy możesz podać mi źródło, skąd pochodzi ta wiedza (w pierwszym akapicie, a nie w drugim)? –

+0

Jest informacja w Rozdziale 3 Przewodnika programowania CUDA 4.1. Jednak po przeczytaniu go widzę, że nie mówi to wyraźnie "przeplata jądro uruchamia". Dostałem informacje od moich kolegów z zespołu oprogramowania NVIDIA CUDA. – harrism

+0

Dzięki za aktualizację. Zamierzam ponownie przejrzeć mój kod i dostarczyć więcej informacji/aktualizacji, jeśli to możliwe. –

Powiązane problemy