OpenCV 4.11.0
开源计算机视觉库
|
OpenCV CUDA 模块是一组用于利用 CUDA 计算能力的类和函数。它使用 NVIDIA* CUDA* 运行时 API 实现,仅支持 NVIDIA GPU。OpenCV CUDA 模块包括实用程序函数、低级视觉基元和高级算法。实用程序函数和低级基元为开发利用 CUDA 的快速视觉算法提供了强大的基础架构,而高级功能则包括一些最先进的算法(例如立体匹配、人脸和行人检测器等),可供应用程序开发人员直接使用。
CUDA 模块设计为主机级 API。这意味着如果您有预编译的 OpenCV CUDA 二进制文件,则不需要安装 CUDA 工具包或编写任何额外代码即可使用 CUDA。
OpenCV CUDA 模块设计易于使用,不需要任何 CUDA 知识。但是,掌握 CUDA 知识无疑有助于处理非平凡的情况或获得最高的性能。了解各种操作的成本、GPU 的工作方式、首选的数据格式等非常有帮助。CUDA 模块是快速实现 CUDA 加速计算机视觉算法的有效工具。但是,如果您的算法涉及许多简单的操作,为了获得最佳性能,您可能仍然需要编写自己的内核以避免对中间结果进行额外的写入和读取操作。
要启用 CUDA 支持,请使用 CMake 配置 OpenCV,并设置 WITH_CUDA=ON 。当设置此标志且已安装 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 模块包括:
这意味着对于计算能力为 1.3 和 2.0 的设备,二进制映像可以直接运行。对于所有较新的平台,将 1.3 的 PTX 代码 JIT 编译为二进制映像。对于计算能力为 1.1 和 1.2 的设备,将 1.1 的 PTX 代码 JIT 编译。对于计算能力为 1.0 的设备,没有可用的代码,函数会抛出异常。对于首先执行 JIT 编译的平台,运行速度较慢。
在计算能力为 1.0 的 GPU 上,您仍然可以编译 CUDA 模块,并且大多数函数都可以完美运行。为此,请将“1.0”添加到二进制文件列表中,例如 CUDA_ARCH_BIN="1.0 1.3 2.0" 。不能在计算能力为 1.0 的 GPU 上运行的函数会抛出异常。
您可以始终在运行时确定 OpenCV GPU 构建的二进制文件(或 PTX 代码)是否与您的 GPU 兼容。函数 cuda::DeviceInfo::isCompatible 返回兼容性状态(true/false)。
在当前版本中,每个 OpenCV CUDA 算法只能使用单个 GPU。因此,要利用多个 GPU,您必须手动将工作分配到各个 GPU 之间。可以使用 cuda::setDevice() 函数切换活动设备。更多详细信息,请阅读 Cuda C 编程指南。
在为多个 GPU 开发算法时,请注意数据传递开销。对于基本函数和小图像,这可能是很大的开销,这可能会消除使用多个 GPU 的所有优势。但对于高级算法,请考虑使用多 GPU 加速。例如,立体块匹配算法已使用以下算法成功并行化:
使用此算法,与单个 Fermi GPU 相比,双 GPU 的性能提高了 180%。有关源代码示例,请参见 https://github.com/opencv/opencv/tree/4.x/samples/gpu/。