使用 Ryzen™ Threadripper 进行游戏开发 - 优化 UE4 构建时间

首次发布时间:
Sebastian Aaltonen

前言

这是一篇来自 Sebastian Aaltonen 的客座文章。Sebastian 是 Second Order 的联合创始人,曾任育碧®的高级渲染主管。Second Order 于 2018 年发布了他们的第一款游戏 — Claybook — 该游戏现已在 Steam™、PlayStation 4™ 和 Xbox One™ 上推出。Sebastian 使用虚幻引擎 4 构建了这款游戏,并在此前(去年早些时候)在 GPUOpen 上撰写了一篇关于优化 Claybook 新颖渲染器的 GPU 占用率和资源使用情况的文章。

然而,本文并非关于游戏中的技术。相反,它涵盖了任何虚幻引擎 4 开发者都应该感兴趣的内容:使用 AMD Ryzen Threadripper 处理器 在现代高性能、高度多线程工作站上优化引擎构建及其资产生产流程。核心概念也适用于大多数游戏引擎和资产生成系统,因此无论您是否是 UE4 开发者,都可以深入了解 Sebastian 如何优化他的 Threadripper 系统来帮助构建他们的游戏。

引言

一年前,我们构建了第一台 Ryzen Threadripper 1950X 工作站,就在 AMD 发布其新款高端桌面平台两个月后。在看到它如何加速开发后,我们又在几个月后构建了第二台 Threadripper 工作站。现在,我们已经使用这两台工作站一年来构建我们的游戏 Claybook,是时候谈谈我们使用 Threadripper 的体验了。

新旧对比

三年前我们成立 Second Order Ltd 时,是一家小型两人工作室,我们购买了当时最快的消费级英特尔® CPU。当时,这意味着全新的 Core i7-6700K,这是一款拥有 4 核 8 线程、主频 4.0 GHz、睿频 4.2 GHz 的“Skylake”处理器。它至今仍然是出色的游戏 CPU,而且英特尔在其最新芯片中仍然使用与其早期 Skylake 衍生产品 Core i9-9900K(代号 Coffee Lake)非常相似的核心微架构。

虚幻引擎文档目前建议在使用 C++ 源代码编译 UE4 时使用高核心数的英特尔至强 (Xeon) CPU。这一建议是准确的:使用 Core i7-6700K 编译虚幻引擎 4 的时间超过 40 分钟。

在我担任育碧®高级渲染主管期间,我已经与 AMD 和其他硬件供应商建立了良好的关系,AMD 提供了一台 Ryzen Threadripper 1950X 来帮助我们评估新平台,并了解它是否能改善我们的游戏制作方式。在花了一些时间了解 Threadripper 的优势和劣势,并对系统进行调整后,我们将虚幻引擎 4 的编译时间提高了 3 倍以上。这是一个巨大的改进,因此我们决定购买另一台 Threadripper 系统,以提高我们两人的生产力。

以下是用于生成以下数据所使用的系统的组件

处理器

Intel Core i7-6700K (4 核/8 线程, 4.0/4.2 GHz 基础/睿频)
AMD Ryzen Threadripper 1950X (16 核/32 线程, 3.4/4.0 GHz 基础/睿频)

内存

4 x 8 GiB DDR4-2133
4 x 8 GiB DDR4-2400
4 x 8 GiB DDR4-2667

存储2 x Samsung 850 PRO 512GB SSD
主板

ASUS Z170 Pro Gaming (Core i7)
ASRock Taichi X399 (Ryzen Threadripper)

首次 UE4 C++ 引擎编译对比

首先,我们为 Ryzen Threadripper 1950X 系统配备了从被 Threadripper 取代的 Core i7 系统上拆下来的现有 DDR4-2133 内存条。现在是时候重新编译 UE4 解决方案(包括 Claybook,所以这是完整的游戏编译)了。这是我们的发现:

处理器线程数时间性能
Intel Core i7-6700K640m 18s (2,418s)1x (基准)
Intel Core i7-6700K837m 12s (2,232s)1.11x
AMD Ryzen Threadripper 1950X2414m 52s (892s)2.71x
AMD Ryzen Threadripper 1950X3214m 43s (883s)2.74x

我们比较了两种 CPU 的最大线程数,也使用了保持桌面和其他应用程序高度响应的线程数。当 Core i7 使用所有 8 个线程编译 UE4 时,整个系统变得非常卡顿。甚至网页浏览器和 YouTube 视频也会卡顿。因此,8 线程编译主要适用于午休或会议期间的编译。当您将编译线程数减少到 6 时,桌面卡顿消失,您可以边编译边使用网页浏览器等轻量级应用程序。因此,我们将 Core i7 的 6 线程编译选为我们的 1.00x 基准。

