NVIDIA Optical Flow SDK 5.0

NVOFA 编程指南

从 Turing 架构开始的 NVIDIA GPU 包含一个基于硬件的光流加速器(以下简称 NVOFA)。NVOFA 硬件接受一对 YUV/RGB 帧作为输入,并生成两帧之间的流向量图。可以使用 NVIDIA Optical Flow API(以下简称 NVOF API)访问 NVOFA 引擎的功能,这些 API 通过 NVIDIA Optical Flow SDK 公开。

本文档提供有关如何使用 SDK 中公开的 NVOF API 对 NVOFA 进行编程的信息。NVOF API 在 Windows(Windows 7 及以上版本)和 Linux 上受支持。

预计开发人员应熟悉 Windows 和/或 Linux 开发环境。

NVOF API 保证向后兼容性(并在向后兼容性被破坏时明确提及)。这意味着使用旧版本已发布 API 编译的应用程序将继续在 NVIDIA 发布的未来驱动程序版本上工作。

NVIDIA OFAPI 旨在接受原始视频帧(8 位 YUV 或 RGB 格式)并输出流向量。

广义上讲,编程流程包括以下步骤

  1. 创建光流上下文
  2. 初始化 NVOF API 接口
  3. 分配输入/输出缓冲区
  4. 设置所需的参数
  5. 启动 NVOFA 引擎
  6. 清理 - 释放所有已分配的输入/输出缓冲区
  7. 关闭会话

这些步骤将在本文档的其余部分中进行解释,并在 Optical Flow SDK 包中包含的示例应用程序中进行演示。

打开会话

开发人员可以创建一个客户端应用程序,该应用程序调用 nvOFAPI.dll(Windows)或 libnvidia-opticalflow.so(Linux)公开的 NVOF API。这些库作为 NVIDIA 显示驱动程序的一部分安装。客户端应用程序可以在运行时使用 Windows 上的 GetProcAddress() 和 Linux 上的 dlsym() 链接到这些库。

NVIDIA OFAPI 支持使用以下类型的接口

  • DirectX 11 - DirectX 11 在 Windows 8 及以上版本上受支持。
  • DirectX 12 - DirectX 12 在 Windows 10 20H1 及以上版本上受支持。
  • CUDA – CUDA 接口在 Linux 和 Windows(Windows 7 及以上版本)上受支持。
  • Vulkan – Vulkan 接口在 Linux 和 Windows(Windows 10 及以上版本)上受支持。

初始化

根据使用的接口,初始化步骤有所不同。

DirectX 11 接口

请按照以下步骤初始化光流的 DirectX 11 接口。

  1. 加载光流模块 nvofapi.dll/nvofapi64.dll
  2. 创建 ID3D11Device 和 ID3D11DeviceContext 的实例。
  3. 从加载的光流模块中检索导出的函数 NvOFAPICreateInstanceD3D11 的地址。
  4. 填充 API 函数指针列表。
    • 调用 NvOFAPICreateInstanceD3D11 以填充 NVOF API 函数指针列表。
    • 该 API 接受 NV_OF_API_VERSION 和指向函数指针列表 NV_OF_D3D11_API_FUNCTION_LIST* 的内存块的指针,该内存块接收 NVOF API 地址 NV_OF_D3D11_API_FUNCTION_LIST
    • 函数指针使能够访问光流功能。
  5. 创建光流实例
    • 调用 NvCreateOpticalFlowD3D11 并传递在上一步中创建的 ID3D11DeviceID3D11DeviceContext 的实例。
    • 该 API 返回一个 NvOFHandle,应保留并在整个会话中使用。
  6. 调用 NvOFGetCaps 以查询 NVIDIA 显示驱动程序和 GPU 支持的功能。
  7. 在填写 NV_OF_INIT_PARAMS 后调用 NvOFInit

DirectX 12 接口

