这是一个普遍的问题,虽然我使用 OpenCV 作为框架,但这个问题比 OpenCV 的领域更广泛。
我正在开发一个图像处理工具,它将有效地从网络摄像头获取图像(产生位于主机内存cv::Mat),将其上传到 CUDA 中的 GPU 设备内存(即cv::GpuMat),使用 CUDA 进行一些处理并获得结果finalCudaMat,最后发送结果传送至 OpenGL(即cv::ogl::Buffer::mapDevice+ finalCudaMat.copyTo(mappedOglBuffer))。一切都按预期进行。
由于整个过程涉及多个步骤,因此我使用 CUDA 流对象 ( cv::cuda::Stream) 来使 CUDA 调用异步,而不是等待 CPU 端完成每个操作。现在,如果有人最终将结果复制到 CPU 矩阵(即finalCudaMat.download(finalCpuMat)),如在通常情况下,通常需要等待流(cudaStream.waitForCompletion())以确保结果在使用 CPU 端矩阵之前准备就绪。
就我而言,结果永远不会返回到 CPU,因为它继续在屏幕上渲染(还涉及一些 OpenGL 操作和着色器)。
一种方法是,在开始将 GpuMat 复制到 OpenGL 缓冲区之前,等待 CUDA 工作完成可能是合适的。因此,如果我添加流等待,一切都会正常工作,CUDA 操作大约需要 2.5 毫秒。
另一种方式,感觉就像我不需要等待流的完成(无论如何,所有结果都被 GPU 消耗——CPU 永远不会再参与)。cudaStream.waitForCompletion()因此,我可以在执行之前删除呼叫finalCudaMat.copyTo(mappedOglBuffer),一切似乎都工作正常。整个 CUDA 处理操作(基本上任何 GPU 任务减去 OpenGL 相关的任务)显然对我来说大约需要 1.8 毫秒。
过去,如果涉及两个不同的 API,我有过无法正确同步 GPU 工作的糟糕经历(例如,在 Direct3D 9 …