Ryzen Threadripper 1950X 使用全部 32 个线程进行编译时,仍然可以保持桌面和网页浏览器的响应。您可以同时编译和浏览网页,没有任何问题。如果您将编译线程数减少到 24,在编译期间也可以进行繁重的后台任务,没有任何问题。减少到 24 个线程只会稍微增加编译时间。

在 Ryzen Threadripper 1950X 系统上进行 UE4 重建时,我曾多次在 4K 分辨率下进行《守望先锋》 competitivo 比赛,游戏始终保持 60 赫兹的帧率锁定。这非常出色,特别是如果您正在开发一款 CPU 密集型的 AAA 游戏并希望在 C++ 解决方案重建期间测试您的游戏。

核心利用率和时钟

虚幻引擎使用一个名为 UBT 的自定义构建工具,该工具可以很好地扩展到高核心数。在大量编译期间,UBT 会占用所有可用线程,并能达到所有核心 100% 的 CPU 利用率。然而,在构建过程的开始有一些任务(特别是 UnrealHeaderTool)是单线程的。在进行完整重新编译时,大约有 30 秒的构建时间会花费在单线程代码上。

Intel Core i7-6700K 使用所有 8 个线程编译。时钟速率稳定在 4 GHz。未达到睿频。深蓝色表示在内核中花费的时间,浅蓝色表示在用户代码中花费的时间。

AMD Threadripper 1950X 使用所有 32 个线程编译。时钟速率为 3.67 GHz,比 3.4 GHz 的基础时钟高 270 MHz 睿频。深蓝色表示在内核中花费的时间,浅蓝色表示在用户代码中花费的时间。

散热器和噪音

令人惊讶的是,在最大负载下,Threadripper 1950X 系统的噪音明显低于我们的 Core i7 系统。

我们的 Core i7 系统使用了 Corsair H100i 水冷散热器,而我们的两台 Threadripper 系统都配备了 Noctua NH-U14S 风冷散热器。Noctua 有一个大型 140mm 风扇,其转速比 Corsair H100i 的两个小型 120mm 风扇要慢。即使连续批量编译 Claybook 支持的所有四个平台,Noctua 也能将 CPU 温度保持在较低水平。这绝对是一个令人惊讶的结果。只要安装了像 Noctua NH-U14S 这样大型高质量的散热器,Threadripper 的噪音就不是问题。

优化 Threadripper

Intel Core i7 是一款消费级 CPU,开箱即用即可达到最大性能。然而,Threadripper 需要更多调整才能配置为最佳的工作站性能。默认情况下,某些 Ryzen Threadripper BIOS 设置会优先考虑游戏,而不是游戏开发中常见的、大规模并行的 C++、着色器和资产编译任务。这些任务通常不会在线程之间共享太多数据,这使得我们可以启用 NUMA 模式来提高性能。

Threadripper 对 DDR4 速度非常敏感,甚至比消费级 Ryzen CPU 更敏感,因为系统拓扑结构以及系统 RAM 如何连接到处理器。更高的 DDR4 速度在 Threadripper 上能起到双重作用:它还可以提高活动芯片之间 Infinity Fabric 互连的速度。

虚幻引擎:启用所有编译器线程

您首先要做的就是配置 UE4 以更好地利用我们的逻辑核心。默认情况下,UE4 将编译线程数设置为最多 4 核 CPU 的物理核心数,对于超过 4 核的 CPU,则设置为所有核心(包括逻辑核心)的 3/4。您可以提高这些值来提高编译性能。

修改 UE4 的 BuildConfiguration.xml 文件,以设置您偏好的配置

<!--?xml version="1.0" encoding="utf-8" ?-->
<configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<parallelexecutor>
<processorcountmultiplier>2</processorcountmultiplier>
<maxprocessorcount>30</maxprocessorcount>
</parallelexecutor>
</configuration>

在此示例中,我通过将 ProcessorCountMultiplier 设置为 2 来启用 SMT(英特尔称之为超线程)。这使得编译器可以使用 16 核 Threadripper 1950X 处理器的所有 32 个硬件线程。然后,我将 MaxProcessorCount 设置为 30,将编译线程数限制为 30。这样可以为主软件保留 2 个逻辑核心,从而在项目编译期间进行多任务处理时获得流畅的体验。

