如何在 OpenCV 中使用 gpu::Stream?

Posted

技术标签:

【中文标题】如何在 OpenCV 中使用 gpu::Stream?【英文标题】:how to use gpu::Stream in OpenCV? 【发布时间】:2013-07-24 19:10:39 【问题描述】:

OpenCV 具有封装异步调用队列的gpu::Stream 类。某些函数具有额外的 gpu::Stream 参数的重载。除了gpu-basics-similarity.cpp sample code,OpenCV 文档中几乎没有关于如何以及何时使用gpu::Stream 的信息。例如,(对我而言)不太清楚gpu::Stream::enqueueConvertgpu::Stream::enqueueCopy 究竟做了什么,或者如何使用gpu::Stream 作为额外的重载参数。我正在寻找gpu::Stream 的类似教程的概述。

【问题讨论】:

【参考方案1】:

默认情况下,所有 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;

【讨论】:

谢谢!因此,在您的示例中, gpu::Stream 用于 GPU 上与 CPU 函数调用异步的函数调用。但是假设我有两个独立的功能(在 GPU 上)。我可以使用两个不同的 gpu::Stream 对象,以便这些函数在单个 GPU 上并行执行(类似于多线程)吗? 什么时候会使用多个流? 是的,您可以使用多个流。但是,正如我所说,如果您从不同的流中调用相同的函数,您可能会遇到问题。 这个有效代码如何? host_src_pl 不会是空的吗? stream.enqueueDownload 将为host_dst_pl 分配内存。

以上是关于如何在 OpenCV 中使用 gpu::Stream?的主要内容,如果未能解决你的问题,请参考以下文章

如何在示例中使用opencv的calibration.cpp(ubuntu opencv 2.4.12)

如何在 OSX 中使用 C++ opencv highgui 将活动窗口设置为 opencv 图像

如何在 OpenCV 中使用 gpu::Stream?

如何在python中使用opencv模块(我正在使用pycharm)[重复]

如何在 ipython 中使用 opencv 克服导入错误

如何在python中使用opencv复制图像区域?