请按照以下步骤初始化光流的 DirectX 12 接口。

  1. 加载光流模块 nvofapi.dll/nvofapi64.dll
  2. 创建 ID3D12Device 的实例。
  3. 从加载的光流模块中检索导出的函数 NvOFAPICreateInstanceD3D12 的地址。
  4. 填充 API 函数指针列表。
    • 调用 NvOFAPICreateInstanceD3D12 以填充 API 函数指针列表。
    • 该 API 接受 NV_OF_API_VERSION 和指向函数指针列表 NV_OF_D3D12_API_FUNCTION_LIST* 的内存块的指针,该内存块接收 API 地址 NV_OF_D3D12_API_FUNCTION_LIST
    • 函数指针使能够访问光流功能。
  5. 创建光流实例
    • 调用 NvCreateOpticalFlowD3D12 并传递在上一步中创建的 ID3D12Device 的实例。
    • 该 API 返回一个 NvOFHandle,应保留并在整个会话中使用。
  6. 调用 NvOFGetCaps 以查询 NVIDIA 显示驱动程序和 GPU 支持的功能。
  7. 在填写 NV_OF_INIT_PARAMS 后调用 NvOFInit

Cuda 接口

请按照以下步骤初始化 CUDA 接口。

  1. 创建 CUDA 上下文。
  2. 加载光流模块 libnvidia-opticalflow.so。
  3. 从加载的光流模块中检索导出的函数 NvOFAPICreateInstanceCuda 的地址。
  4. 填充 API 函数指针列表。
    • 调用 NvOFAPICreateInstanceCuda 以填充 API 函数指针列表。
    • 该 API 接受 NV_OF_API_VERSION 和指向函数指针列表 NV_OF_CUDA_API_FUNCTION_LIST* 的内存块的指针,该内存块接收 API 地址 NV_OF_CUDA_API_FUNCTION_LIST
    • 函数指针使能够访问光流功能。
  5. 使用在较早步骤中创建的 CUDA 上下文调用 NvCreateOpticalFlowCuda
    • 客户端必须将 NV_OF_API_VERSION 作为 NvCreateOpticalFlowCuda 的第一个参数传递。
    • 该 API 返回一个 NvOFHandle,应保留并在整个会话中使用。
  6. 建议创建 CUDA 流,并调用 NvOFSetIOCudaStreams 以在各自的流上启用内部预处理和后处理。
  7. 调用 NvOFGetCaps 以查询 NVIDIA 显示驱动程序和 GPU 支持的功能。
  8. 在填写 NV_OF_INIT_PARAMS 后调用 NvOFInit

Vulkan 接口

请按照以下步骤初始化光流的 Vulkan 接口。

  1. 加载光流模块 nvofapi.dll/nvofapi64.dll
  2. 通过创建启用了 VK_KHR_get_physical_device_properties2 扩展的 VkInstance 初始化 Vulkan,并确保 VkApplicationInfo::apiVersion 设置为 VK_API_VERSION_1_3 或更高版本。
  3. 选择支持 VK_KHR_timeline_semaphoreVK_NV_optical_flow 扩展的物理设备。
  4. 查询支持 VK_QUEUE_OPTICAL_FLOW_BIT_NV 的队列族。
  5. 创建逻辑设备,启用
    • VK_KHR_timeline_semaphoreVK_NV_optical_flow 扩展。
    • VkPhysicalDeviceTimelineSemaphoreFeaturesVkPhysicalDeviceSynchronization2FeaturesVkPhysicalDeviceOpticalFlowFeaturesNV 功能。
    • 用于光流族的设备队列以及用于图形、计算和/或其他任务的其他设备队列。
  6. 从加载的光流模块中检索导出的函数 NvOFAPICreateInstanceVk 的地址。
  7. 填充 API 函数指针列表。
    • 调用 NvOFAPICreateInstanceVk 以填充 Vulkan API 函数指针列表。
    • 该 API 接受 NV_OF_API_VERSION 和指向函数指针列表 NV_OF_VK_API_FUNCTION_LIST* 的内存块的指针,该内存块接收 API 地址 NV_OF_VK_API_FUNCTION_LIST
    • 函数指针使能够访问光流功能。
  8. 创建光流实例
    • 调用 nvCreateOpticalFlowVk 并传递在上一步中创建的 VkInstance,VkPhysicalDevice,VkDevice
    • 该 API 返回一个 NvOFHandle,应保留并在整个会话中使用。
  9. 调用 NvOFGetCaps 以查询 NVIDIA 显示驱动程序和 GPU 支持的功能。
  10. 在填写 NV_OF_INIT_PARAMS 后调用 NvOFInit