如果您的设置配置正确,您将获得以下 UE4 构建过程输出:

正在使用 30 个进程构建 XXX 个操作…

内存

Ryzen Threadripper 1000 系列处理器官方支持高达 DDR4-2667 的内存速度,而 Threadripper 2000 系列官方支持高达 DDR4-2933 的内存速度。您需要确保购买足够快的内存以达到官方时钟速率。我们没有对内存进行超频,因为稳定性对于专业工作非常重要。通过为系统配备四条相同的 DIMM 来达到最大内存速度。这将启用四通道内存,这对于充分发挥 Threadripper 系统的性能至关重要。如果您配备了超过四个 DIMM,由于内存子系统上的额外负载,支持的最大内存频率会略有降低。

虚幻引擎每个编译线程大约消耗 0.7 GB 的 RAM。当使用 Threadripper 1950X 的所有 32 个线程编译时,内存使用量峰值约为 21 GB。着色器编译器内存峰值类似。因此,对于 32 线程系统,您应该至少购买 32 GB 的 DDR4-2667 内存。如果您内存不足,当编译过程耗尽所有可用内存时,整个系统将陷入停顿。如果您希望在编译期间执行内存密集型任务(例如编辑具有大量图层的 16 位 Photoshop 文件或测试您的游戏),我强烈建议使用 64 GB。

让我们来看看内存时钟对 1950X 编译性能的影响

处理器 / 内存速度线程数时间性能
Intel Core i7-6700K640m 18s (2,418s)1x (基准)
AMD Ryzen Threadripper 1950X @ DDR4-21333214m 43s (883s)2.74x
AMD Ryzen Threadripper 1950X @ DDR4-24003213m 56s (836s)2.89x
AMD Ryzen Threadripper 1950X @ DDR4-26673212m 53s (773s)3.13x

结果很明显。与 DDR4-2133 相比,使用 DDR4-2667 内存可以节省将近 2 分钟。当您升级到 Threadripper 时,请务必购买您能获得的最快的内存 DIMM。

值得重申的是,Threadripper 2000 系列处理器官方支持 DDR4-2933。仅凭内存速度,我预计编译时间会缩短大约一分钟。再加上 +100 MHz 的基础时钟,+400 MHz 的睿频时钟以及约 3% 的 IPC 提升,Ryzen Threadripper 2950X 似乎比我们用于构建 Claybook 的 Threadripper 1950X 有了显著的升级。

NUMA

默认情况下,一些 Threadripper 主板会将处理器配置为使用 UMA 内存模式。这更适合游戏,平均游戏性能提高约 2%。但一些新游戏在 NUMA 模式下运行得更好,因为它们更能感知在 NUMA 系统上运行的含义。

如果您的 Threadripper BIOS 未默认启用 NUMA 模式,您确实应该启用它,因为 C++ 和着色器编译通常不会在线程之间共享任何数据,这在被正确视为 NUMA 系统的 NUMA 模式下具有优势。每个编译过程都是单线程的,但我们有 32 个进程并行运行。

通过进入 BIOS 并将 Memory Interleaving (内存交错) 更改为 Channel (通道) 来启用 NUMA。请查阅您的 X399 主板 BIOS 手册以获取正确的设置,但它通常是这样称呼的。

让我们看看这对性能有什么影响

处理器 / 内存速度线程数时间性能
Intel Core i7-6700K640m 18s (2,418s)1x (基准)
AMD Ryzen Threadripper 1950X @ DDR4-26673212m 53s (773s)3.13x
AMD Ryzen Threadripper 1950X @ DDR4-2667 + NUMA3212m 6s (726s)3.33x

通过启用 NUMA,我们将编译时间又缩短了 47 秒。现在我们的编译速度比起点(8 线程的 Core i7)快了 3 倍。这是预期的结果,因为我们比较的是 4 GHz 的 4 核处理器和 3.67 GHz 的 16 核处理器。Threadripper 1950X 的核心数量是 4 倍,但时钟速率略低,IPC 也略低。全新的 Threadripper 2950X 型号在这两方面都有改进,可能会让我们更接近 4 倍的理论性能增益。

着色器编译和数据烘焙

虚幻引擎编辑器有一个用于编译着色器和烘焙数据的后台线程系统。我们从 UE4 4.8 开始 Claybook 的开发,并一直使用到 UE4 4.21。在此期间,我们几乎合并了每个主要版本。在每次合并完成后,我们都会清理编译过的目录(DerivedDataCache, Intermediate, Saved),以确保没有过时的数据。在完整合并后首次启动 UE4 编辑器,在 Core i7-6700K 上花费了 30 多分钟。我们并没有大量使用 UE4 着色器节点图,但我们仍然拥有超过 2000 个着色器排列。Threadripper 使得合并过程快了很多。

