GNU make:作业数应等于系统中CPU内核数吗?


87

关于GNU make中的作业数量是否应该等于内核数量,或者是否可以通过添加一个可以排队等待其他作业“工作”的额外作业来优化构建时间,似乎存在争议。 。

是在四核系统上使用-j4还是更好-j5

您是否看到(或完成了)任何一个支持另一个的基准测试?


8
仅作为提示,您可以make `nproc`用来制作独立于CPU的脚本:)
VivienG 2015年

如果混合使用io绑定和cpu绑定的配方,那么您可能需要的不仅仅是NCPU。还考虑添加-lX选项。除了“这取决于您的硬件和执行任务”,这实际上不是一个可以回答的问题。
James Moore

从技术上讲,有可能看到改进。您需要一个慢速的磁盘,不足的ram和许多小的源代码文件。十年前更容易实现。
汉斯·帕桑

Answers:


56

我想说的最好的办法是自己针对特定的环境和工作负载进行基准测试。似乎有太多的变量(一种/所有大小)的答案(源文件的大小/数量,可用内存,磁盘缓存,您的源目录和系统头是否位于不同的磁盘等)。

我的个人经验(在2核MacBook Pro上)是-j2显着快于-j1,但除此之外(-j3,-j4等)没有可测量的加速。因此,对于我的环境,“工作==核心数”似乎是一个很好的答案。(YMMV)


57

我已经在带有超线程笔记本电脑的4核上运行了我的家庭项目,并记录了结果。这是一个相当繁重的项目,但是最后包含了17.7秒的单元测试。编译不是非常耗费IO;有很多可用的内存,如果没有,其余的都放在快速的SSD上。

1 job        real   2m27.929s    user   2m11.352s    sys    0m11.964s    
2 jobs       real   1m22.901s    user   2m13.800s    sys    0m9.532s
3 jobs       real   1m6.434s     user   2m29.024s    sys    0m10.532s
4 jobs       real   0m59.847s    user   2m50.336s    sys    0m12.656s
5 jobs       real   0m58.657s    user   3m24.384s    sys    0m14.112s
6 jobs       real   0m57.100s    user   3m51.776s    sys    0m16.128s
7 jobs       real   0m56.304s    user   4m15.500s    sys    0m16.992s
8 jobs       real   0m53.513s    user   4m38.456s    sys    0m17.724s
9 jobs       real   0m53.371s    user   4m37.344s    sys    0m17.676s
10 jobs      real   0m53.350s    user   4m37.384s    sys    0m17.752s
11 jobs      real   0m53.834s    user   4m43.644s    sys    0m18.568s
12 jobs      real   0m52.187s    user   4m32.400s    sys    0m17.476s
13 jobs      real   0m53.834s    user   4m40.900s    sys    0m17.660s
14 jobs      real   0m53.901s    user   4m37.076s    sys    0m17.408s
15 jobs      real   0m55.975s    user   4m43.588s    sys    0m18.504s
16 jobs      real   0m53.764s    user   4m40.856s    sys    0m18.244s
inf jobs     real   0m51.812s    user   4m21.200s    sys    0m16.812s

基本结果:

  • 扩展到核心数量几乎可以线性地提高性能。实时时间从2.5分钟减少到1.0分钟(速度快了2.5倍),但是编译期间花费的时间从2.11分钟增加到2.50分钟。系统几乎没有注意到此位中的任何其他负载。
  • 从核心数量到线程数量的扩展极大地增加了用户负载,从2.50分钟增加到4.38分钟。这种可能性几乎翻了一番,因为其他编译器实例希望同时使用相同的CPU资源。系统越来越多地处理请求和任务切换,导致使用时间达到了17.7秒。优点是编译时间为53.5秒时约为6.5秒,从而使速度提高了12%。
  • 从线程数扩展到双线程数并没有明显提高速度。12和15处的时间很可能是您可以忽略的统计异常。与系统时间一样,所花费的总时间增加得如此之小。两者最有可能是由于增加了任务切换。这没有任何好处。

我现在的猜测是:如果您在计算机上执行其他操作,请使用核心计数。如果没有,请使用线程数。超过它并没有显示任何好处。在某些时候,它们将变得受内存限制并因此而崩溃,从而使编译慢得多。“ inf”行是在较晚的日期添加的,这使我怀疑8个以上的作业存在一些热限制。这确实表明,对于此项目大小,没有有效的内存或吞吐量限制。不过,这是一个小项目,可以编译8GB的内存。


根据stackoverflow.com/questions/56272639/…的说法,运行任务多于拥有CPU可以获得更多的优势,但前提是您的任务花费大量时间等待网络I / O。对于编译任务,情况并非如此。
ivan_pozdeev '19

30

我个人使用make -j nn为“核数” +1。

但是,我无法给出科学的解释:我见过很多人使用相同的设置,到目前为止,他们给了我很好的效果。

