Spr*_*son 5 opengl opencv cuda gpu direct3d
这是一个普遍的问题,虽然我使用 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 上执行某些操作,不要等待它完成,然后将生成的纹理复制到 Direct3D 10 纹理,并且清楚地在某些帧上,图像会变空或撕裂)。
此时,差异很小,不会影响我的 60 FPS 吞吐量。但我想知道我在技术上是否通过删除等待流操作来完成正确的工作。对此有什么想法吗?或者也许有关 OpenGL/CUDA 互操作的文档可以帮助我?
本文档中定义了规则:https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#graphics-interoperability
特别是它说
在映射时通过 OpenGL、Direct3D 或其他 CUDA 上下文访问资源会产生未定义的结果。
这是一个非常强烈的暗示,表明所需的同步是由 执行的,其文档cudaGraphicsUnmapResources也证实了这一点:
此函数提供同步保证,确保
stream之前发出的任何 CUDA 工作cudaGraphicsUnmapResources()将在任何后续发出的图形工作开始之前完成。
因此,您不需要让 CPU 等待 CUDA 完成,但您必须调用cudaGraphicsUnmapResources它将适当的屏障放入异步指令流中。请注意,与 CPU 传输代码不同,此调用在CUDA 将数据复制到 OpenGL 缓冲区之后进行。
| 归档时间: |
|
| 查看次数: |
588 次 |
| 最近记录: |