本文介绍了使用 NVIDIA GPU 时的 CPU 最佳实践。要在应用程序中获得高且一致的帧速率,请参阅高级API 性能提示。
要从 NVIDIA GPU 中获得最佳性能,请将其与 CPU 上的高效工作委派配对。帧速率上限、卡顿和其他低于标准的应用程序性能事件通常可以追溯到 CPU 上的瓶颈。使用以下技巧来了解你应该做什么以及应该避免什么。
多线程和工作负载平衡
再多的 GPU 工作优化也无法克服 CPU 瓶颈。均匀平衡所有线程的工作,以获得最佳效果。
推荐
- 平衡所有线程之间的命令列表创建和记录。 D3D12 和 Vulkan 的主要设计理念是使游戏引擎能够在多个 CPU 核心之间分配图形工作负载。
- 关闭并重置录制工作线程上的命令列表。
不推荐
- CPU 密集型命令列表不应记录在其上
ExecuteCommandLists
被调用。典型的ExecuteCommandLists
在给定帧的命令列表记录之后被序列化。将其与所有其他命令列表记录线程保持在一个单独的线程上,可以使后续的帧 CPU 工作从不那么复杂的负载平衡开始。 - 细粒度查询的使用增加了 CPU 开销,例如在绘制调用的计时方面。
执行命令列表和多个命令队列
ExecuteCommandLists
向 GPU 提交一个命令列表数组( ECL )以供执行。 NVIDIA 硬件支持多个命令队列以并行化图形工作,使图形计算或计算工作能够同时执行。
推荐
- 减少
ExecuteCommandLists
尽可能多地打电话。 - 在多个队列上执行命令列表时,请考虑同步所增加的开销。信号或等待围栏呼叫越少, CPU 就越好。这应该与最大化 GPU 上的工作负载重叠的能力相平衡。
资源分配和销毁
创建和销毁缓冲区、纹理和着色器是高效计算机图形的基础。
推荐
- 使用专用线程创建资源,以避免隐藏的操作系统成本和阻塞帧渲染,因为这可能会导致昂贵的操作系统分页工作。
- 免费的线程资源创建也可能是异步复制队列上传的自然选择,这将使完全免费的线程数据上传到
vidmem
用于新分配的资源。以这种方式构建上传避免了为帧渲染添加隐藏的开销。但是,请注意,额外的队列和队列之间的同步也可能增加 CPU 开销。
构建光线跟踪加速度结构
光线跟踪加速结构是组织场景的几何信息以优化光线和场景对象之间的相交测试的数据结构。BuildRaytracingAccelerationStructure
使用场景几何体执行加速度结构的初始构造。
推荐
- 使用时在单独的线程上录制
BuildRaytracingAccelerationStructure
,优选在异步计算队列上进行调度。这个 API 是 CPU 密集型的,可以控制命令列表记录时间 - 要警惕与完整构建的几何复杂性直接相关的 CPU 开销。重建应该是相对固定的开销。
- 请注意与
FAST_TRACE
构建。
有关详细信息,请参阅Best Practices: Using NVIDIA RTX Ray Tracing.
CreatePipelineState 和 CreateStateObject
CreatePipelineState
用于创建渲染管道状态对象,该对象定义图形管道的配置。管道状态对象封装执行图形命令所需的所有状态,例如输入布局、着色器程序、混合状态、深度模具状态和光栅化器状态。
CreateStateObject
使开发人员能够创建一个状态对象,将图形管道的状态封装为一个整体。状态对象包括使用创建的管道状态对象CreatePipelineState
,以及其他状态信息,如视口、剪刀形矩形和输入布局。
推荐
- 使用
AddToStateObject
以将着色器代码增量添加到现有光线跟踪状态对象,并避免不必要的 CPU 开销。
不推荐
- 避免不必要地创建管道状态对象和光线跟踪对象。这些操作涉及着色器创建,这可能会消耗大量的 CPU 周期。着色器复杂性直接影响创建调用的复杂性。