![]() |
OpenCV 4.12.0
开源计算机视觉
|
OpenCV CUDA 模块是一组用于利用 CUDA 计算能力的类和函数。 它使用 NVIDIA* CUDA* 运行时 API 实现,并且仅支持 NVIDIA GPU。 OpenCV CUDA 模块包括实用函数、底层视觉原语和高级算法。 实用函数和底层原语为开发利用 CUDA 的快速视觉算法提供了强大的基础设施,而高级功能包括一些最先进的算法(例如立体对应、人脸和行人检测器等),应用程序开发人员可以直接使用。
CUDA 模块设计为宿主机级别 API。 这意味着如果您有预编译的 OpenCV CUDA 二进制文件,则无需安装 CUDA 工具包或编写任何额外的代码即可使用 CUDA。
OpenCV CUDA 模块的设计易于使用,不需要任何 CUDA 知识。 然而,这些知识对于处理非平凡的情况或实现最高性能肯定会有所帮助。 了解各种操作的成本、GPU 的工作方式、首选数据格式等等非常有帮助。 CUDA 模块是快速实现 CUDA 加速的计算机视觉算法的有效工具。 但是,如果您的算法涉及许多简单的操作,那么为了获得最佳性能,您可能仍然需要编写自己的内核,以避免对中间结果进行额外的写入和读取操作。
要启用 CUDA 支持,请使用 WITH_CUDA=ON 在 CMake 中配置 OpenCV。 设置该标志并且安装了 CUDA 后,将构建功能齐全的 OpenCV CUDA 模块。 否则,该模块仍然会被构建,但在运行时,该模块中的所有函数都会抛出带有 CV_GpuNotSupported 错误代码的异常,除了 cuda::getCudaEnabledDeviceCount()。 在这种情况下,后一个函数返回零 GPU 计数。 构建没有 CUDA 支持的 OpenCV 不会执行设备代码编译,因此不需要安装 CUDA 工具包。 因此,使用 cuda::getCudaEnabledDeviceCount() 函数,您可以实现一个高级算法,该算法将在运行时检测 GPU 的存在并相应地选择合适的实现(CPU 或 GPU)。
NVIDIA* 编译器能够生成二进制代码 (cubin 和 fatbin) 和中间代码 (PTX)。 二进制代码通常意味着特定的 GPU 架构和代系,因此与其他 GPU 的兼容性无法保证。 PTX 针对一个完全由一组功能或特性定义的虚拟平台。 根据所选的虚拟平台,即使实际硬件支持所有功能,某些指令也会被模拟或禁用。
在第一次调用时,PTX 代码使用 JIT 编译器编译为特定 GPU 的二进制代码。 当目标 GPU 的计算能力 (CC) 低于 PTX 代码时,JIT 会失败。 默认情况下,OpenCV CUDA 模块包括
这意味着对于 CC 为 1.3 和 2.0 的设备,二进制镜像已准备好运行。 对于所有较新的平台,1.3 的 PTX 代码 JIT'ed 为二进制镜像。 对于 CC 为 1.1 和 1.2 的设备,1.1 的 PTX JIT'ed。 对于 CC 为 1.0 的设备,没有可用的代码,并且这些函数会抛出异常。 对于首先执行 JIT 编译的平台,运行速度较慢。
在 CC 为 1.0 的 GPU 上,您仍然可以编译 CUDA 模块,并且大多数功能都可以完美运行。 为了实现这一点,请将 "1.0" 添加到二进制文件列表中,例如,CUDA_ARCH_BIN="1.0 1.3 2.0" 。 无法在 CC 1.0 GPU 上运行的功能会抛出异常。
您始终可以在运行时确定 OpenCV GPU 构建的二进制文件(或 PTX 代码)是否与您的 GPU 兼容。 函数 cuda::DeviceInfo::isCompatible 返回兼容性状态(true/false)。
在当前版本中,每个 OpenCV CUDA 算法只能使用单个 GPU。 因此,要利用多个 GPU,您必须手动在 GPU 之间分配工作。 可以使用 cuda::setDevice() 函数切换活动设备。 有关更多详细信息,请阅读 Cuda C Programming Guide。
在开发用于多个 GPU 的算法时,请注意数据传递开销。 对于原始函数和小图像,这可能很重要,这可能会消除拥有多个 GPU 的所有优势。 但是对于高级算法,请考虑使用多 GPU 加速。 例如,已使用以下算法成功地并行化了立体块匹配算法
使用此算法,与单个 Fermi GPU 相比,双 GPU 的性能提高了 180%。 有关源代码示例,请参见 https://github.com/opencv/opencv/tree/4.x/samples/gpu/。