在查询功能后,填充 NV_OF_INIT_PARAMS: 的以下参数:

  • 图像高度:将评估向量的图像/视频序列的高度。
  • 图像宽度:将评估向量的图像/视频序列的宽度。
  • 启用外部提示的标志:NVOF API 为客户端提供了灵活性,可以输入外部流向量,NVOFA 在执行运动搜索时将使用这些向量作为提示。
  • 输出网格大小:指定 NV_OF_INIT_PARAMS::outGridSize。将为指定的网格大小生成流向量。
  • 提示网格大小:如果客户端正在使用外部提示,则应指定提示网格大小。
  • 预设 – NVOF API 公开了三个预设来权衡质量与性能。
  • 操作模式: NVOFA 可用于生成光流向量(包含 X 和 Y 分量,称为光流模式)或立体向量(仅包含 X 分量,称为立体模式)。
  • 启用输出成本: 设置此标志以生成与流向量相关的置信度。成本值越高,表示流向量越不准确,反之亦然。建议使用 8 位成本(通过分配 NV_OF_BUFFER_FORMAT_UINT8 类型的缓冲区)而不是 32 位成本,因为这样可以节省 CUDA 带宽。
  • 视差范围: 这从 Ampere 及更高版本的 GPU 开始有效,并且适用于 NV_OF_MODE_STEREODISPARITY 模式。它指定了最大立体视差范围值。
  • 启用 ROI: 设置此标志以估计图像内矩形区域的流。在 Ampere 及更高版本的 GPU 上可用
  • 预测方向: 预测的方向。支持向前或前向-后向方向。
  • 启用全局流: 当设置此标志时,启用全局流估计。
  • 输入缓冲区格式: 输入缓冲区的 NV_OF_BUFFER_FORMAT

在会话创建和初始化之后,客户端需要分配生成光流/立体向量所需的缓冲区。

DirectX 11 接口的缓冲区分配

当使用 DirectX 11 接口时,请按照以下步骤分配缓冲区。

  1. 调用 NvOFGetSurfaceFormatCountD3D11
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE 和 NV_OF_MODE。
    • 该函数返回接口支持的 DXGI_FORMAT 的计数。
  2. 分配 DXGI_FORMAT 的数组。数组的大小应至少等于 NvOFGetSurfaceFormatCountD3D11 中返回的 DXGI_FORMAT 的计数。
  3. 调用 NvOFGetSurfaceFormatD3D11
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE、NV_OF_MODE 和指向接收支持的 DXGI_FORMAT 的内存的指针。
  4. 使用支持的所需 DXGI_FORMAT 通过 CreateResource DirectX 11 API 分配 ID3D11Resource
  5. 应通过调用 NvOFRegisterResourceD3D11 向 NVOF API 注册每个已分配的缓冲区。
    • API 通过 NvOFGPUBufferHandle 返回已注册资源的句柄,该句柄将用于访问缓冲区。

DirectX 12 接口的缓冲区分配

