2010-03-23 117 views
66

关于GNU make中的作业数量是否应该等于内核数量,或者如果您可以通过添加一个额外的可以排队的作业来优化构建时间,而其他人“工作”。GNU make:作业数量是否应等于系统中CPU内核的数量?

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

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

+7

只是冰山,你可以使用'使\'NPROC \''使CPU独立的脚本:) – VivienG 2015-12-18 13:57:01

+0

如果您混合了io绑定和cpu绑定的配方,那么您可能会需要比NCPU更多的配置。考虑添加-lX选项。这不是一个真正可以回答的问题,除了“这取决于你的硬件并且完成任务”。 – 2017-07-10 17:48:27

回答

47

我会说最好的做法是自己在特定的环境和工作负载上进行基准测试。似乎有太多的变量(源文件的大小/数量,可用内存,磁盘缓存,源目录&系统标头是否位于不同的磁盘上等),以便找到适合所有人的答案。我的个人经验(在2核MacBook Pro上)是-j2比-j1快很多,但超出了(-j3,-j4等),没有可测量的加速。所以对于我的环境来说,“职位==核心数量”似乎是一个很好的答案。 (因人而异)

25

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

我不能,但是,给予科学的解释:我已经看到了很多的使用人相同的设置,他们给了我相当不错的成绩。

无论如何,你必须要小心,因为一些化妆链根本不与--jobs选项兼容,并可能导致意想不到的结果。如果您遇到奇怪的依赖性错误,请尝试make而不使用--jobs

+14

解释(不能保证其科学性,尽管)是“+ 1”提供了一个额外的工作,而其他n个工作中的任何人都在做I/O。 – 2010-03-24 11:56:49

+0

@LaurynasBiveinis:但是这些工作一直在不同的内核上运行,至少比更保守的环境下工作的时间更长,在这种环境下,工作有机会在相同的内核中保持一段较长的时间。这里有优点和缺点...... – krlmlr 2012-06-08 08:47:42

+1

核心数+ 1也是我的默认设置。一个问题是,在任何相当大的系统中,make似乎都会延迟链接,并且一起完成链接步骤。此时你用完了RAM。呸! – bobbogo 2014-01-16 22:04:18

6

最终,您将不得不做一些基准来确定用于构建的最佳数字,但要记住CPU不是唯一重要的资源!

如果你已经有了一个构建,在很大程度上依赖于磁盘上,例如,然后在多核系统上产卵大量的就业机会,实际上可能,因为磁盘将不得不做一些额外的工作使盘片头来回服务所有不同的工作(取决于许多因素,例如操作系统处理磁盘缓存的程度,磁盘本地命令排队等)。

然后你已经有了“真正的”核心与超线程。您可能会也可能不会从每个超线程的产卵作业中受益。再次,你必须找出基准。

我不能说我具体试过#cores + 1,但在我们的系统(英特尔酷睿i7 940,4个超线程核心,大量的RAM,和VelociRaptor硬盘)和我们的构建(大型C++建立交替的CPU和I/O绑定),-j4和-j8之间几乎没有什么区别。 (它可能会好15%...但是远不及近两倍)

如果我要去吃午饭,我会用-j8,但是如果我想用我的系统来做其他任何事情我会用一个较低的数字。 :)

+1

看起来不错,但我很困惑,为什么你不会每次使用这个+ 15%,通过使用'-j 8' – 2014-05-20 19:19:13

+0

@sg:j8确实对我在原始文章中描述的系统征税......机器仍然*可用*,但肯定不太敏感。所以如果我仍然想交互地使用它来完成其他任务(通常在其他代码上工作,偶尔也可能偶尔使用单个DLL构建),我会为交互位预留几个核心。 – ijprest 2014-05-21 00:22:28

+0

@sg:这对我们较新的系统来说不是什么问题......我怀疑这主要是因为我们现在正在运行SSD。 (我认为现在我们要完成固态硬盘了,我们完全依赖于CPU,我们试着完全在RAM驱动器上构建,几乎没有任何改进)。但是如果我是我,我仍然会留下几个内核在前台做任何比简单的文本编辑更多的事情。 – ijprest 2014-05-21 00:24:33

1

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

4

我刚买了一台富士康M/B和4GB G-Skill内存的Athlon II X2 Regor proc。

我把'cat/proc/cpuinfo'和'free'放在这个末尾,这样其他人就可以看到我的规格。这是一款双核心Athlon II X2,配备4GB内存。

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内核配置;

然后用各种咒语运行make。

我通过在时间命令之后发出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 
[email protected]:/archive4/linux-3.2.46$ 

同上,但用make -j2

real 27m3.194s 
user 48m5.135s 
sys  3m39.431s 
[email protected]:/archive4/linux-3.2.46$ 

同上,但用make -j3

real 27m30.203s 
user 48m43.821s 
sys  3m42.309s 
[email protected]:/archive4/linux-3.2.46$ 

同上,但用make - j4

real 27m32.023s 
user 49m18.328s 
sys  3m43.765s 
[email protected]:/archive4/linux-3.2.46$ 

同上,但用make -j8

real 28m28.112s 
user 50m34.445s 
sys  3m49.877s 
[email protected]:/archive4/linux-3.2.46$ 

'执行cat/proc/cpuinfo中' 收益率:

[email protected]:/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 

'免费' 得到:

[email protected]:/archive4$ free 
      total  used  free  shared buffers  cached 
Mem:  3991304 3834564  156740   0  519220 2515308 
+1

只有'make -j'在那个系统上做了什么? Make应该检查负载并根据负载调整进程的数量。 – 2013-10-21 16:38:26

+0

'make -j'根本不限制作业的数量。这对中型或大型项目来说通常是灾难性的,因为分工的速度比RAM更快。 你需要加载限制的选项是'-l [load]',与'-j' – 2017-05-05 22:34:12

39

我碰到我的我的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的内存

1

编译正如参考:

Spawning Multiple Build Jobs部分LKD

其中n是就业人数产卵。通常的做法是每个处理器产生一个或两个作业。例如,双处理器的机器上,人们可能会做

$使J4

相关问题