2013-07-24 37 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