当使用 DirectX 12 接口时,请按照以下步骤分配缓冲区。

  1. 调用 NvOFGetSurfaceFormatCountD3D12
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE 和 NV_OF_MODE。
    • 该函数返回接口支持的 DXGI_FORMAT 的计数。
  2. 分配 DXGI_FORMAT 的数组。数组的大小应至少等于 NvOFGetSurfaceFormatCountD3D12 中返回的 DXGI_FORMATs 的计数。
  3. 调用 NvOFGetSurfaceFormatD3D12
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE、NV_OF_MODE 和指向接收支持的 DXGI_FORMAT 的内存的指针。
  4. 使用所需的 DXGI_FORMAT 通过 ID3D12Device::CreateCommittedResource DirectX 12 API 分配 ID3D12Resource
  5. 应通过调用 NvOFRegisterResourceD3D12 向 NVOF API 注册每个已分配的缓冲区。
    • API NvOFRegisterResourceD3D12 接受两个 NV_OF_FENCE_POINT 对象(栅栏点是 ID3D12Fence 指针和一个值的对),NV_OF_REGISTER_RESOURCE_PARAMS_D3D12::inputFencePointNV_OF_REGISTER_RESOURCE_PARAMS_D3D12::outputFencePoint。NVOFA 等待直到 NV_OF_REGISTER_RESOURCE_PARAMS_D3D12::inputFencePoint::fence 达到或超过 NV_OF_REGISTER_RESOURCE_PARAMS_D3D12::inputFencePoint::value,然后再开始处理 resource。在处理 resource 后,NV_OF_REGISTER_RESOURCE_PARAMS_D3D12::outputFencePoint::fence 将使用 NV_OF_REGISTER_RESOURCE_PARAMS_D3D12::outputFencePoint::value 进行更新。
    • API 通过 NvOFGPUBufferHandle 返回已注册资源的句柄,该句柄将用于访问缓冲区。

CUDA 接口的缓冲区分配

当使用 CUDA 接口时,请按照以下步骤分配缓冲区。

  1. 使用要分配的表面的尺寸、缓冲区类型(在 NV_OF_BUFFER_USAGE 中枚举)和可用格式(在 NV_OF_BUFFER_FORMAT 中枚举)填充 NV_OF_BUFFER_DESCRIPTOR
  2. 指定 NV_OF_CUDA_BUFFER_TYPE
  3. 调用 NvOFCreateGPUBufferCuda

API 通过 NvOFGPUBufferHandle 返回分配缓冲区的句柄,该句柄可用于访问缓冲区。

Vulkan 接口的缓冲区分配

当使用 Vulkan 接口时,请按照以下步骤分配缓冲区。

  1. 调用 nvOFGetSurfaceFormatCountVk
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE 和 NV_OF_MODE。
    • 该函数返回接口支持的 VkFormat 的计数。
  2. 分配 VkFormat 的数组。数组的大小应至少等于 nvOFGetSurfaceFormatCountVk 中返回的 VkFormats 的计数。
  3. 调用 nvOFGetSurfaceFormatVk
    • 在进行调用时,客户端应指定 NV_OF_BUFFER_USAGE、NV_OF_MODE 和指向接收支持的 VkFormat 的内存的指针。
  4. 使用所需的 VkFormat 通过 vkCreateImage Vulkan API 分配 VkImage
  5. vkCmdPipelineBarrier Vulkan API 用于图像内存屏障流水线。
  6. 应通过调用 nvOFRegisterResourceVk 向 NVOF API 注册每个已分配的缓冲区。
    • API nvOFRegisterResourceVk 接受 vulkan 图像及其格式。
    • 在处理 VkImage 之后
    • API 通过 NvOFGPUBufferHandle 返回已注册资源的句柄,该句柄将用于访问缓冲区。

DirectX 11 和 CUDA 接口中的过程相同。由于 DirectX 12、Vulkan 中的显式同步,该过程略有不同。

根据客户端要求和支持的功能,客户端可以编程其他字段以生成更多数据。

流向量由 32 位值表示,每个水平和垂直分量均为 16 位值。最低 5 位保持小数值,后跟 10 位整数值,最高有效位为符号位。

DirectX 11 和 CUDA

