Автоматическая установка заданий (-j) для многоядерной машины?
У меня есть Makefile на машине, в которой есть тонны ядер, но я всегда забываю писать -jX
при компиляции моего проекта, и это занимает больше времени, чем нужно.
Можно ли установить флаг -j
через переменную среды или какой-либо другой файл постоянной конфигурации, чтобы make автоматически выполнял несколько заданий параллельно на этой машине?
Ответы
Ответ 1
Кажется, что переменная среды MAKEFLAGS
может передавать флаги, которые являются частью каждого запуска make
(по крайней мере, для GNU make). Мне не повезло с этим самим, но вместо -j
можно было бы использовать -l
, чтобы автоматически запускать столько заданий, сколько подходит для количества доступных вам ядер.
Ответ 2
Я предполагаю, что вы используете Linux. Это от моего ~/.bashrc
# parallel make
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
alias pmake='time nice make -j$NUMCPUS --load-average=$NUMCPUS'
использование образца
[email protected] src> echo $NUMCPUS
8
[email protected] src> pmake
становится time nice make -j8 --load-average=8
.
Чтобы ответить на ваш конкретный вопрос о том, чтобы поместить это в Makefile
, я не считаю целесообразным посыпать эту логику во всех своих файлах Makefile. Включение этого в верхний уровень Makefile также не является отличным решением, поскольку я часто создаю его из подкаталогов и хочу строить их параллельно. Однако, если у вас довольно ровная иерархия источников, она может работать для вас.
Ответ 3
Как сказал Иеремия Уилкок, используйте 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
Ответ 4
Я обычно делаю это следующим образом в моих сценариях bash:
make -j$(nproc)
Ответ 5
Вы можете добавить строку в свой файл Makefile, как показано ниже:
NUMJOBS=${NUMJOBS:-" -j4 "}
Затем добавьте строку ${NUMJOBS}
в свои правила или добавьте ее в другую Makefile
var (например, MAKEFLAGS
). Это будет использовать NUMJOBS envvar, если он существует; если это не так, автоматически используйте -j4
. Вы можете настроить или переименовать его по своему вкусу.
(NB: Лично я предпочел бы, чтобы по умолчанию было -j1
или ""
, особенно если оно будет распространено среди других, потому что, хотя у меня есть несколько ядер, я компилирую на разных платформах и часто забывайте отключить настройку -jX
.)
Ответ 6
Псевдонимы не распространяются внутри скриптов. Лучше создать отдельный make
script и поместить его в один из каталогов $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` "[email protected]"
Ответ 7
До тех пор, пока в прошлом году вы не смогли сделать это в своем make файле: (GNU make test)
MAKEFLAGS += "-j$(NUM_CORES) -l$(NUM_CORES)
(где NUM_PPROCS
вычисляется или задается в соответствии с одним из многих других ответов здесь) И, bam! у вас многоэтапное строительство.
Учитывая, что это перестало работать, самое лучшее, что я мог придумать, это то, где makefile вызывает себя, но с -jX
и -lX
.
# add parallelism equal to number of cores every time.
# it seems that adding -jX to MAKEFLAGS directly doesn't work any more.
# included some "random" strings to ensure uniqueness
ifneq ($(PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB),done)
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) [email protected] PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB=done
# the match for this else is at the end of the file
else
##### rest of makefile here #####
all: ...
...
other_target: ...
...
##### etc. #####
endif
Ответ 8
В Ubuntu 16.4 с использованием всех ядер процессора:
export MAKEFLAGS='-j$(nproc)'
или
export MAKEFLAGS='-j 2'
Ответ 9
В начале файла Makefile:
MAKEFLAGS+="j"
Он не будет принимать числовые аргументы для любой версии GNU Make до 4.2.
Если у вас закончилось некоторое количество заданий на работу, вы можете заставить их запускать только один за раз с помощью flock
из util-linux-ng. Например, утилита convert
от ImageMagick будет использовать все ресурсы, которые она может получить при использовании оптимизировать изображения согласно рекомендациям Google, так что нет чтобы он работал параллельно.
%.min.jpg: %.jpg
@flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip [email protected]
Важно установить длительное время ожидания, так как make все равно будет выполнять большинство этих команд параллельно. Поэтому время ожидания должно быть таким, как самое глубокое время выполнения очереди. Если у вас восемь ядер и восемь больших изображений занимают минуту, чтобы оптимизировать, вы должны установить время ожидания как минимум на минуту.
С сотнями ядер и огромными изображениями, установленных на шестьсот секунд, может быть недостаточно.
Ответ 10
Я бы просто положил
alias make='make -j'
в ~/.profile
или ~/.bashrc
.
В соответствии с manual:
Если после опции "-j нет ничего похожего на целое число, количество вакансий не ограничено.