为软件包构建烘焙数据是另一项耗时任务。当我们迭代 Xbox 和 PlayStation 4 的认证构建候选版本时,我们总共准备了近一百个内部软件包构建。软件包构建脚本会为该平台重新编译源代码并打包数据。Threadripper 提供了巨大的帮助。

Ryzen Threadripper 1950X 为 Xbox One 目标编译 Claybook 的所有着色器。几乎 100% 全核利用。3.52 GHz 时钟速率,比基础时钟高 120 MHz 睿频。深蓝色表示在内核中花费的时间,浅蓝色表示在用户代码中花费的时间。

HPET 定时器问题

在我们的 ASRock Taichi X399 主板上,其中一个干净的 Windows 10 Pro 安装在安装了 Windows 10 的 Meltdown 和 Spectre 补丁以及 X399 平台驱动程序后出现卡顿问题。我在更新主板 BIOS 之前安装并升级了 Windows,这可能导致了以下问题。

经过一些调查,我得出结论,卡顿问题影响了调用大量定时器的程序。UE4 开发编辑器的帧速率减半,因为其代码库中有许多计时器括号。像 Samsung Magician SSD 速度测试器和 Intel VTune 这样的基准测试软件也将系统拖慢至停顿。

我从其他 Threadripper 用户和 AMD 那里获得了一些帮助,并将问题追溯到了 HPET 定时器的使用。如果您认为您的系统也受到此问题的影响,请在管理员命令提示符中运行以下命令:bcdedit。此命令将显示一些系统启动信息。如果您看到以下行,则表示您受到了此问题的影响:Useplatformclock Yes

修复很简单,运行此命令行并重启您的计算机:bcdedit /deletevalue useplatformclock。如果您出于某种原因想恢复 HPET 定时器,可以运行此命令行:bcdedit /set useplatformclock true

您需要执行一次 deletevalue 命令,然后卡顿问题应该就会永久消失。AMD 已确认 HPET 定时器默认应在 Threadripper 上禁用,我认为新的 Windows 10 版本和新的主板 BIOS 版本应该能修复此问题。运行此命令后,我们带有 ASRock 主板的 Threadripper 系统的性能与我们带有 ASUS 主板的第二台 Threadripper 系统相当。

结论

很高兴看到 x86 CPU 市场再次出现强劲的供应商竞争。Ryzen Threadripper 为高性能工作站市场提供了一个受欢迎的新选择。它特别适合游戏开发工作负载,并且目前在市场上具有最佳的游戏开发成本/性能比。

作为一个新平台,在提取最大性能方面确实存在一些初期的磨合问题和调整需求,但一旦弄清楚这些问题,该平台和处理器就能够实现拥有 16 个 CPU 核心(带 SMT)和四通道内存的系统的绝大部分理论性能。请记住:如果您正在为游戏开发组装自己的 Threadripper 系统,请为您的系统配备快速的 DDR4 内存,并确保如果您使用虚幻引擎 4,请购买至少每线程 1 GB 内存。

使用 Threadripper 进行游戏开发的好处显而易见:在编译引擎代码、着色器和构建资源等常见游戏开发任务中能获得巨大的速度提升,同时还能提供一个响应迅速的系统,让您在进行这些任务的同时也能处理其他工作。

您可以访问我们开发的网站 www.claybookgame.com。该游戏今天已经在 Steam、PlayStation 4 和 Xbox One 上发布,快去看看吧!

Sebastian Aaltonen 的其他帖子

使用大型线程组优化 GPU 占用率和资源使用

Second Order Ltd 的联合创始人 Sebastian Aaltonen 探讨了如何优化使用大型线程组的计算着色器的 GPU 占用率和资源使用情况。

使用 Ryzen™ Threadripper 进行游戏开发 – 优化 UE4 构建时间

Sebastian Aaltonen(Second Order 联合创始人)的客座文章。文中涵盖了在使用 AMD Ryzen Threadripper 处理器时优化引擎构建和资产生产。

Sebastian Aaltonen

Sebastian Aaltonen 是 Second Order 的联合创始人,这是一家位于赫尔辛基的小型独立工作室,最近发布了他们的第一款游戏 Claybook!他此前曾在育碧担任高级渲染主管。

相关新闻和技术文章

© . This site is unofficial and not affiliated with AMD.