在 NVOF API 初始化且所有缓冲区都已分配后,客户端需要按照以下步骤生成流向量

  1. NV_OF_EXECUTE_INPUT_PARAMS 中填充以下字段
    • 输入帧的句柄。
    • 参考帧的句柄。
    • 外部运动向量提示缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableExternalHints)。
    • 使过去的临时提示无效的标志。
  2. NV_OF_EXECUTE_OUTPUT_PARAMS 中填充以下字段
    • NVOFA 将在其中转储流向量的输出缓冲区的句柄。
    • 成本缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableOutputCost)。
  3. 调用 NvOFExecute
    • 必须为每对帧/图像调用此 API。
  4. NVOFA 将生成流向量并将其存储在 NV_OF_EXECUTE_OUTPUT_PARAMS::outputBuffer 中。

DirectX 12

在 NVOF API 初始化且所有缓冲区都已分配后,客户端需要按照以下步骤生成流向量

  1. NV_OF_EXECUTE_INPUT_PARAMS_D3D12 中填充以下字段
    • 输入帧的句柄。
    • 参考帧的句柄。
    • 外部运动向量提示缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableExternalHints)。
    • 使过去的临时提示无效的标志。
    • 指向输入栅栏点数组 NV_OF_FENCE_POINT 的指针。由于有多个输入缓冲区,并且数据可以通过不同的引擎渲染到这些缓冲区,因此应用程序可以使用这些栅栏点将 NVOFA 与其他引擎同步。
  2. NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12 中填充以下字段
    • NVOFA 将在其中转储流向量的输出缓冲区的句柄。
    • 成本缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableOutputCost)。
    • 指向 NV_OF_FENCE_POINT 的指针,当 NVOFA 完成所有处理后,将发出信号。
  3. 调用 NvOFExecuteD3D12
    • 必须为每对帧/图像调用此 API。
  4. NVOFA 将生成流向量并将其存储在 NV_OF_EXECUTE_OUTPUT_PARAMS::outputBuffer 中。

Vulkan

在 NVOF API 初始化且所有缓冲区都已分配后,请按照以下步骤生成流向量

  1. NV_OF_EXECUTE_INPUT_PARAMS_VK 中填充以下字段
    • 输入帧的句柄。
    • 参考帧的句柄。
    • 外部运动向量提示缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableExternalHints)。
    • 使过去的临时提示无效的标志。
    • 指向输入信号量数组 NV_OF_SYNC_VK 的指针。由于有多个输入缓冲区,并且数据可以通过不同的引擎渲染到这些缓冲区,因此应用程序可以使用这些信号量将 NVOFA 与其他引擎同步。
  2. NV_OF_EXECUTE_OUTPUT_PARAMS_VK 中填充以下字段
    • NVOFA 将在其中转储流向量的输出缓冲区的句柄。
    • 成本缓冲区的句柄(如果启用了 NV_OF_INIT_PARAMS::enableOutputCost)。
    • 指向 NV_OF_SYNC_VK 的指针,当 NVOFA 完成所有处理后,将发出信号。
  3. 调用 NvOFExecuteVk
    • 必须为每对帧/图像调用此 API。
  4. NVOFA 将生成流向量并将其存储在 NV_OF_EXECUTE_OUTPUT_PARAMS::outputBuffer 中。

会话完成后,客户端需要释放所有已分配的资源,如下所述。

DirectX 11 模式

请按照以下步骤执行所有必要的清理

  1. 通过调用 NvOFUnregisterResourceD3D11 注销所有已分配的资源。
  2. 释放所有已分配的资源。
  3. 调用 NvOFDestroy
    • 此 NVOF API 销毁 NVOF 会话并释放 NVIDIA 显示驱动程序在内部分配的所有资源。
  4. 销毁 DirectX 11 设备上下文。
  5. 销毁 DirectX 11 设备。

DirectX 12 模式

请按照以下步骤执行所有必要的清理

  1. 通过调用 NvOFUnregisterResourceD3D12 注销所有已分配的资源。
  2. 释放所有已分配的资源。
  3. 调用 NvOFDestroy
    • 此 NVOF API 销毁 NVOF 会话并释放 NVIDIA 显示驱动程序在内部分配的所有资源。
  4. 销毁 DirectX 12 设备。