无论如何,您必须要小心,因为某些制造链与该--jobs选件根本不兼容,并可能导致意外结果。如果您遇到奇怪的依赖错误,请尝试make不使用--jobs


19
解释(尽管不能保证其科学性)是“ +1”提供了一个额外的工作,而其他n个工作中的任何一个正在执行I / O。
Laurynas Biveinis

@LaurynasBiveinis:但是,这些作业一直都在不同的核心上运行,至少比在一个较为保守的环境下运行的频率更高,在保守的环境下,一个工作有机会在同一核心上保留更长的时间。这里有优点和缺点...
krlmlr 2012年

1
核心数+ 1也是我的默认设置。一个问题是,在任何相当大的系统中,make似乎都会延迟链接并一起完成所有链接步骤。此时,您的RAM用完了。呸!
bobbogo 2014年

4
一些make-chains与--jobs选项不兼容->这意味着您缺少依赖项。如果有,请修复您的makefile。
dascandy

7

最终,您必须做一些基准测试来确定用于构建的最佳数量,但是请记住,CPU并不是唯一重要的资源!

例如,如果您的构建严重依赖于磁盘,那么在多核系统上产生大量作业实际上可能会比较,因为磁盘将不得不做一些额外的工作来回移动磁盘才能服务所有磁盘。不同的作业(取决于许多因素,例如操作系统处理磁盘缓存的性能如何,磁盘对本机命令的支持等等)。

然后,您有了“真正的”核心与超线程。您可能会也可能不会从每个超线程的生成工作中受益。同样,您必须进行基准测试才能找出答案。

我不能说我专门尝试了#cores + 1,但是在我们的系统(Intel i7个超线程内核,大量RAM和VelociRaptor驱动器)和我们的构建(大规模C ++生成,交替使用CPU和I)上/ O界)-j4和-j8之间几乎没有什么区别。(它可能好了15%……但远不及两倍。)

如果我要去吃午餐,我将使用-j8,但如果要在构建系统时将其用于其他任何系统,则将使用较小的数字。:)


1
看起来不错,但我感到困惑,为什么您不每次都使用+ 15%的-j 8
收益

1
@sg:j8确实对我在原始帖子中描述的系统造成了负担……该机器仍然可用,但响应速度肯定较慢。因此,如果我仍然想以交互方式将其用于其他任务(通常在其他代码上工作,也许偶尔使用单个DLL构建),那么我将为交互位保留几个内核。
ijprest

@sg:在我们较新的系统上,这不是一个大问题...我怀疑这主要是因为我们现在正在运行SSD。(我认为我们现在要使用SSD完全受CPU的限制了……我们尝试完全在RAM驱动器上构建,几乎没有任何改善。)但是如果我仍然愿意的话,我仍然会保留几个内核可用除了在前台进行简单的文本编辑以外,还可以执行其他任何操作。
ijprest

5

我刚刚获得了带有富士康M / B和4GB G-Skill内存的Athlon II X2 Regor proc。

我将“ cat / proc / cpuinfo”和“免费”放在此结尾,以便其他人可以看到我的规格。它是具有4GB RAM的双核Athlon II x2。

uname -a on default slackware 14.0 kernel is 3.2.45.

我将下一步内核源代码(linux-3.2.46)下载到/ archive4;

提取(tar -xjvf linux-3.2.46.tar.bz2);

cd进入目录(cd linux-3.2.46);

并将默认内核的配置复制到(cp /usr/src/linux/.config .);

用于make oldconfig准备3.2.46内核配置;

然后用-jX的各种咒语进行make。

我通过在time命令后发出make来测试每次运行的时间,例如'time make -j2'。在每次运行之间,我对linux-3.2.46树“ rm -rf”进行重新提取,将默认的/usr/src/linux/.config复制到目录中,运行make oldconfig,然后再次进行“ make -jX”测试。

普通的“ make”:

real    51m47.510s
user    47m52.228s
sys     3m44.985s
bob@Moses:/archive4/linux-3.2.46$

如上,但使用-j2

real    27m3.194s
user    48m5.135s
sys     3m39.431s
bob@Moses:/archive4/linux-3.2.46$

如上,但用-j3

real    27m30.203s
user    48m43.821s
sys     3m42.309s
bob@Moses:/archive4/linux-3.2.46$

如上,但用-j4

real    27m32.023s
user    49m18.328s
sys     3m43.765s
bob@Moses:/archive4/linux-3.2.46$

如上,但用-j8

real    28m28.112s
user    50m34.445s
sys     3m49.877s
bob@Moses:/archive4/linux-3.2.46$

'cat / proc / cpuinfo'产生:

bob@Moses:/archive4$ cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.91
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.94
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

“免费”收益率:

bob@Moses:/archive4$ free
             total       used       free     shared    buffers     cached
Mem:       3991304    3834564     156740          0     519220    2515308

