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

Ale*_*xey 4 c++ opencv gpgpu

OpenCV具有gpu::Stream封装异步调用队列的类.某些函数具有附加gpu::Stream参数的重载.除了gpu-basics-similarity.cpp示例代码之外,OpenCV文档中关于如何以及何时使用的信息非常少gpu::Stream.例如,(对我而言)不清楚究竟是什么gpu::Stream::enqueueConvertgpu::Stream::enqueueCopy做什么,或者如何使用它gpu::Stream作为额外的过载参数.我正在寻找一些类似教程的概述gpu::Stream.

jet*_*t47 10

默认情况下,所有gpu模块函数都是同步的,即当前CPU线程被阻塞直到操作完成.

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;
Run Code Online (Sandbox Code Playgroud)