GNU make:作业数量是否等于系统中的CPU核心数量?
关于GNU make中作业的数量是否应该等于内核数量,或者如果你可以通过增加一个额外的工作来优化构build时间,这些工作可以排队而其他人“工作”,似乎有一些争议。 。
在四核系统上使用-j4
或-j5
更好吗?
你有没有看到(或完成)任何支持其中的基准testing?
我认为最好的做法是自己在特定的环境和工作负载上进行基准testing。 似乎有太多的variables(源文件的大小/数量,可用内存,磁盘caching,源目录和系统头文件是否位于不同的磁盘上,等等)的一个万能的答案。
我个人的经验(在2核MacBook Pro上)是-j2比-j1快得多,但超出了(-j3,-j4等),没有可测量的加速。 所以对于我的环境来说,“职位==核心数量”似乎是一个很好的答案。 (YMMV)
我用超线程笔记本电脑在我的4核心上运行了我的家庭项目并logging了结果。 这是一个相当重的编译器项目,但最后包含了一个17.7秒的unit testing。 编译不是很密集的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的时间很可能是你可以忽略的统计exception。 所花费的总时间和系统时间一样略有增加。 这两者很可能是由于任务切换的增加。 这没有任何好处。
我现在的猜测是:如果你在电脑上做了其他的事情,就使用核心数量。 如果不这样做,请使用线程数。 超过它显示没有好处。 在某些时候,由于这个原因,它们将变得记忆受限,崩溃,使编译速度变慢。 这个“inf”系列在更晚的时候被添加了,这使我怀疑有8个以上的工作有一些热量节stream。 这确实表明,对于这个项目大小,没有实际的内存或吞吐量限制。 这是一个小的项目,但是如果有8GB的内存,
我个人使用make -jn
,其中n是“核心数”+ 1。
然而,我不能给出一个科学的解释:我见过很多人使用相同的设置,他们给了我相当不错的结果。
无论如何,你必须小心,因为一些生产链只是不兼容的--jobs
选项,并可能导致意想不到的结果。 如果您遇到奇怪的依赖性错误,只需尝试使用--jobs
。
最终,你将不得不做一些基准testing来确定用于构build的最佳数字,但请记住,CPU不是唯一重要的资源!
例如,如果你的构build依赖于磁盘,那么在多核系统上产生大量作业可能实际上会比较慢 ,因为磁盘将不得不做额外的工作,来回移动磁盘头来提供全部服务不同的作业(取决于很多因素,如操作系统如何处理磁盘caching,由磁盘支持本地命令排队等)。
然后你就有了“真正”的内核与超线程。 每个超线程的产卵作业可能会也可能不会受益。 再次,你必须找出基准。
我不能说我已经专门尝试了#core + 1 ,但是在我们的系统上(Intel i7 940,4个超线程内核,大量的RAM和VelociRaptor驱动器)以及我们的系统(大规模的C ++构build,交替使用CPU和I / O绑定),-j4和-j8之间几乎没有什么区别。 (可能要好15%,但是差不多两倍)
如果我要去吃午饭,我会用-j8,但是如果我想用我的系统来做任何其他事情,那么我会用一个较小的数字。 🙂
我刚买了一台富士康M / B和4GB G技能的Athlon II X2 Regor处理器。
我把“cat / proc / cpuinfo”和“free”放在这个末尾,这样其他人就可以看到我的规格了。 这是双核Athlon II X2与4GB的RAM。
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
);
并复制默认内核的configuration( cp /usr/src/linux/.config .
);
使用make oldconfig
来准备3.2.46内核configuration;
然后用-jX的各种咒语跑。
我通过在时间命令之后发出make来testing每次运行的时间,例如'time make -j2'。 在每次运行之间,我运行rm -rf linux-3.2.46树并重新提取它,将默认的/usr/src/linux/.config复制到目录中,运行make oldconfig,然后再次执行“make -jX”testing。
简单的“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$
如上所述,但与make -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
根据我的经验,添加额外工作时必须有一些性能优势。 这只是因为磁盘I / O是CPU之外的瓶颈之一。 然而,由于与所使用的磁盘的核心数量和types高度相关联,所以额外作业的数量并不容易。
就像一个参考:
来自LKD的 Spawning Multiple Build Jobs
部分:
其中n是产卵工作的数量。 通常的做法是每个处理器产生一个或两个作业。 例如,在一个双处理器机器上,可能会这样做
$ make j4