CUDA 模式

请按照以下步骤执行所有必要的清理

  1. 通过调用 NvOFDestroyGPUBufferCuda 取消分配所有已分配的缓冲区。
  2. 调用 NvOFDestroy
    • 此 NVOF API 销毁 NVOF 会话并释放 NVIDIA 显示驱动程序在内部分配的所有资源。
  3. 销毁 CUDA 流(如果已分配)。
  4. 销毁 CUDA 上下文。

Vulkan 模式

请按照以下步骤执行所有必要的清理

  1. 通过调用 NvOFUnregisterResourceVk 注销所有已分配的资源。
  2. 释放所有已分配的资源。
  3. 调用 NvOFDestroy
    • 此 NVOF API 销毁 NVOF 会话并释放 NVIDIA 显示驱动程序在内部分配的所有资源。
  4. 销毁 VkDevice、VkInstance

NVOF API 支持以下附加功能。

查询 NVOF API 功能

客户端应按照以下步骤查询 NVOF API 的各种功能

  1. 调用 NvOFGetCaps,在 NV_OF_CAPS 中指定要查询的功能。
  2. NVOF API 将填充与查询功能对应的支持值。

DirectX 11/12、Vulkan 和 CUDA 模式支持此 NVOF API。为了使应用程序在未来具有前瞻性,强烈建议客户端在使用这些功能之前检查此 API 返回的功能。

获取遇到的最后一个错误

客户端可以调用 NvOFGetLastError 以查询 NVIDIA 光流 API/驱动程序内部遇到的最后一个错误。

NVOF API 使用遇到的最后一个错误的描述填充输出缓冲区。

DirectX 11 和 CUDA 模式都支持此 NVOF API,并且在进行故障排除时可能会有所帮助。

查询最大支持的 NVOF API 版本

客户端应用程序可以使用 NvOFGetMaxSupportedApiVersion 来检索底层 NVIDIA 显示驱动程序支持的最大 NVOF API 版本。

使用此 NVOF API,客户端应用程序可以支持多个版本的 NVIDIA 驱动程序,并且仅使用底层 NVIDIA 显示驱动程序中特定 NVOF API 标头版本支持的功能。

换句话说,NvOFGetMaxSupportedApiVersion 使客户端能够构建可在支持不同 NVOF API 版本的不同 NVIDIA 显示驱动程序版本之间工作的应用程序。

DirectX 11/12、Vulkan 和 CUDA 模式都支持 NvOFGetMaxSupportedApiVersion

NVIDIA Optical Flow SDK 1.1 及更高版本支持此 NVOF API。

感兴趣区域 (ROI)

从 GA100 GPU 开始,NVOFA 可以为帧内的指定区域生成流向量,从而提高性能。

请按照以下步骤使用该功能

  1. 通过调用 NvOFGetCaps 查询功能。
  2. 如果支持该功能,则应将 NV_OF_INIT_PARAMS::enableRoi 设置为 1。
  3. 分别在 NV_OF_EXECUTE_INPUT_PARAMS::numRoisNV_OF_EXECUTE_INPUT_PARAMS::roiData 中指定需要评估流向量的 ROI 数量和 ROI 坐标。

前向和后向流(FB 流)

NV_OF_INIT_PARAMS::predDirection 设置为 NV_OF_PRED_DIRECTION_BOTH 时,将在单个 NvOFExecute/NvOFExecuteD3D12/NvOFExecuteVk API 调用中生成前向和后向流。

除了设置 NV_OF_INIT_PARAMS::predDirection 之外,如果设置了 NV_OF_INIT_PARAMS::enableOutputCost 标志,客户端还需要设置 NV_OF_EXECUTE_OUTPUT_PARAMS::bwdOutputBuffer/ NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12::bwdOutputBufferNV_OF_EXECUTE_OUTPUT_PARAMS::bwdOutputCostBuffer/ NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12::bwdOutputCostBuffer,它们分别接收后向流输出和成本。

