在 linux 下编译时,我使用标志 -j16,因为我有 16 个内核。我只是想知道使用-j32之类的东西是否有意义。实际上,这是一个关于处理器时间调度的问题,以及是否有可能以这种方式对特定进程施加比其他任何方式更大的压力(假设我喜欢使用 -j16 进行并行编译,如果使用 -j32 会怎样?) . 我认为这没有多大意义,但我不确定,因为不知道内核如何解决这些问题。
亲切的问候,
在 linux 下编译时,我使用标志 -j16,因为我有 16 个内核。我只是想知道使用-j32之类的东西是否有意义。实际上,这是一个关于处理器时间调度的问题,以及是否有可能以这种方式对特定进程施加比其他任何方式更大的压力(假设我喜欢使用 -j16 进行并行编译,如果使用 -j32 会怎样?) . 我认为这没有多大意义,但我不确定,因为不知道内核如何解决这些问题。
亲切的问候,
我使用基于 GNU make 的非递归构建系统,我想知道它的扩展性如何。
我在具有超线程的 6 核 Intel CPU 上运行基准测试。-j1
我使用to测量了编译时间-j20
。每个-j
选项make
运行 3 次,记录最短时间。在最短的编译时间内使用-j9
结果,比-j6
.
换句话说,超线程确实有一点帮助,英特尔处理器的超线程最佳公式是number_of_cores * 1.5
:
经验法则是使用处理器数量+1。超线程很重要,因此具有 HT 的四核 CPU 应该具有 -j9
将值设置得太高会适得其反,如果您确实想加快编译时间,请考虑使用 ccache 缓存在每次编译中不会更改的编译对象,并使用 distcc 将编译分布在多台机器上。
我们店里有一台机器,具有以下特点:
回到它最初设置的时候,在其他用户发现它的存在之前,我运行了一些时间测试,看看我能把它推多远。有问题的构建是非递归的,因此所有作业都从一个制作过程开始。我还将我的 repo 克隆到/tmp
以利用 ram 驱动器。
我看到了高达 -j56 的改进。除此之外,我的结果与 Maxim 的图表非常相似,直到高于(大约)-j75 的某个地方,性能开始下降。运行多个并行构建我可以将它推到 -j56 的明显上限之外。
主make进程是单线程的;在运行了一些测试之后,我意识到我遇到的上限与主线程可以服务多少子进程有关——这进一步受到了 makefile 中任何需要额外时间来解析的东西的阻碍(例如,使用而=
不是:=
避免不必要的延迟评估、复杂的用户定义宏等)或使用$(shell)
.
这些是我已经能够做的事情来加速具有显着影响的构建:
:=
尽可能使用
如果您使用 分配给变量一次:=
,然后使用分配+=
,它将继续使用立即评估。但是,?=
当+=
一个变量之前没有被赋值时,总是会延迟评估。
在你有足够大的构建之前,延迟评估似乎没什么大不了的。如果一个变量(如CFLAGS
)在所有 makefile 都被解析后没有改变,那么你可能不想对它使用延迟评估(如果你这样做了,你可能已经足够了解我在说什么了忽略我的建议)。
如果您创建使用该$(call)
工具执行的宏,请尽量提前进行评估
我曾经想到要创建以下形式的宏:
IFLINUX = $(strip $(if $(filter Linux,$(shell uname)),$(1),$(2)))
IFCLANG = $(strip $(if $(filter-out undefined,$(origin CLANG_BUILD)),$(1),$(2)))
...
# an example of how I might have made the worst use of it
CXXFLAGS = ${whatever flags} $(call IFCLANG,-fsanitize=undefined)
此构建生成超过 10,000 个目标文件,其中大约 8,000 个来自 C++ 代码。如果我使用CXXFLAGS := (...)
,它只需要${CXXFLAGS}
在所有编译步骤中立即用已经评估的文本替换。相反,它必须为每个编译步骤重新评估该变量的文本一次。
如果您别无选择,另一种实现至少可以帮助减轻一些重新评估:
ifneq 'undefined' '$(origin CLANG_BUILD)'
IFCLANG = $(strip $(1))
else
IFCLANG = $(strip $(2))
endif
......虽然这只有助于避免重复$(origin)
和$(if)
调用; 您仍然必须尽可能遵循有关使用的建议:=
。
在可能的情况下,避免在配方中使用自定义宏
在上面之后,推理应该很明显了;任何需要为每个编译/链接步骤重复评估变量或宏的东西都会降低您的构建速度。每个宏/变量评估都发生在与启动新作业的线程相同的线程中,因此任何花费在解析上的时间都是延迟启动另一个并行作业的时间。
每当它促进代码重用和/或提高可读性时,我都会在自定义宏中放入一些食谱,但我尽量将其保持在最低限度。