CPU 和 GPU 优化提示

本文档介绍了如何使用工具来识别和解决 CPU 和 GPU 瓶颈,从而优化游戏性能。

CPU 优化

如果分析显示游戏受 CPU 限制,则必须进一步调查。 这需要确定导致瓶颈并降低 FPS 的特定线程或 API。

对于 CPU 优化,通用解决方案通常效果不佳。相反,您必须根据游戏或场景确定最繁重的工作负载,然后优化相关逻辑和函数。

游戏引擎时间轨迹工具

以下工具可帮助您进行此分析:

Unreal Insights

在 Unreal Engine 项目中,Unreal Insight 工具可帮助分析构成帧的各个线程的时序轨迹信息。

举例来说,GameThread 通常会占用最大比例的 CPU 时间,这主要是因为 Tick Time。此外,与 FActorComponentTickFunction 关联的任务会消耗相当一部分 Tick Time。

为了优化 FActorComponentTick,必须排除计算并针对位于相机视野范围之外的角色和对象实现剔除。此外,利用基于 LOD(细节级别)的动画可以进一步提升性能。

Unreal Insight 轨迹时间轴,显示了 GameThread、RenderThread 和 RHIThread 的执行时间
包含 GameThread、RenderThread 和 RHIThread 的 Unreal Insight 轨迹(点击可放大)。

Unity Profiler (Unity)

使用 Unity 性能分析器 进行分析后发现,主 线程 消耗的时间超过 45 毫秒,其中 PostLateUpdate.FinishFrameRendering 占用了 16.23 毫秒,是耗时最多的操作。在此期间,观察到多次调用 Inl_RenderCameraStack。建议确定已启用摄像头的必要性,并据此进行优化。

Unity Profiler 时间轴显示了主线程等待 Gfx.WaitForPresentOnGfxThread
Unity 分析器中的 GPU 绑定示例(点击可放大)。

系统级分析工具

使用以下性能分析工具:

Perfetto

借助 Perfetto 跟踪记录,您可以确定 Android 设备上每个线程的 CPU 核心分配和执行详细信息。这样,您就可以通过分析线程执行数据来发现性能瓶颈。

CPU 开销情况

该轨迹表明,GameThread 和 RenderThread 上的工作负载导致 RHI 线程的 QueuePresent 出现延迟,从而导致基于 VSync 的 CPU 绑定场景。

Perfetto 轨迹,显示了 GameThread、RenderThread 和 RHIThread 的执行时间
包含 CPU 执行详细信息的 Perfetto 轨迹(点击可放大)。

GPU 开销案例

轨迹表明,GPU 完成本身超过 25 毫秒,这表示属于 GPU 绑定场景。

Perfetto 跟踪记录显示 GPU 完成块等待 GPU 完成
包含 GPU 开销详细信息的 Perfetto 轨迹(点击可放大)。

Simpleperf

如需确定当前 CPU 使用率最高的函数,可以使用 simpleperf。为获得最佳效果,建议您对这些功能进行排序,优先处理使用率最高的功能。

显示 CPU 使用率最高的函数的 Simpleperf 输出
Simpleperf CPU 分析:分析函数调用层次结构和资源利用率(点击可放大)。

Simpleperf 可帮助您检查有关占用最多 CPU 时间的函数的数据。如需优化 CPU 使用率,请先从使用 CPU 最多的函数入手。在此示例中,与 ActorComponentTickFunctions 中的动画关联的 USkeletalMeshComponent 使用的 CPU 最多。

GPU 优化

如果分析表明游戏受 GPU 限制,则必须进一步调查。这需要使用各种工具和技术来进行 GPU 优化和分析。

如需优化 GPU,请使用帧调试器分析每个场景的渲染流水线和绘制调用。此外,您还必须深入了解 GPU 架构和流水线行为,才能确定不必要的操作或需要优化的方面。

以下部分介绍了 GPU 优化方法和工具。

消除不必要的 RenderPass

为了提高渲染性能并减少 GPU 工作负载,请消除不必要的渲染通道。其中包括缺少绘制调用的任何渲染通道,或输出未在最终帧中使用的任何渲染通道。

使用 GPU 调试器(例如 RenderDoc)分析渲染流水线并发现优化机会。

  1. 无绘制调用:检查渲染通道是否包含任何绘制调用。如果没有绘制调用,则移除相应 pass。

  2. 未使用的输出:检查后续处理遍数是否会访问或显示渲染处理遍数的输出,例如颜色或深度。如果不是,请移除通行卡。

  3. 可合并的卡券:确定可合并的卡券:

    • 相同的帧缓冲区或附件
    • 兼容的加载或存储操作
    • 中间没有依赖屏障
RenderDoc 事件浏览器,显示 Vulkan 渲染通道和绘制调用
RenderDoc 中的 RenderPass 和 GPU 命令序列(点击可放大)。

尽可能减少加载或存储操作

加载或存储操作会占用大量内存,因此属于资源密集型操作。最大限度地减少不必要的加载-存储操作。仅当需要 RenderPass 中的附件时才执行这些操作。否则,请将它们替换为 ClearDon't care 操作,以减少开销。

如何进行优化

使用 GPU 调试器(例如 RenderDoc)分析渲染流水线,并确定以下优化机会:

  1. 加载:如果渲染通道附件不使用来自前一个通道或附件的数据,则无需执行加载操作。在这种情况下,使用 Don't careClear 可以减少开销。

  2. 存储:如果渲染通道附件在当前渲染通道之后未使用,则存储操作是不必要的。在这种情况下,请使用 Don't careClear

  3. 替换:确定当前加载或存储设置是否可以替换为 ClearDon't Care,而不会影响最终帧。