2012-06-21 10 views
12

Mam aplikację, która wymaga przetwarzania wielu obrazów równolegle w celu utrzymania prędkości w czasie rzeczywistym.Równoległe przetwarzanie GPU przy użyciu OpenCV

Rozumiem, że nie mogę wywoływać funkcji GPU OpenCV w trybie wielowątkowym na pojedynczym urządzeniu CUDA. Próbowałem się kod konstruktu OpenMP takie jak:

#pragma omp parallel for 
for(int i=0; i<numImages; i++){ 
    for(int j=0; j<numChannels; j++){ 
     for(int k=0; k<pyramidDepth; k++){ 
      cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k]); 
     } 
    } 
} 

To wydaje się skompilować i wykonać poprawnie, ale niestety wydaje się, aby wykonać numImages wątki kolejno na tym samym urządzeniu CUDA.

Powinienem być w stanie wykonywać wiele wątków równolegle, jeśli mam wiele urządzeń CUDA, prawda? Czy w celu uzyskania wielu urządzeń CUDA potrzebuję wielu kart wideo?

Czy ktoś wie, czy karta dual-chipowa nVidia GTX 690 działa jako dwa niezależne urządzenia CUDA z OpenCV 2.4 lub nowszym? Znalazłem potwierdzenie, że może działać jako takie z OpenCL, ale nie ma potwierdzenia w odniesieniu do OpenCV.

+0

Być może odpowiedź jest w kodzie źródłowym dla OpenCV? –

Odpowiedz

5

Po prostu wykonaj wielokrotne przekazywanie całych zdjęć do funkcji cv::gpu::multiply().

OpenCV i CUDA będą obsługiwać dzielenie i dzielenie zadania w najlepszy sposób. Zasadniczo każda jednostka komputerowa (to jest rdzeń) w GPU może uruchamiać wiele wątków (zwykle> = 16 w CUDA). Jest to dodatek do posiadania kart, które mogą występować jako wiele układów GPU lub umieszczać wiele połączonych kart na jednym komputerze.

Cały punkt cv::gpu polega na tym, że nie musisz wiedzieć, jak działają elementy wewnętrzne.

+0

Tak, prawda. Funkcja multiply() jest napisana, aby wykorzystać CUDA w samej funkcji. Potrzebuję jednak więcej niż jednej funkcji multiply() działającej w równoległych wątkach. To nie wydaje się możliwe bez wielu procesorów graficznych. Następnie można wykonać funkcję mnożenia() na każdym równolegle i dla różnych obrazów jednocześnie. – mmccullo

+0

@mmccullo - tak cv :: gpu używa wątku cuda niskiego poziomu, możesz wywoływać go w wątkach wielu użytkowników, ale każdy w pełni wykorzysta gpu, dopóki drugi nie skończy. Jeśli masz kartę z cuda2, użyje ona strumieni, aby to zrobić asynchronicznie, więc twoje wątki nie blokują –

+0

Używam CUDA v4.2. Nie jestem pewien, co dokładnie oznacza twoje odniesienie do "cuda2". Wygląda na to, że nie blokuje ona moich wątków OpenMP, ale czas wykonywania mojego kodu powyżej jest tylko trochę lepszy niż wykonanie w pojedynczym wątku. Wygląda na to, że wykonanie wielu wątków odbywa się szeregowo na pojedynczym urządzeniu CUDA - w przeciwnym razie czas wykonania powinien być znacznie mniejszy niż pojedynczy wątek na tym samym urządzeniu. Mój testowy GPU to Quadro2000M z rdzeniami CUDA 2GB i 192. Obrazy mają rozdzielczość 1280 x 960 RGB. – mmccullo

0

Nie wiem nic o funkcjach GPU OpenCV, ale jeśli są całkowicie autonomiczne (tj. Tworzą kontekst GPU, przesyłają dane do GPU, obliczają wyniki, przesyłają wyniki z powrotem do CPU), to nic dziwnego, funkcje te pojawiają się w postaci szeregowej podczas korzystania z pojedynczego procesora graficznego.