前向流表示像素从输入帧到参考帧的运动。后向流表示像素从参考帧到输入帧的运动。

全局流向量

NV_OF_INIT_PARAMS::enableGlobalFlow 设置为 NV_OF_TRUE 时,在相同的 NvOFExecute/NvOFExecuteD3D12/NvOFExecuteVk API 调用中从前向流估计全局流向量。

除了设置 NV_OF_INIT_PARAMS::enableGlobalFlow 之外,客户端还需要设置 NV_OF_EXECUTE_OUTPUT_PARAMS::globalFlowBuffer/ NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12::globalFlowBuffer,它们接收全局流向量。

  1. 最大限度地减少创建的 CUDA 上下文数量。
    • 尽可能在多个 NVOF 会话中共享 CUDA 上下文。这有助于避免与 CUDA 上下文创建相关的内存和初始化开销。如果无法使用单个 CUDA 上下文,请尝试最大限度地减少创建的 CUDA 上下文数量(例如,使用池化上下文)。
  2. 为预处理和后处理创建和使用不同的 CUDA 流。
    • NVOF API 在内部使用 CUDA 进行预处理和后处理。因此,为预处理和后处理创建和使用不同的 CUDA 流可以实现更好的流水线处理并提高吞吐量。如果未指定不同的 CUDA 流,则 NVOF API 将对所有内部预处理和后处理操作使用 NULL 流,这可能会对整体吞吐量产生不利影响。
  3. 保持启用临时提示,NVOF API 默认情况下启用该提示。
    • NVOFA 使用较早帧的流向量作为提示来执行运动搜索,以利用视频序列中的时间相关性。仅当预先知道没有时间相关性时才禁用临时提示(例如,场景更改、独立的连续帧对)。
  4. 传递高质量的流向量作为提示。
    • NVOF API 提供了传递外部提示的选项。在硬件执行运动搜索时,外部提示被赋予最重要的地位。因此,建议传递高质量的流向量作为提示,并且如果提示质量不高,则不要使用该功能。
  5. 客户端应用程序应维护输入和参考缓冲区的池,并以循环方式使用它们。
    • NVOF API 需要输入帧和参考帧才能生成流向量。
    • 建议客户端应用程序维护输入和参考缓冲区的池,并以循环方式使用它们。这通过避免资源冲突来确保更好的流水线处理,但代价是稍微增加了内存占用。例如,对于第一个 NvOFExecute,,如果缓冲区 1 用作参考,缓冲区 2 用作输入,则第二个 NvOFExecute 应使用缓冲区 3 作为输入,缓冲区 4 作为参考。这避免了重用缓冲区的同步开销带来的性能影响。通常,4-6 个输入缓冲区的缓冲池应足以使硬件饱和。较低的分辨率(例如,低于 480p)可能需要更多数量的缓冲区才能实现高效率。
  6. 最大限度地减少原始图像缓冲区 (RGB/YUV) 的 PCIe 传输,以提高性能。
    • 如果输入帧在系统内存中以原始 YUV/RGB 帧的形式提供,则尽可能多地预加载视频内存中的帧将是有益的。通常,原始图像的 PCIe 传输需要大量带宽,并成为实现光流高性能的瓶颈。如果将帧预加载到视频内存中不是一种选择,请尝试在光流引擎计算当前帧集上的流向量时,流水线加载下一批帧到视频内存中。
    • 另一种选择是考虑对帧使用 H.264 或 HEVC 编码的码流,并在发送到光流计算之前及时使用 GPU 的 NVDEC 引擎解码帧。
  7. 仅在图形引擎带宽充足的情况下使用 SLOW 预设。
    • 使用 SLOW 预设可能会导致图形/CUDA 引擎利用率增加。
  8. 启用输出成本以获得流向量的置信度。
    • 成本值越高,表示流向量越不准确,反之亦然。
  9. NVOF API 不是线程安全的。
    • 如果 NVOF API 上下文在客户端应用程序中的多个线程之间共享,则应用程序需要使用适当的同步机制(例如临界区)来同步对共享 NVOF API 上下文的访问。
  10. 如果指定了 NV_OF_MODE::NV_OF_MODE_STEREODISPARITY,则输入图像对应该是已校正的,即输入帧对之间的垂直位移应为零。
  11. 当将输入帧传递到 NVOF API 时,不应向帧添加任何填充。
  12. NvOFGetMaxSupportedApiVersion 可用于开发可在支持不同 NVOF API 版本的 NVIDIA 显示驱动程序版本之间工作的应用程序。
  13. 建议使用 8 位成本(通过分配 NV_OF_BUFFER_FORMAT_UINT8) 类型的缓冲区)而不是 32 位成本,因为这样可以节省 CUDA 带宽。对 32 位成本的支持将在未来版本中弃用。

