首页 UE4 中的 PGO
文章
取消

UE4 中的 PGO

简介

PGO(Profile Guided Optimization)是一种基于 LLVM 的编译时优化,通过使用运行时收集的分析数据来指导编译器进行优化。截至 UE5.0 版本,Epic 对 PC、Android 以及各 Console 平台都进行了配置。网路上很少有 PGO 相关的文章,这篇文章旨在尝试 PGO 的使用流程。

流程

按照 Epic 的流程,PGO 可以直接启用,也可以搭配Gauntlet 自动测试框架集成到自动测试流程中使用。关于 Gauntlet 框架的可参考官方文档 Gauntlet 自动化框架。PGO 整体的大致流程如图:

Progress2

构建用于 PGO 的版本

首先需要构建用于收集分析数据的 PGO 版本。添加命令行-PGOProfile以开启相应的宏:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /* --- TargetRules.cs --- */
  /// <summary>
  /// Whether to enable Profile Guided Optimization (PGO) instrumentation in this build.
  /// </summary>
  [CommandLine("-PGOProfile", Value = "true")]
  [XmlConfigFile(Category = "BuildConfiguration")]
  public bool bPGOProfile = true;

  /* --- UEBuildTarget.cs --- */
  if (Rules.bPGOProfile)
  {
    GlobalCompileEnvironment.Definitions.Add("ENABLE_PGO_PROFILE=1");
  }
  else
  {
    GlobalCompileEnvironment.Definitions.Add("ENABLE_PGO_PROFILE=0");
  }

PGO 版本中,宏ENABLE_PGO_PROFILE应该被启用,否则不会输出 PGO 的临时文件:

1
2
3
4
5
6
  /* --- PlatformMisc.cpp --- */
  #if ENABLE_PGO_PROFILE
    // Write the PGO profiling file on a clean shutdown.
    extern void PGO_WriteFile();
    PGO_WriteFile();
  #endif

可以通过在 build 时传入指定的参数-PGOProfile来控制是否开启ENABLE_PGO_PROFILE。默认情况下打开 PGOProfile 后也会打开 LTO,因此链接时间会变得非常长。

运行时收集数据

接下来需要启动游戏正常游玩、正常退出。因为只有在RequestExit()时才会在PGO_WriteFile中调用__llvm_profile_write_file即写入扩展名为*.profraw的临时文件。 该临时文件的输出目录可由命令行参数指定,但由于实现的问题,在不同的平台中,命令行参数有所不同,在启动时不指定输出目录,便会将该文件写入到默认位置,详情可参照PGO_GetOutputDirectory函数。

创建 Gauntlet 的测试用例<可选>

如果需要集成到自动测试流程中,需要创建测试用例并添加该测试至 Gauntlet 的项目里。这个过程可以参考Engine\Source\Programs\AutomationTool\Gauntlet\Unreal\Game下的 Samples。 Gauntlet 中已经有一个 PGO 的测试节点Gauntlet.UnrealPGONode.cs,其中 PGOConfig 有下面几个参数,可通过命令行传入给 UAT,其中ProfileOutputDirectory是必需的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /// <summary>
  /// Output directory to write the resulting profile data to.
  /// </summary>
  [AutoParam("")]
  public string ProfileOutputDirectory;

  /// <summary>
  /// Directory to save periodic screenshots to whilst the PGO run is in progress.
  /// </summary>
  [AutoParam("")]
  public string ScreenshotDirectory;

  [AutoParam("")]
  public string PGOAccountSandbox;

  [AutoParam("")]
  public string PgcFilenamePrefix;

使用 UAT 运行指定的测试用例。可以加入到 bat 文件里,方便集成到 Jenkins 一类的 CI 里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  rem path for RunUAT.bat
  set UAT_PATH=RunUAT.bat
  rem project name
  set PRJ_NAME={ProjectName}
  rem staging path
  set STAGING_DIR={EngineRoot}\{ProjectName}\Saved\StagedBuilds
  rem test command
  set TEST_CMD=RunUnreal
  rem test name
  set TEST_NAME=PGOTest
  rem profdata output path
  set PROFILE_OUTPUT_PATH={ProjectName}\Saved\Automation\PGO\
  rem screenshot path
  set SCREENSHOT_DIRECTORY={ProjectName}\Saved\Automation\PGO\Screenshot\
  rem platform Name
  set PLATFORM=Android
  rem build configuration
  set CONFIG=Test

  rem ********************* Start Gauntlet Test *********************
  %UAT_PATH% %TEST_CMD% -project=%PRJ_NAME% -platform=%PLATFORM% -configuration=%CONFIG% -build=%STAGING_DIR%\%PLATFORM%  -test=%TEST_NAME% -ProfileOutputDirectory=%PROFILE_OUTPUT_PATH% -ScreenshotDirectory=%SCREENSHOT_DIRECTORY% 
  rem ********************* End   Gauntlet Test *********************
  pause

注意事项

  • PGO 本质上是编译器优化,因此随着优化等级的提高,有可能会暴露出代码中一些原本不存在的问题。
  • 随着版本的迭代,代码不断更新,原本 PGO 收集的数据在用于新版本的优化时的效果会大打折扣。
  • Profile 数据会有额外的内存占用。

参考资料

本文由作者按照 CC BY 4.0 进行授权

VS 中一键 Attach 到指定进程

Uniform Table 的偏移问题