我在一台有大量内核的机器上有一个 Makefile,但我似乎总是-jX
在编译我的项目时忘记写,而且它花费的时间比它应该的要长。
有什么方法可以-j
通过环境变量或其他持久性配置文件设置标志,以便 make 自动在这台机器上并行执行多个作业?
我在一台有大量内核的机器上有一个 Makefile,但我似乎总是-jX
在编译我的项目时忘记写,而且它花费的时间比它应该的要长。
有什么方法可以-j
通过环境变量或其他持久性配置文件设置标志,以便 make 自动在这台机器上并行执行多个作业?
我假设您使用的是 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
.
要回答您关于将其放入 a 的具体问题Makefile
,我认为将这个逻辑散布在我的 Makefile 中是不切实际的。将其放入顶级 Makefile 也不是一个很好的解决方案,因为我经常从子目录构建并希望并行构建它们。但是,如果您有一个相当平坦的源层次结构,它可能对您有用。
似乎MAKEFLAGS
环境变量可以传递作为每次make
运行一部分的标志(至少对于 GNU make)。我自己对此并没有太多运气,但是可能可以使用-l
而不是-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
我通常在我的 bash 脚本中这样做:
make -j$(nproc)
您可以在 Makefile 中添加类似于以下内容的行:
NUMJOBS=${NUMJOBS:-" -j4 "}
然后${NUMJOBS}
在您的规则中添加一行,或将其添加到另一个Makefile
var(如MAKEFLAGS
)中。这将使用 NUMJOBS 环境变量(如果存在);如果没有,自动使用-j4
. 您可以根据自己的喜好对其进行调整或重命名。
(注意:就我个人而言,我更喜欢默认设置为-j1
or ""
,尤其是当它要分发给其他人时,因为虽然我也有多个内核,但我在许多不同的平台上编译,并且经常忘记禁用该-jX
设置。 )
别名不会在脚本内展开。最好创建一个单独的make
脚本并将其放入以下$PATH
目录之一:
#!/bin/sh
if [ -f /proc/cpuinfo ]; then
CPUS=`grep processor /proc/cpuinfo | wc -l`
else
CPUS=1
fi
/usr/bin/make -j`expr $CPUS + 1` "$@"
直到 2016 年的某个时候,你可以把它放在你的 makefile 中:(GNU make 测试)
MAKEFLAGS += "-j$(NUM_CORES) -l$(NUM_CORES)
(NUM_PPROCS
根据此处的许多其他答案之一计算或设置哪里)而且,砰!您正在进行多进程构建。
鉴于这已经停止工作,我能想到的最好的事情就是这个,makefile 调用自己的地方,但是使用-jX
and -lX
。
ifeq ($(PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB),done)
all: ...
...
other_target: ...
...
else
# add parallelism equal to number of cores every time.
# "random" strings are to ensure uniqueness
NUM_CORES ?= $(shell grep -c "vendor_id" /proc/cpuinfo)
MAKEFLAGS +=" -j$(NUM_CORES) -l$(NUM_CORES) "
# for the default target case
parallel_wrapper_default_target_anthsqjkshbeohcbmeuthnoethoaeou:
$(MAKE) PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB=done
# catches everything else
% :
$(MAKE) $@ PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB=done
endif
在使用所有 CPU 内核的 Ubuntu 16.4 上:
export MAKEFLAGS='-j$(nproc)'
或者
export MAKEFLAGS='-j 2'
在 Makefile 的开头:
MAKEFLAGS+="j"
It won't take numeric arguments for any version of GNU Make before 4.2. After 4.2 you can do:
MAKEFLAGS+="j2"
For versions earlier than 4.2 if you happen to have some jobs running out of memory, you could make them run only one at a time with flock
from util-linux-ng. For example, a convert
utility from ImageMagick will use all resources it can get when used to optimize images according to Google's recommendations, so there's no point to have it run in parallel.
%.min.jpg: %.jpg
@flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip $@
It is important to set a long wait time because make will still run most of these commands in parallel. Therefore, wait time must be as such as the deepest queue execution time. If you have eight cores, and eight large images take a minute to optimize, you must set the wait time to at least a minute.
With hundreds of cores and huge images, six hundred seconds set above might not be enough.