UE 编译时 PCH 虚拟内存不足的错误

在多核心 CPU 上编译 UE 时,如 Ryzen 线程撕裂者(64 核 128 线程),比较频繁的遇到以下错误:

1
2
3
4
5
6
7
8
9
10
11
12
c1xx: note: 请访问 https://aka.ms/pch-help 了解更多详情
c1xx: fatal error C1076: 编译器限制: 达到内部堆限制
[12/1456] Module.Renderer.17_of_18.cpp
c1xx: error C3859: 未能创建 PCH 的虚拟内存
c1xx: note: 系统返回代码 1455: 页面文件太小,无法完成操作。
// english log
2> c1xx: note: please visit https://aka.ms/pch-help for more details
2>c1xx: Error C1076 : compiler limit: internal heap limit reached
2> [353/3017] Module.AdvancedPreviewScene.cpp
2> [354/3017] Module.PlacementMode.cpp
2>c1xx: Error C3859 : Failed to create virtual memory for PCH
2> c1xx: note: the system returned code 1455: The paging file is too small for this operation to complete.

默认情况下,UE 会拉起系统最大线程数量的编译进程。

如我的机器就是 128 个:

UE 里每个编译任务的 /zm 值为 1000:VCToolChain.cs?q=%2Fzm#L354

表示每个 cl 进程会分配 750M 的虚拟内存:/Zm (Specify precompiled header memory allocation limit)

Value of factor Memory allocation limit
10 7.5 MB
100 75 MB
200 150 MB
1000 750 MB
2000 1500 MB

而系统的虚拟内存大小是有上限的:

如果进程数 * 每个进程的 /zm 大于系统的虚拟内存,会导致虚拟内存分配失败:

$TaskCount * PCHMemoryAllocationFactor > SystemVirtualMemery$

也就出现了前面的问题。

解决这个问题的办法有两个:

  1. 根据线程数 *750M 来设置系统的虚拟内存大小
  2. 限制并行的任务数量,避免大量的进程同时分配虚拟内存

注意:如果 /zm 值设置的太小,可能无法满足 UE 合并翻译单元的要求,导致编译错误,所以,最好还是修改系统虚拟内存大小或者控制并行的任务数量。

通过编辑 BuildConfiguration.xml 就可以控制编译进程的 /zm 值,以及能够使用多少个 Task:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<WindowsPlatform>
<PCHMemoryAllocationFactor>1000</PCHMemoryAllocationFactor>
</WindowsPlatform>
<LocalExecutor>
<MaxProcessorCount>60</MaxProcessorCount>
</LocalExecutor>
<ParallelExecutor>
<MaxProcessorCount>60</MaxProcessorCount>
</ParallelExecutor>
</Configuration>

按照 128*750M 的计算,在 Ryzen3990X 上,至少要设置 94G 的虚拟内存,才能够满足 UE 拉起 128 个进程编译的需要。