为了确定您的游戏进程线程是否得到合理利用和安排以实现最佳性能,需要考虑一些事项。
- Frame pacing
- 多线程和线程并行化
- CPU 核心亲和性
多线程处理
许多游戏和游戏引擎使用多线程将 CPU 工作划分为可以稍微独立运行的逻辑任务。一种典型的配置是:用于输入和游戏逻辑的游戏线程、用于准备和提交要绘制对象的渲染线程,以及用于其他子任务(例如动画或音频)的工作线程。
我们建议并行处理线程,以充分利用多线程的性能优势。例如,游戏和渲染线程在不同的核心上部分或完全并发运行。这并非总能实现,例如在具有共享数据依赖项的情况下;但是,如果可能,这可能会导致 CPU 时间缩短,从而可能提高帧速率。
![使用并行处理的主线程和渲染线程以及工作器线程和音频线程的游戏](https://developer.android.google.cn/static/images/agi/threads-scheduling-images/sample_multithreading.png?authuser=7&hl=nl)
CPU 核心亲和性
对 CPU 工作负载性能有显著影响的一个因素是它们在核心上的调度方式。具体可分为两部分:
- 游戏线程是否在最适合其工作负载的核心上运行。
- 游戏线程是否经常在核心之间切换。
现代设备通常使用一种称为“异构计算”的架构,在该架构中,核心具有不同级别的性能:
- 一个或多个核心可提供最高的峰值性能,但会消耗更多电量。这些核心有时称为“大”核心。
- 其他核心的峰值性能较低,但节能较高。这些核心有时称为“小”核心。
- 可选:一个或多个核心可在性能和功耗之间取得平衡。这些核心有时称为“中等”核心。
您可以在获取跟踪记录时,在配置文件配置中启用 CPU,从而调查 CPU 使用率下的 CPU 线程行为。通过将轨迹的某个部分放大(小于 200 毫秒),您可以查看在设备的 CPU 核心上运行的各个进程。通常,较小的核心对应于较小的索引(例如 CPU“0”-“3”),而较大的核心对应于较高的索引(例如 CPU “6”-“7”),而中间核心(如果存在)将占据中间的索引(例如 CPU “5”-“6”)。这是惯例,但不保证一定如此。
如果您发现某些线程被调度到无法满足其性能或功耗需求的 CPU 上,请考虑手动为这些线程设置 CPU 亲和性。
![游戏中的主线程和渲染线程主要在大核心 (CPU 6-7) 上运行,显示为浅蓝色](https://developer.android.google.cn/static/images/agi/threads-scheduling-images/sample_bigcores.png?authuser=7&hl=nl)
您还可以观察线程是否会在核心之间切换。此类核心切换会产生一些上下文切换开销,以及核心的缓存/寄存器会丢失状态。
![游戏中的主线程 (Thread-7) 和渲染线程 (Thread-8) 在核心之间切换,显示为紫色](https://developer.android.google.cn/static/images/agi/threads-scheduling-images/sample_coreswitching.png?authuser=7&hl=nl)
为线程设置 CPU 亲和性会指示系统在游戏在前台运行时在给定核心上安排线程。这样做时需要考虑以下几个因素:
- 平台软件无法针对运行时因素(例如负载和温控降频)动态调整任务位置。
在不同设备上进行性能测试可能会产生截然不同的性能特征,尤其是在设备在价位或发布日期方面存在很大差异时。
较新款或较昂贵的设备可以在小核心上轻松运行给定工作负载,但较旧或更便宜的设备可能需要更大的核心才能满足同一工作负载的截止时间要求。
通过强制与大核心建立亲和关系,可能会不必要地增加耗电量和热负载。
出于这些原因,通常最好避免手动设置 CPU 亲和性。