Подтвердить что ты не робот

Параллельные вычисления с использованием OpenCV

У меня есть приложение, которое требует обработки нескольких изображений параллельно, чтобы поддерживать скорость в реальном времени.

Насколько я понимаю, я не могу назвать функции GPU OpenCV многопоточным способом на одном устройстве CUDA. Я пробовал конструкцию кода OpenMP, такую ​​как:

#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]);
        }
    }
}

Кажется, что он компилируется и выполняется правильно, но, к сожалению, он, как представляется, последовательно выполняет numImages потоки на одном и том же устройстве CUDA.

Я должен иметь возможность выполнять несколько потоков параллельно, если у меня есть несколько устройств CUDA, правильно? Чтобы получить несколько устройств CUDA, нужны ли мне несколько видеокарт?

Кто-нибудь знает, работает ли двухчиповая карта nVidia GTX 690 как два независимых устройства CUDA с OpenCV 2.4 или новее? Я нашел подтверждение, что он может работать как таковой с OpenCL, но без подтверждения относительно OpenCV.

4b9b3361

Ответ 1

Просто выполните многократные передачи целых изображений в функцию cv::gpu::multiply().

OpenCV и CUDA будут обрабатывать разделение и делить задачу наилучшим образом. Обычно каждый компьютерный блок (то есть ядро) в графическом процессоре может запускать несколько потоков (обычно >= 16 в CUDA). Это в дополнение к наличию карт, которые могут отображаться в виде нескольких графических процессоров или размещения нескольких связанных карт на одной машине.

Весь смысл cv::gpu заключается в том, чтобы избавить вас от необходимости знать что-либо о том, как работают внутренние элементы.

Ответ 2

Ответ от Мартина работал у меня. Ключ состоит в том, чтобы использовать класс gpu:: Stream, если ваше устройство CUDA указано как вычислительная способность 2 или выше. Я верну его здесь, потому что я не смог правильно разместить код в мини-редакторе комментариев.

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]);
        }
    }
}

Вышеприведенный код, похоже, выполняет параллельное копирование (numImages = 3 для моего приложения). Существуют также методы Stream, которые помогают загружать/загружать изображения в память GPU и из нее, а также методы проверки состояния потока, чтобы помочь в синхронизации с другим кодом.

Итак, для параллельного выполнения кода OpenCV GPU, по-видимому, не требуется несколько устройств CUDA (например, графических карт)!

Ответ 3

Я ничего не знаю о функциях GPU OpenCV, но если они полностью автономны (т.е. создают контекст графического процессора, передают данные на GPU, вычисляют результаты, возвращают результаты обратно в CPU), то неудивительно, что эти функции появляются при использовании одного графического процессора.

Если у вас несколько графических процессоров, то должен быть способ сообщить функции OpenCV для таргетинга на определенный графический процессор. Если у вас несколько графических процессоров и можно эффективно их настроить, я тогда не вижу причин, по которым вызовы функций GPU не будут распараллеливаться. Согласно вики OpenCV, функции GPU нацелены только на один GPU, но вы можете вручную разделить работу самостоятельно: http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ#Can_I_use_two_or_more_GPUs.3F

Двойные графические процессоры, такие как GTX 690, будут отображаться как два разных устройства с собственной памятью в отношении вашей программы GPU. См. Здесь: http://forums.nvidia.com/index.php?showtopic=231726

Кроме того, если вы собираетесь использовать маршрут с двумя GPU для вычислительных приложений, я бы рекомендовал против GTX 690, потому что его вычислительная производительность несколько искалечена по сравнению с GTX 590.

Ответ 4

GTX 290 ведет себя как два отдельных устройства CUDA, независимо от того, какую версию OpenCV вы используете. Вам не нужно несколько графических карт для получения нескольких графических процессоров, которые у вас есть на одной карте, например, в GTX 290. Но с точки зрения программирования CUDA нет большой разницы между использованием двух графических процессоров на 290 и использованием 2 графических процессора на отдельно подключенных графических картах. Многие пользователи OpenCV используют библиотеку ArrayFire CUDA, дополняющую дополнительные функции обработки изображений и простое масштабирование с несколькими GPU. Конечно, мой отказ от ответственности заключается в том, что я работаю над ArrayFire, но я действительно думаю, что это поможет вам в этом случае.