声明

本文档仅供参考,不得视为对产品的特定功能、条件或质量的保证。NVIDIA Corporation(“NVIDIA”)对本文档中包含的信息的准确性或完整性不作任何明示或暗示的陈述或保证,并且对本文档中包含的任何错误不承担任何责任。NVIDIA 对因使用此类信息或因使用此类信息而可能导致的侵犯专利或第三方的其他权利的后果或使用不承担任何责任。本文档不承诺开发、发布或交付任何材料(下文定义)、代码或功能。

NVIDIA 保留随时对本文档进行更正、修改、增强、改进和任何其他更改的权利,恕不另行通知。

客户在下订单前应获取最新的相关信息,并应验证此类信息是否为最新且完整。

NVIDIA 产品根据订单确认时提供的 NVIDIA 标准销售条款和条件进行销售,除非 NVIDIA 和客户的授权代表签署的单独销售协议(“销售条款”)另有约定。NVIDIA 在此明确反对将任何客户通用条款和条件应用于购买本文档中引用的 NVIDIA 产品。本文件未直接或间接地形成任何合同义务。

NVIDIA 产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命支持设备,也不适用于 NVIDIA 产品的故障或故障可能合理预期会导致人身伤害、死亡或财产或环境损害的应用。NVIDIA 对在此类设备或应用中包含和/或使用 NVIDIA 产品不承担任何责任,因此此类包含和/或使用风险由客户自行承担。

NVIDIA 不保证或声明基于本文档的产品将适用于任何特定用途。NVIDIA 不一定对每个产品的所有参数进行测试。客户全权负责评估和确定本文档中包含的任何信息的适用性,确保产品适用于并适合客户计划的应用,并为该应用执行必要的测试,以避免应用或产品的默认设置。客户产品设计的缺陷可能会影响 NVIDIA 产品的质量和可靠性,并可能导致超出本文档中包含的附加或不同的条件和/或要求。对于可能基于或归因于以下原因的任何默认设置、损坏、成本或问题,NVIDIA 不承担任何责任:(i) 以任何违反本文档的方式使用 NVIDIA 产品,或 (ii) 客户产品设计。

商标

NVIDIA、NVIDIA 徽标以及 cuBLAS、CUDA、CUDA Toolkit、cuDNN、DALI、DIGITS、DGX、DGX-1、DGX-2、DGX Station、DLProf、GPU、Jetson、Kepler、Maxwell、NCCL、Nsight Compute、Nsight Systems、NVCaffe、NVIDIA Deep Learning SDK、NVIDIA Developer Program、NVIDIA GPU Cloud、NVLink、NVSHMEM、PerfWorks、Pascal、SDK Manager、Tegra、TensorRT、TensorRT Inference Server、Tesla、TF-TRT、Triton Inference Server、Turing 和 Volta 是 NVIDIA Corporation 在美国和其他国家/地区的商标和/或注册商标。其他公司和产品名称可能是与其关联的各自公司的商标。

© 2018-2023 NVIDIA Corporation。保留所有权利。 上次更新时间:2023 年 2 月 27 日。