Автоматическая установка флага задания (- j) для многоядерной машины?



У меня есть Makefile на машине, которая имеет тонну ядер в нем, но я всегда, кажется, забываю писать -jX при компиляции моего проекта и это занимает гораздо больше времени, чем это должно быть.

есть ли способ я могу установить -j флаг через переменную окружения или какой-либо другой постоянный файл конфигурации, чтобы make автоматически выполнял несколько заданий параллельно на этой машине?

207   10  

10 ответов:

получается, что MAKEFLAGS переменная окружения может передавать флаги, которые являются частью каждого make run (по крайней мере, для GNU make). Мне самому не очень повезло с этим, но можно было бы использовать -l, а не -j автоматически запускать столько заданий, сколько соответствует количеству доступных ядер.

Я предполагаю, что вы используете 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, Я не считаю практичным разбрызгивать эту логику по всем моим Makefiles. Помещение этого в Makefile верхнего уровня также не является отличным решением, так как я часто строю из подкаталогов и хочу строить их параллельно. Однако, если у вас есть довольно плоский исходная иерархия, она может работать для вас.

как сказал Иеремия Уиллкок, используйте 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 envvar, если он существует; если это не так, автоматически использовать -j4. Вы можете настроить или переименовать его на свой вкус.

(N. B.: лично я бы предпочел, чтобы по умолчанию было -j1 или "", особенно если он будет распространен среди других, потому что хотя у меня есть несколько ядер также, я компилирую на разных платформах, и часто забываю СОП-возможность -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` "$@"

на Ubuntu 16.4 с использованием всех ядер процессора:

export MAKEFLAGS='-j$(nproc)'

или

export MAKEFLAGS='-j 2'

пока где-то в прошлом году вы не могли сделать это в своем makefile: (GNU make tested)

MAKEFLAGS += "-j$(NUM_CORES) -l$(NUM_CORES)

(где NUM_PPROCS рассчитывается или устанавливается в соответствии с одним из многих других ответов здесь) и, бац! у вас есть многопроцессное здание происходит.

учитывая, что это перестало работать, лучшее, что я мог придумать, это то, где 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) $@ 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

В начале файла 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 $@

важно установить долгое время ожидания, потому что make все равно будет выполнять большинство этих команд параллельно. Поэтому время ожидания должно быть таким же, как самое глубокое время выполнения очереди. Если у вас есть восемь ядер и восемь больших изображений занимают минуту для оптимизации, вы должны установить время ожидания не менее минуты.

С сотнями ядер и огромными изображениями, шестьсот секунд, установленных выше, может быть недостаточно.

Я бы просто поставил

alias make='make -j'

на ~/.profile или ~/.bashrc.

По словам руководство:

Если после опции '- j ' нет ничего похожего на целое число, то количество слотов заданий не ограничено.

    Ничего не найдено.

Добавить ответ:
Отменить.