2013-07-24 79 views
3

OpenCV有gpu::Stream類,它封裝了一個異步調用隊列。某些功能會因額外的gpu::Stream參數而發生過載。除了gpu-basics-similarity.cpp sample code之外,OpenCV文檔中關於如何以及何時使用gpu::Stream的信息非常少。例如,對於我而言,gpu::Stream::enqueueConvertgpu::Stream::enqueueCopy究竟做了什麼或者如何使用gpu::Stream作爲附加的過載參數並不是很清楚。我正在尋找gpu::Stream的類似教程的概述。如何在OpenCV中使用gpu :: Stream?

回答

8

默認情況下,所有gpu模塊函數都是同步的,即當前CPU線程被阻塞直到操作完成。

gpu::StreamcudaStream_t的包裝,允許使用異步非阻塞調用。您還可以閱讀「CUDA C編程指南」以獲取有關CUDA異步併發執行的詳細信息。

大多數gpu模塊功能還有其他gpu::Stream參數。如果您傳遞非默認流,則函數調用將是異步的,並且該調用將被添加到流命令隊列中。

另外gpu::Stream還提供了用於CPU<->GPUGPU<->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上與CPU函數調用不同步的函數調用。但是,假設我有兩個獨立的功能(在GPU上)。我可以使用兩個不同的gpu :: Stream對象,以便這些函數可以在單個GPU上並行執行(類似於多線程)? – Alexey

+0

什麼時候會使用多個流? – Alexey

+0

是的,你可以使用多個流。但是,如我所說,如果您從不同的流中調用相同的功能,則可能會遇到問題。 – jet47