不确定单独在一个Makefile中是否可以这样做,但我希望以一种方式编写Makefile,以便尝试在文件中构建任何目标,自动地检测当前系统上的处理器数量并构建并行处理目标数量。
类似下面的“伪代码”示例,但更清洁?
all:
@make -j$(NUM_PROCESSORS) all
或者:
all: .inparallel
... build all here ...
.inparallel:
@make -j$(NUM_PROCESSORS) $(ORIGINAL_TARGET)
在这两种情况下,您只需输入以下内容:
% make all
希望这是有道理的。
更新:仍然希望上面的示例Makefile。对找到进程数并不感兴趣,但对如何在没有-j命令行选项的情况下编写并行构建的makefile感兴趣。
答案 0 :(得分:23)
检测部分将取决于操作系统。这是一个适用于Linux和Mac OS X的片段:
NPROCS:=1
OS:=$(shell uname -s)
ifeq($(OS),Linux)
NPROCS:=$(shell grep -c ^processor /proc/cpuinfo)
endif
ifeq($(OS),Darwin) # Assume Mac OS X
NPROCS:=$(shell system_profiler | awk '/Number Of CPUs/{print $4}{next;}')
endif
要使其正常工作,您可能需要重新调用make。那你的问题是阻止无限递归。您可以通过使用两个makefile(第一个仅重置-j
值)来管理它,但可能会对它进行精细化。
答案 1 :(得分:7)
我刚把它添加到我的Makefile的顶部。它允许创建任意数量的作业,但尝试将负载平均值保持在cpu核心数之下。
MAKEFLAGS+="-j -l $(shell grep -c ^processor /proc/cpuinfo) "
请注意,这是特定于Linux的。
答案 2 :(得分:6)
在读了LDD3第2章并阅读dmckee的回答之后,我想出了使用两个makefile的不太好的答案(我更喜欢只有一个)。
$ cat Makefile
MAKEFLAGS += -rR --no-print-directory
NPROCS := 1
OS := $(shell uname)
export NPROCS
ifeq ($J,)
ifeq ($(OS),Linux)
NPROCS := $(shell grep -c ^processor /proc/cpuinfo)
else ifeq ($(OS),Darwin)
NPROCS := $(shell system_profiler | awk '/Number of CPUs/ {print $$4}{next;}')
endif # $(OS)
else
NPROCS := $J
endif # $J
all:
@echo "running $(NPROCS) jobs..."
@$(MAKE) -j$(NPROCS) -f Makefile.goals $@
%:
@echo "building in $(NPROCS) jobs..."
@$(MAKE) -j$(NPROCS) -f Makefile.goals $@
$ cat Makefile.goals
MAKEFLAGS += -rR --no-print-directory
NPROCS ?= 1
all: subgoal
@echo "$(MAKELEVEL) nprocs = $(NPROCS)"
subgoal:
@echo "$(MAKELEVEL) subgoal"
您对此解决方案有何看法?
我看到的好处是人们仍然要键入make
来构建。因此,没有一些“驱动程序”脚本执行NPROCS
和make -j$(NPROCS)
工作,人们将不得不知道而不是输入make。
缺点是您必须明确使用make -f Makefile.goals
才能进行串行构建。而且我不确定如何解决这个问题...
更新:在上面的代码段中添加了$ J.似乎工作很顺利。即使它的两个makefile而不是一个,它仍然非常无缝和有用。
答案 3 :(得分:6)
这就是我的目标:
ifeq ($(OS),Linux)
NUMPROC := $(shell grep -c ^processor /proc/cpuinfo)
else ifeq ($(OS),Darwin)
NUMPROC := $(shell sysctl hw.ncpu | awk '{print $$2}')
endif
# Only take half as many processors as available
NUMPROC := $(shell echo "$(NUMPROC)/2"|bc)
ifeq ($(NUMPROC),0)
NUMPROC = 1
endif
答案 4 :(得分:5)
我会跳过$(NPROCS)
检测内容,但是这里是你如何在一个Makefile
中执行此操作(这可能是GNU Make特定的,但这看起来像你正在运行的变种):
ifeq ($(NPROCS),)
# Code to set NPROCS...
%:
$(MAKE) -j$(NPROCS) NPROCS=$(NPROCS)
else
# All of your targets...
endif
请参阅Defining Last-Resort Default Rules中的Overriding Part of Another Makefile和GNU Make Manual。
答案 5 :(得分:2)
如果您希望它是自动的,那么您可以在主目录的.bashrc
中覆盖典型的make命令,使其成为自身的别名。
示例:
alias make="make -j"
或者你可以这样做:
alias jmake="make -j"
如果你不想覆盖它,但想要一种快速,简单(和令人难忘)的方式来并行运行make。
答案 6 :(得分:1)
如果我正确阅读了问题,目标是尽可能并行化构建过程。 make
手册页说明了以下内容
如果在没有参数的情况下给出-j选项,make将不会限制可以同时运行的作业数。
这基本上不是你想要的解决方案吗?如果您的Makefile有足够的并行目标,那么您将使用所有CPU,如果目标不是并行的,那么-j
选项将无济于事。