如何加快linux中的编译时间

时间:2013-07-19 10:11:15

标签: linux compiler-construction kernel

在linux下编译时我使用flag -j16,因为我有16个内核。我只是想知道使用像-j32这样的东西是否有意义。实际上这是一个关于处理器时间安排的问题,是否有可能比其他任何方式对特定进程施加更多压力(假设我想用-j16对每个编译进行简化,如果有一个-j32会怎么样?) 。 我认为它没有多大意义,但我不确定,因为不知道内核如何解决这些问题。

亲切的问候,

3 个答案:

答案 0 :(得分:3)

我使用基于GNU make的非递归构建系统,我想知道它的扩展程度如何。

我在具有超线程的6核Intel CPU上运行基准测试。我使用-j1-j20来衡量编译时间。对于每个-j选项make,运行三次并记录最短时间。使用-j9可以缩短编译时间,比-j6好11%。

换句话说,超线程确实有一点帮助,超线程的英特尔处理器的最佳公式是number_of_cores * 1.5

enter image description here

Chart data is here

答案 1 :(得分:2)

我们的商店里有一台具有以下特点的机器:

  • 256核心sparc solaris
  • ~64gb RAM
  • 用于/ tmp
  • 的ram驱动器的一些内存

当它最初设置时,在其他用户发现它存在之前,我运行了一些时序测试,看看我能推动它到底有多远。有问题的构建是非递归的,因此所有作业都是从单个make进程中启动的。我还将我的仓库克隆到/tmp以利用ram驱动器。

我看到-j56的改进。除此之外,我的结果很像Maxim的图表,直到某个地方(大致)-j75,性能开始下降。运行多个并行构建我可以将它推到-j56的明显上限之外。

主要制作过程是单线程的;在运行一些测试之后,我意识到我遇到的上限与主线程可以服务多少个子进程有关 - 这进一步受到makefile中任何需要额外时间解析的限制(例如,使用{{1而不是=以避免不必要的延迟评估,复杂的用户定义宏等)或使用:=之类的东西。

这些是我能够做的事情,可以加快那些会产生明显影响的构建:

尽可能使用$(shell)

如果您使用:=分配一个变量,然后稍后使用:=分配变量,则会继续使用立即评估。但是,+=?=,如果之前未分配变量,则始终会延迟评估。

在你有足够大的构建之前,延迟评估似乎不是什么大问题。如果变量(如+=)在所有makefile被解析后都没有变化,那么你可能不想对它进行延迟评估(如果你

如果您使用CFLAGS工具创建宏,请尝试尽可能提前进行评估

我曾经在脑海中创建了以下形式的宏:

$(call)

此版本生成10,000多个目标文件,其中大约8,000个来自C ++代码。如果我使用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) ,它只需要在已经评估的文本的所有编译步骤中立即替换CXXFLAGS := (...)。相反,它必须为每个编译步骤重新评估该变量的文本一次。

如果您别无选择,可以至少帮助减轻某些重新评估的替代实施:

${CXXFLAGS}

...虽然这只会有助于避免重复的ifneq 'undefined' '$(origin CLANG_BUILD)' IFCLANG = $(strip $(1)) else IFCLANG = $(strip $(2)) endif $(origin)来电;您仍然必须遵循尽可能使用$(if)的建议。

尽可能避免在食谱中使用自定义宏

在上述之后,推理应该非常明显;任何需要为每个编译/链接步骤重复评估变量或宏的内容都会降低您的构建速度。每个宏/变量评估发生在与启动新作业相同的线程中,因此解析所花费的时间是延迟启动另一个并行作业的时间。

每当它促进代码重用和/或提高可读性时,我都会在自定义宏中添加一些配方,但我尽量将其保持在最低限度。

答案 2 :(得分:1)

经验法则是使用处理器数+ 1。 Hyper-Thready计数,因此具有HT的四核CPU应具有-j9

将值设置得过高会产生反效果,如果你想加快编译时间,可以考虑使用ccache来缓存每个编译中不会改变的编译对象,并将distcc分配到多台机器上。