100

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

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

您是否看过(或做过)任何支持其中之一的基准测试?

4

10 回答 10

60

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

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

于 2010-03-23T11:53:47.613 回答
60

我已经在我的 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 秒。优势是大约 6.5 秒,编译时间为 53.5 秒,加速了 12%。
  • 从线程数扩展到双线程数并没有显着加速。12 和 15 的时间很可能是您可以忽略的统计异常。所花费的总时间和系统时间一样略有增加。两者都很可能是由于任务切换增加所致。这没有任何好处。

我现在的猜测:如果您在计算机上执行其他操作,请使用核心数。如果不这样做,请使用线程数。超过它没有任何好处。在某些时候,它们会受到内存限制并因此崩溃,从而使编译速度变慢。“inf”行是在很久以后添加的,这让我怀疑 8+ 工作存在一些热节流。这确实表明对于这个项目大小,没有有效的内存或吞吐量限制。不过,这是一个小项目,需要 8GB 的​​内存进行编译。

于 2013-09-17T15:01:08.107 回答
31

我个人使用make -j n其中 n 是“核心数”+ 1。

然而,我不能给出科学的解释:我见过很多人使用相同的设置,到目前为止他们给了我很好的结果。

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

于 2010-03-23T14:46:07.990 回答
9

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

make -j`nproc`

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

附加信息:正如有人提到的那样,使用所有内核/线程来编译软件可能会让你的机器几乎死机(无响应),甚至可能比使用更少的内核花费更长的时间。正如我在这里看到的一位 Slackware 用户发布的那样,他拥有双核 CPU,但仍提供高达 j 8 的测试,这在 j 2 时不再不同(CPU 只能使用 2 个硬件内核)。所以,为了避免无响应的盒子,我建议你像这样运行它:

make -j`nproc --ignore=2`

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

于 2019-06-15T06:12:11.477 回答
7

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

例如,如果你有一个严重依赖磁盘的构建,那么在多核系统上生成大量作业实际上可能会更慢,因为磁盘必须做额外的工作来回移动磁盘头来服务所有不同的作业(取决于许多因素,例如操作系统处理磁盘缓存的能力、磁盘对本机命令队列的支持等)。

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

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

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

于 2010-03-23T19:12:14.137 回答
5

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

我把我的 'cat /proc/cpuinfo' 和 'free' 放在最后,这样其他人可以看到我的规格。它是具有 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'd 进入目录 ( cd linux-3.2.46);

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

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

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

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

简单的“制作”:

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

如上所述,但使用 make -j2

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

如上所述,但使用 make -j3

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

如上所述,但使用 make -j4

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

如上,但使用 make -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
于 2013-07-13T04:42:49.743 回答
3

就像一个参考:

LKDSpawning Multiple Build Jobs部分:

其中 n 是要生成的作业数。通常的做法是为每个处理器生成一个或两个作业。例如,在双处理器机器上,可能会

$ 使 j4

于 2015-10-07T06:49:44.333 回答
1

根据我的经验,添加额外工作时必须有一些性能优势。只是因为磁盘 I/O 是除 CPU 之外的瓶颈之一。然而,决定额外作业的数量并不容易,因为它与正在使用的内核数量和磁盘类型高度相关。

于 2012-07-20T05:26:37.603 回答
1

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

我建议自己检查一下,但我从其他人的意见中发现,使用逻辑核心数来计算作业数在 Zen 上效果很好。除此之外,系统似乎并没有失去响应能力。我想这也适用于最近的英特尔 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 的速度。

于 2020-02-22T06:32:02.643 回答
1

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

Linus 自己刚刚升级到 3970x,你可以赌你的底价,他至少在运行 -j64。

于 2020-09-09T19:16:36.513 回答