1
make -j在该系统上做什么?Make应该检查负载并根据负载缩放进程数。
docwhat13年

1
make -j完全没有限制工作的数量。对于中型或大型项目,这通常是灾难性的,因为分叉的工作快于RAM支持的工作。您需要通过负载限制的选项是-l [load],与-j
Matt G

5

两者都没有错。为了与您自己以及正在编译的软件的作者保持和平(不同的多线程/单线程限制本身适用于软件级别),建议您使用:

make -j`nproc`

注意:nproc是linux命令,它将返回系统上可用的内核/线程数(现代CPU)。像上面一样将其放在ticks之下,会将数字传递给make命令。

其他信息:正如某人所提到的那样,使用所有内核/线程来编译软件实际上可能会使您的机器几乎瘫痪(无响应),甚至可能比使用更少的内核还要花费更长的时间。正如我在这里看到的一个Slackware用户所发布的那样,他拥有双核CPU,但仍然提供了对j 8的测试,但在j 2时就停止了变化(只有2个CPU可以使用的硬件内核)。因此,为避免无响应的框,我建议您这样运行:

make -j`nproc --ignore=2`

这将传递nprocto的输出,make并从其结果中减去2个核心。


3

就像一个参考:

LKD中的Spawning Multiple Build Jobs部分:

其中n是要产生的作业数。通常的做法是每个处理器产生一两个作业。例如,在一台双处理器计算机上,

$使j4


断开的链接,这是Robert Love的Linux Kernel Development的引文吗?
Behrooz

是的,那是那本书的。
南晓

1

根据我的经验,添加额外的工作一定会有一些性能上的好处。仅仅是因为磁盘I / O是CPU之外的瓶颈之一。但是,要确定额外作业的数量并不容易,因为它与所使用的磁盘的内核数量和类型密切相关。


1

多年以后,这些答案中的大多数仍然是正确的。但是,发生了一些变化:使用比物理核更多的工作现在确实可以显着提高速度。作为Dascandy表的附录,这是我在Linux上的AMD Ryzen 5 3600X上编译项目的时间。(The Powder Toy,提交c6f653ac3cef03acfbc44e8f29f11e1b301f1ca2)

我建议检查一下自己,但从其他人的输入中我发现,使用逻辑核心计数进行作业计数在Zen上效果很好。除此之外,该系统似乎并没有失去响应能力。我想这也适用于最近的Intel CPU。请注意,我也有一个SSD,因此值得亲自测试一下CPU。

scons -j1 --release --native  120.68s user 9.78s system 99% cpu 2:10.60 total
scons -j2 --release --native  122.96s user 9.59s system 197% cpu 1:07.15 total
scons -j3 --release --native  125.62s user 9.75s system 292% cpu 46.291 total
scons -j4 --release --native  128.26s user 10.41s system 385% cpu 35.971 total
scons -j5 --release --native  133.73s user 10.33s system 476% cpu 30.241 total
scons -j6 --release --native  144.10s user 11.24s system 564% cpu 27.510 total
scons -j7 --release --native  153.64s user 11.61s system 653% cpu 25.297 total
scons -j8 --release --native  161.91s user 12.04s system 742% cpu 23.440 total
scons -j9 --release --native  169.09s user 12.38s system 827% cpu 21.923 total
scons -j10 --release --native  176.63s user 12.70s system 910% cpu 20.788 total
scons -j11 --release --native  184.57s user 13.18s system 989% cpu 19.976 total
scons -j12 --release --native  192.13s user 14.33s system 1055% cpu 19.553 total
scons -j13 --release --native  193.27s user 14.01s system 1052% cpu 19.698 total
scons -j14 --release --native  193.62s user 13.85s system 1076% cpu 19.270 total
scons -j15 --release --native  195.20s user 13.53s system 1056% cpu 19.755 total
scons -j16 --release --native  195.11s user 13.81s system 1060% cpu 19.692 total
( -jinf test not included, as it is not supported by scons.)

在带有Ryzen 5 3600X,Samsung 860 Evo SSD(SATA)和32GB RAM的Ubuntu 19.10上进行的测试

最后说明:拥有3600X的其他人可能会得到比我更好的时间。进行此测试时,我启用了Eco模式,从而稍微降低了CPU的速度。


0

是!在3950x上,我运行-j32,这样可以节省数小时的编译时间!在编译过程中,我仍然可以观看youtube,浏览网络等,没有任何区别。即使使用1TB 970 PRO nvme或1TB Auros Gen4 nvme和64GB的3200C14,处理器也不总是固定的。即使是这样,我也不会注意到UI。我计划在不久的将来使用-j48在即将进行的一些大型项目中进行测试。我希望,正如您可能会做的那样,会看到一些令人印象深刻的改进。那些仍然拥有四核的人可能不会获得相同的收益。

Linus自己刚刚升级到了3970x,您可以打赌最低价,他至少正在运行-j64。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.