Jeśli masz wiele procesorów graficznych, to powinieneś w jakiś sposób poinformować funkcję OpenCV, aby skierować konkretny procesor GPU. Jeśli masz wiele procesorów graficznych i możesz skutecznie nimi kierować, nie widzę powodu, dla którego wywołania funkcji GPU nie byłyby zrównoleglone. Według Wiki OpenCV, funkcje GPU są kierowane tylko na jeden GPU, ale możesz samodzielnie podzielić pracę: http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ#Can_I_use_two_or_more_GPUs.3F

Dwa GPU, takie jak GTX 690, będą widoczne jako dwa różne urządzenia z własną pamięcią, jeśli chodzi o twój GPU program jest zaniepokojony. Zobacz tutaj: http://forums.nvidia.com/index.php?showtopic=231726

Ponadto, jeśli masz zamiar podwójną trasę GPU do zastosowań obliczeniowych, polecam przeciwko GTX 690, ponieważ jej wydajność obliczeniowa jest nieco okaleczony porównaniu do GTX 590.

+0

Interesująca uwaga na temat wydajności 690 vs. 590. Ta strona [nVidia] (http://developer.nvidia.com/cuda-gpus) wskazuje na wyższą wydajność komputera dla 690. Czy masz jakieś informacje na temat tego, jak 690 jest kaleką? – mmccullo

+0

"Zgodnie z wiki OpenCV, funkcje GPU są ukierunkowane tylko na pojedynczy procesor graficzny, ale można ręcznie podzielić pracę", ale link nie jest już aktywny. Co to znaczy ręcznie podzielić? Musisz ustawić identyfikator urządzenia przed każdym wywołaniem gpu opencv? Czy istnieje jakiś oficjalny przykład popierający oświadczenie? – alap

+0

Czy oznacza to również, że w trybie SLI/CrossFire należy wykonać ręczny przełącznik? – alap

0

GTX 290 zachowuje jako 2 oddzielne urządzenia CUDA, niezależnie od używanej wersji OpenCV. Nie potrzebujesz wielu kart GPU, aby uzyskać wiele GPU, które masz 2 na jednej karcie, tak jak w GTX 290. Ale z perspektywy programowania CUDA nie ma dużej różnicy między używaniem dwóch procesorów graficznych na 290 i używaniem 2 procesory graficzne na osobno podłączonych kartach GPU. Wielu użytkowników OpenCV korzysta z biblioteki CUDA ArrayFire w celu uzupełnienia dodatkowych funkcji przetwarzania obrazu i łatwego skalowania wielu GPU. Oczywiście, moje zastrzeżenie jest takie, że pracuję nad ArrayFire, ale naprawdę myślę, że to ci pomoże w tym przypadku.

4

Odpowiedź od Martina zadziałała dla mnie. Kluczem jest użycie klasy gpu :: Stream, jeśli twoje urządzenie CUDA jest wymienione jako zdolność obliczeniowa 2 lub wyższa. Powtórzę to tutaj, ponieważ nie mogę poprawnie umieścić kodu w edytorze mini komentarzy.

cv::gpu::Stream stream[3]; 

for(int i=0; i<numImages; i++){ 
    for(int j=0; j<numChannels; j++){ 
     for(int k=0; k<pyramidDepth; k++){ 
      cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k], stream[i]); 
     } 
    } 
} 

Powyższy kod wydaje się wykonywać mnożenie równolegle (numImages = 3 dla mojej aplikacji). Istnieją również metody Stream, które ułatwiają przesyłanie/pobieranie obrazów do iz pamięci GPU, a także metody sprawdzania stanu strumienia w celu ułatwienia synchronizacji z innym kodem.

Więc ... najwyraźniej nie wymaga wielu urządzeń CUDA (tj. Kart GPU) w celu równoległego wykonywania kodu GPU OpenCV!