2013-07-24 2 views
3

OpenCV имеет класс gpu::Stream, который инкапсулирует очередь асинхронных вызовов. Некоторые функции имеют перегрузки с дополнительным параметром gpu::Stream. Помимо gpu-basics-similarity.cpp sample code, в документации OpenCV очень мало информации о том, как и когда использовать gpu::Stream. Например, не совсем понятно (мне), что именно gpu::Stream::enqueueConvert или gpu::Stream::enqueueCopy, или как использовать gpu::Stream в качестве дополнительного параметра перегрузки. Я ищу некоторый обзор, подобный учебнику, gpu::Stream.Как использовать gpu :: Stream в OpenCV?

ответ

8

По умолчанию все функции модуля gpu являются синхронными, то есть текущий поток процессора блокируется до завершения операции.

gpu::Stream является оберткой для cudaStream_t и позволяет использовать асинхронный неблокирующий вызов. Вы также можете прочитать «Руководство по программированию CUDA C» для получения подробной информации о асинхронном одновременном выполнении CUDA.

Большинство функций модуля gpu имеют дополнительный параметр gpu::Stream. Если вы передаете поток не по умолчанию, вызов функции будет асинхронным, и вызов будет добавлен в очередь команд потока.

Также gpu::Stream предоставляет методы для передачи асинхронной памяти между CPU<->GPU и GPU<->GPU. Но CPU<->GPU Передача асинхронной памяти работает только с памятью с блокировкой страниц. Существует еще один класс gpu::CudaMem, который инкапсулирует такую ​​память.

В настоящее время вы можете столкнуться с проблемами, если одна и та же операция дважды отображается в разных данных в разные потоки. В некоторых функциях используется постоянная или текстурная память GPU, и следующий вызов может обновить память до того, как предыдущий будет завершен. Но вызов различных операций асинхронно безопасен, поскольку каждая операция имеет свой собственный постоянный буфер. Операции копирования/выгрузки/загрузки/установки операций с буферами, которые вы держите, также безопасны.

Вот небольшой пример:

// allocate page-locked memory 
CudaMem host_src_pl(768, 1024, CV_8UC1, CudaMem::ALLOC_PAGE_LOCKED); 
CudaMem host_dst_pl; 

// get Mat header for CudaMem (no data copy) 
Mat host_src = host_src_pl; 

// fill mat on CPU 
someCPUFunc(host_src); 

GpuMat gpu_src, gpu_dst; 

// create Stream object 
Stream stream; 

// next calls are non-blocking 

// first upload data from host 
stream.enqueueUpload(host_src_pl, gpu_src); 
// perform blur 
blur(gpu_src, gpu_dst, Size(5,5), Point(-1,-1), stream); 
// download result back to host 
stream.enqueueDownload(gpu_dst, host_dst_pl); 

// call another CPU function in parallel with GPU 
anotherCPUFunc(); 

// wait GPU for finish 
stream.waitForCompletion(); 

// now you can use GPU results 
Mat host_dst = host_dst_pl; 
+0

Спасибо! Таким образом, в вашем примере gpu :: Stream используется для вызовов функций на GPU, которые асинхронны от вызовов функций ЦП. Но предположим, что у меня есть две независимые функции (на GPU). Можно ли использовать два разных объекта gpu :: Stream, чтобы эти функции выполнялись параллельно на одном графическом процессоре (подобно многопоточному)? – Alexey

+0

Когда будет использоваться несколько потоков? – Alexey

+0

Да, вы можете использовать несколько потоков. Но, как я уже сказал, вы можете столкнуться с проблемами, если вы вызываете одни и те же функции из разных потоков. – jet47

Смежные вопросы