在开启 DX12 后出现 CPU 占用率变高,GPU 占用率反而降低,并伴随 帧数提高但时有卡顿 的现象,是一个比较典型的问题,尤其是在 DX12 刚推出时的许多游戏中。这种现象的根本原因主要与 DirectX 12 的设计特点 和 游戏引擎的实现方式 有关。以下是对这种现象的原理分析以及一些可能的解决方案。
1. 为什么 DX12 会导致 CPU 占用率变高?
(1)DX12 的低级 API 特性
DX12 是一个低级别的图形 API,它相比 DX11 提供了更大的灵活性,但也将许多原先由驱动程序处理的任务交给了游戏引擎和应用程序。这意味着:
- 更多的工作由 CPU 承担:DX12 需要开发者显式管理资源、同步和命令队列,这些任务会增加 CPU 的负担。
- 多线程优化:DX12 的多线程能力允许多个线程录制命令缓冲区(Command Buffer),从而更有效地利用多核 CPU。但如果实现不当,多线程工作可能导致 CPU 的负载增加。
简单来说,DX12 将更多的工作从驱动程序层转移到了应用层,导致 CPU 的占用率显著增加。
(2)CPU 线程调度的不平衡
DX12 的多线程能力需要开发者显式管理。如果游戏引擎的多线程实现不够完善,可能会出现以下问题:
- 主线程压力过大:尽管 DX12 支持多线程录制命令缓冲,但如果游戏引擎没有很好地分配任务,主线程可能仍然是瓶颈。
- 线程间同步开销:多线程录制命令缓冲区需要线程间的同步,如果处理不当,可能导致高昂的线程切换和同步开销,从而进一步增加 CPU 占用。
(3)资源管理的复杂性
在 DX11 中,显存管理(如资源绑定和内存分配)由驱动程序自动处理,而在 DX12 中,这些任务需要游戏引擎或开发者手动管理。错误或低效的资源管理可能导致:
- CPU 过度忙碌:CPU 花费更多时间管理资源,而不是用于其他任务。
- GPU 利用率降低:如果 CPU 不能及时为 GPU 准备数据,GPU 可能会出现等待状态。
2. 为什么 GPU 占用率反而降低了?
(1)CPU 成为瓶颈
在 DX12 下,GPU 的工作效率高度依赖于 CPU 的任务分发效率。如果 CPU 处理任务的速度不够快(例如命令缓冲录制或资源绑定延迟),GPU 就会因为等待数据而处于低利用率状态。这种情况被称为 “CPU 限制”(CPU-bound)。
(2)GPU 的优化未充分利用
虽然 DX12 理论上可以让 GPU 更高效地运行,但以下情况可能导致 GPU 利用率未达到预期:
- 渲染管线优化不足:游戏引擎可能没有充分利用 DX12 的高级功能(如异步计算、细粒度命令队列管理),导致 GPU 的潜力被浪费。
- 资源绑定问题:如果资源绑定不够高效,GPU 可能因为频繁的资源切换而降低利用率。
(3)帧率提高导致 GPU 负担下降
在一些场景中,DX12 优化了 CPU 的工作效率,从而提高了帧率。但由于帧率的提高,单帧内 GPU 的工作量实际上可能减少。例如:
- 如果 DX11 下 GPU 每帧运行 16ms(60 FPS),而 DX12 提高到 12ms(80 FPS),单帧 GPU 的工作时间就会减少,从而在统计上表现为 GPU 占用率下降。
3. 为什么会出现卡顿?
尽管 DX12 提高了帧数,但时有卡顿的现象,可能是以下原因导致的:
(1)CPU 和 GPU 的同步问题
DX12 的显式同步特性要求开发者手动管理 CPU 和 GPU 的任务。如果同步不当,例如:
- CPU 提交任务过慢:导致 GPU 闲置,帧时间不均匀。
- 线程同步冲突:多线程录制命令缓冲区时,如果线程间竞争资源,可能导致帧率不稳定。
这种不均匀的帧时间会导致 瞬时卡顿,即使平均帧率较高。
(2)资源加载或状态切换问题
在 DX12 下,错误或低效的资源管理可能导致:
- 资源加载卡顿:例如纹理、网格或渲染目标切换时,GPU 可能需要等待资源上传或转换。
- 显存不足:显存管理不当可能导致资源频繁从主内存传输到显存,引发卡顿。
(3)驱动程序或游戏引擎优化不足
- 驱动问题:DX12 的性能优化需要 GPU 驱动的支持。如果驱动程序的 DX12 实现不够成熟,可能导致性能波动。
- 游戏引擎问题:一些游戏的 DX12 实现可能并不完善,尤其是在早期版本中,常见的问题包括多线程优化不足、资源管理低效等。
4. 如何解决这些问题?
(1)尝试不同的图形 API
- 如果 DX12 带来的卡顿问题无法接受,可以尝试切换回 DX11 或 Vulkan。
- 尽管 DX12 提高了帧率,但 DX11 的驱动程序通常更成熟,有更稳定的表现。
(2)调整游戏设置
- 降低 CPU 负担:减少 CPU 开销较高的设置(如视距、物理效果、AI 数量等)。
- 减少 GPU 状态切换:减少材质种类、纹理分辨率等,降低频繁的资源绑定和切换。
(3)更新驱动和游戏版本
- DX12 的性能很大程度上依赖于 GPU 驱动程序。如果驱动未优化,可能导致性能问题。
- 游戏开发者可能会通过补丁优化 DX12 的实现,定期更新游戏版本可能解决问题。
(4)手动优化硬件资源
- 确保 CPU 和 GPU 之间的负载平衡。例如,如果 CPU 是瓶颈,可以尝试超频 CPU 或升级到更多核心的处理器。
- 如果 GPU 利用率过低,可以尝试提高分辨率、开启抗锯齿等图形设置,让 GPU 更充分地工作。
5. 总结
开启 DX12 后 CPU 占用率变高、GPU 占用率降低 的现象主要归因于以下几点:
- DX12 将原本由驱动管理的任务交给了 CPU,增加了 CPU 的负担。
- 多线程管理和同步复杂性增加,可能导致 CPU 成为瓶颈。
- 如果 CPU 不能充分为 GPU 提供数据,GPU 利用率会降低。
- 错误或低效的资源管理、同步问题可能导致帧数波动和卡顿。
如何选择?
如果 DX12 带来的帧数提升不足以抵消卡顿问题,可以切换回 DX11,获得更稳定的体验。而对于 DX12 的卡顿问题,未来可能需要依赖游戏开发者和 GPU 驱动厂商的进一步优化。