Makefile 自动设置多核机器的作业(-j)标志?
我在一台有很多内核的机器上有一个Makefile,但在编译我的项目时,我似乎总是忘记编写Makefile 自动设置多核机器的作业(-j)标志?,makefile,parallel-processing,build-script,Makefile,Parallel Processing,Build Script,我在一台有很多内核的机器上有一个Makefile,但在编译我的项目时,我似乎总是忘记编写-jX,而且所花的时间比它应该花的时间长 是否有某种方法可以通过环境变量或其他持久配置文件设置-j标志,以便make在此机器上自动并行执行多个作业?似乎MAKEFLAGS环境变量可以传递作为每个make运行的一部分的标志(至少对于GNU make而言)。我自己在这方面运气不太好,但是可以使用-l而不是-j来自动运行与可用内核数量相应的作业。您可以在make文件中添加一行,如下所示: NUMJOBS=${NUM
-jX
,而且所花的时间比它应该花的时间长
是否有某种方法可以通过环境变量或其他持久配置文件设置
-j
标志,以便make在此机器上自动并行执行多个作业?似乎MAKEFLAGS
环境变量可以传递作为每个make
运行的一部分的标志(至少对于GNU make而言)。我自己在这方面运气不太好,但是可以使用-l
而不是-j
来自动运行与可用内核数量相应的作业。您可以在make文件中添加一行,如下所示:
NUMJOBS=${NUMJOBS:-" -j4 "}
然后在规则中添加一个${NUMJOBS}
行,或者将其添加到另一个Makefile
var(如MAKEFLAGS
)中。如果存在,这将使用NUMJOBS envar;如果不存在,则自动使用-j4
。您可以根据自己的喜好调整或重命名它
(注意:就我个人而言,我更喜欢默认值为
-j1
或“”
,尤其是当它要分发给其他人时,因为尽管我也有多个内核,但我在许多不同的平台上编译,并且经常忘记禁用-jX
设置。)我假设您正在使用Linux。这是我的~/.bashrc
# parallel make
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
alias pmake='time nice make -j$NUMCPUS --load-average=$NUMCPUS'
样本使用
samm@host src> echo $NUMCPUS
8
samm@host src> pmake
变为time nice make-j8--load average=8
为了回答您关于将其放入Makefile
的具体问题,我觉得将此逻辑散布到我的Makefile中并不实际。将其放入顶级Makefile也不是一个很好的解决方案,因为我经常从子目录进行构建,并希望并行构建它们。但是,如果您有一个相当平坦的sourc这可能对你有用。我想
alias make='make -j'
在~/.profile
或~/.bashrc
中
根据报告:
如果在“-j”选项后没有任何看起来像整数的内容,则作业槽的数量没有限制
正如Jeremiah Willcock所说,使用
MAKEFLAGS
,但下面是如何做到的:
export MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
或者您可以设置一个固定值,如下所示:
export MAKEFLAGS="-j 8"
如果您真的想提高性能,您应该使用ccache
,在Makefile
中添加如下内容:
CCACHE_EXISTS := $(shell ccache -V)
ifdef CCACHE_EXISTS
CC := ccache $(CC)
CXX := ccache $(CXX)
endif
。最好创建一个单独的make
脚本,并将其放入$PATH
目录之一:
!/bin/sh
如果[-f/proc/cpuinfo];则
CPU=`grep processor/proc/cpuinfo | wc-l`
其他的
CPU=1
fi
/usr/bin/make-j`expr$cpu+1`“$@”
我通常在bash脚本中执行以下操作:
make -j$(nproc)
直到2016年的某个时候,您可以将其放在您的makefile中:(GNU make tested) (其中,
NUM\u PPROCS
是根据此处许多其他答案中的一个进行计算或设置的)并且,bam!您正在进行多进程构建
考虑到这已经停止工作,我能想到的最好的办法是,makefile调用自己,但是使用-jX
和-lX
。
在Ubuntu 16.4上,使用所有CPU核:
export MAKEFLAGS='-j$(nproc)'
或
在生成文件的开头:
MAKEFLAGS+="j"
对于任何版本的GNU Make,它都不接受数字参数。4.2之后:
对于4.2之前的版本,如果您碰巧有一些作业内存不足,可以使用util linux ng中的flock
使它们一次只运行一个。例如,ImageMagick中的convert
实用程序将使用它使用时可以获得的所有资源,因此并行运行没有意义
%.min.jpg: %.jpg
@flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip $@
%.min.jpg:%.jpg
@flock--等待600 Makefile convert$<-采样系数4:2:0-带$@
设置较长的等待时间很重要,因为make仍将并行运行这些命令中的大多数。因此,等待时间必须与最深的队列执行时间相同。如果您有八个内核,并且八个大映像需要一分钟来优化,则必须将等待时间设置为至少一分钟
有数百个内核和巨大的图像,上面设置的600秒可能还不够。谢谢你的回答。我同意耶利米的回答,因为它更容易理解,而且我根本不需要修改makefile(让下载项目的人随意设置-j标志).尽管如此。据我所知,在去年的某个时候,向MAKEFLAGS添加-jX已经停止了GNU make最新版本的工作。还有其他人经历过这种情况吗?自动检测内核数量的好主意。尽管我最终选择了$((numpus*2))由于这是我通常使用的编译工具。谢谢!%windows系统上的gnu make可以使用%u个处理器%。请注意:
nproc
在某些较旧的发行版上不存在(看着你,RHEL5)。手册页中关于nproc
的附加说明:“打印当前进程可用的处理单元数量,可能少于联机处理器的数量”相关:@sanmai,您需要它用于哪个操作系统?为什么不alias make='make-j$(getconf\u NPROCESSORS\u ONLN)“
为您工作?Alias不够用,因为我需要发布Makefile并让它继续工作。我需要这个用于GNU Make 4.1。@Tarunalwanion我的2核机器一个不合格的-j
会在一个大的构建中很快耗尽我的所有内存。不推荐使用。是的,这似乎会在您的计算机上造成一个带有大型Makefile。您可以传递-l
或-j
,但不带参数。请自己尝试:注意传递-l
会禁用负载限制功能,而没有参数的-j
会告诉make
启动无限数量的并行
export MAKEFLAGS='-j 2'
MAKEFLAGS+="j"
MAKEFLAGS+="j2"
%.min.jpg: %.jpg
@flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip $@