只要有寫過 C++ 程式的人,大都可以理解不同的構建配置(BuildConfiguration)編譯器會幫助我們進行不同程度的優化── Debug 與 Development主要是為了除錯,Test用來偵測效能表現,最後Shipping則做出最好的優化配置。──但是除了那些各式各樣的編譯參數調整之外,我們其實還可以利用事先產生「profile」的方式讓編譯器利用運行時期的資訊來做出各種更激進的優化手段,例如:縮減整個code size、 降低 if-then-else branch 的預測失誤來減少 cpu指令的執行數量, 或者是重新組織整個 code layout 以增進 cpu 指令的 cache效率。詳細可以參考Intel的線上文檔。
UE4當然也有提供這項優化功能,但目前(4.25)也只支援 PS4、 XboxOne 與Switch 這三個平台。 就我自身的經驗而言,在啟用 PGO 之後整體的 FPS 大約提升了3左右, 其中屬於CPU 部份的 Game 跟 Draw 這二條 Thread 各別降低了1.xx ms的運行成本。這效能的提升雖然不算多,但卻是在一些常規的優化手段都採取之後能夠再額外得到的效能突破。除了缺點是開發者需要多花一些時間在建置流程的設計上與編譯的等待時間之外,但帶來的卻是能夠讓我們將省下的效能預算投入在更好的遊戲表現上,何樂而不為呢?
首先讓我們先來看一下整體運行流程:
整個流程的第一步,我們必須要產生PGI build,這邊我們可以選擇使用Development 或者是 Test 組態都行, 重點是我們必須要籍助RunUAT指令(UnrealAutomation Tool),並傳入以下參數來產生正確的版本: -UbtArgs=’-LTCG-PGOProfile’ 接著在C++進行linking之前出現以下訊息的話就代表指令成功: EnablingProfile Guided Instrumentation (PGI). Linking will take a while.
以下是完整的PGI Build指令:
接著我們必須利用Gauntlet(4.21推出的自動化測試框架)將剛才Local PGIBuild跑起來,但在這之前,我們必須要先設計專案所使用到的PGONode並放進/Path/To/YourProject/Build/Script/YourProject.Automation/YourProject.PGONode.cs,如下:
接著我們必須先編譯這個C#專案,並把dll的輸出路徑設定到Engine/Binaries/DotNET/AutomationScripts/下面,這樣Gauntlet才有辦法找到 YourProjectPGONode並運行起版本。C#專案編譯指令如下:
然後我們就可以運行 Gauntlet 將版本跑起來,其中參數-test=”YourProjectPGONode” 會去找到我們剛剛撰寫的 C# Script起來運行:
這邊我們可以選擇手動跑過整個遊戲流程或者是撰寫自動化 Script ,等到收集完足夠的 profile data 之後, 再手動輸入UE4的quit consolecommand讓引擎跑完正常結束遊戲的流程, Gauntlet 便會自動的將profile.profdata 放在 /Path/To/MyPorject/Build/${YourPlatform}/PGO/ 下面。
到此為止我們已經收集到建構PGO版本所需要的全部資訊,上面介紹的建置PGI版本與收集profile.profdata不需要每次做版本都執行,我們只需要定期的人工檢視C++程式碼有足夠的變動再跑這個流程即可。
接下來,我們就可以利用profile.profdata做出優化過後的PGO版本,只要在RunUAT 做 build 時,代入以下參數:-UbtArgs=’-LTCG -PGOOptimize’,他就會自動的找到 /Path/To/MyPorject/Build/${YourPlatform}/PGO/ 下的profile.profdata 進行建置,接著在C++進行linking之前出現以下訊息的話就代表指令成功: EnablingProfile Guided Optimization (PGO). Linking will take a while.
以下是完整的PGO Build指令:
Leave a Reply