Définition automatique du drapeau jobs (- j) pour une machine multicore?
j'ai un Makefile sur une machine qui a une tonne de noyaux dedans, mais je semble toujours oublier d'écrire -jX
lors de la compilation de mon projet et il prend beaucoup plus de temps qu'il ne devrait.
y a-t-il un moyen pour que je puisse mettre le drapeau -j
à travers une variable d'environnement ou un autre fichier de configuration persistant de sorte que make exécutera automatiquement plusieurs tâches en parallèle sur cette machine?
10 réponses
il apparaît que la variable d'environnement MAKEFLAGS
peut passer les drapeaux qui font partie de chaque make
lancé (au moins pour GNU make). Je n'ai pas eu beaucoup de chance avec moi-même, mais il pourrait être possible d'utiliser des -l
plutôt que -j
pour exécuter automatiquement autant d'emplois que sont appropriés pour le nombre de cœurs disponibles.
je suppose que vous utilisez Linux. C'est de mon ~/.bashrc
# parallel make
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo`
alias pmake='time nice make -j$NUMCPUS --load-average=$NUMCPUS'
exemple d'utilisation
samm@host src> echo $NUMCPUS
8
samm@host src> pmake
devient time nice make -j8 --load-average=8
.
pour répondre à votre question spécifique sur la mise en place d'un Makefile
, Je ne trouve pas pratique de saupoudrer cette logique sur mes Makefiles. Mettre ceci dans un Makefile de haut niveau n'est pas non plus une bonne solution puisque je construis souvent à partir de sous-répertoires et que je souhaite construire en parallèle ainsi. Cependant, si vous avez une hiérarchie des sources assez uniforme, cela peut fonctionner pour vous.
comme Jérémie Willcock a dit, utilisez MAKEFLAGS
, Mais voici comment faire:
export MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
ou vous pouvez définir une valeur fixe comme ceci:
export MAKEFLAGS="-j 8"
si vous voulez vraiment augmenter la performance, vous devez utiliser ccache
en ajoutant quelque chose comme ce qui suit à votre Makefile
:
CCACHE_EXISTS := $(shell ccache -V)
ifdef CCACHE_EXISTS
CC := ccache $(CC)
CXX := ccache $(CXX)
endif
je fais habituellement ceci comme suit dans mes scripts bash:
make -j$(nproc)
vous pouvez ajouter une ligne à votre Makefile similaire à la suivante:
NUMJOBS=${NUMJOBS:-" -j4 "}
puis Ajouter une ligne ${NUMJOBS}
dans vos règles, ou l'ajouter dans un autre Makefile
var (comme MAKEFLAGS
). Ceci utilisera le NUMJOBS envvar, s'il existe; s'il n'existe pas, utilisez automatiquement -j4
. Vous pouvez l'accorder ou le renommer à votre goût.
(N.B.: personnellement, je préférerais que la valeur par défaut soit -j1
ou ""
, surtout si elle va pour être distribué à d'autres, parce que même si j'ai plusieurs noyaux aussi, je compile sur de nombreuses plateformes différentes, et oublie souvent de dis -capable le réglage -jX
.)
les alias ne sont pas développés dans les scripts . Il est préférable de créer un script séparé make
et de le placer dans l'un des répertoires $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` "$@"
sur Ubuntu 16.4 en utilisant tous les cœurs CPU:
export MAKEFLAGS='-j$(nproc)'
ou
export MAKEFLAGS='-j 2'
Jusqu'à l'année dernière, vous pouviez le faire dans votre makefile: (GNU make tested)
MAKEFLAGS += "-j$(NUM_CORES) -l$(NUM_CORES)
(où NUM_PPROCS
est calculé ou ensemble selon l'une des nombreuses autres réponses ici) Et, bam! vous avez la construction multi-processus en cours.
étant donné que cela a cessé de fonctionner, la meilleure chose que j'ai pu trouver est celle-ci, où le makefile s'appelle lui-même, mais avec -jX
et -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
au début d'un Makefile:
MAKEFLAGS+="j"
il ne prendra pas d'arguments numériques pour toute version de GNU Make Avant 4.2 .
s'il vous arrive d'avoir des jobs qui manquent de mémoire, vous pouvez les faire exécuter un seul à la fois avec flock
de util-linux-ng. Par exemple, un utilitaire convert
d'ImageMagick utilisera toutes les ressources qu'il peut obtenir lorsqu'il est utilisé pour optimiser les images selon Recommandations de Google , il n'y a donc pas de raison de le faire fonctionner en parallèle.
%.min.jpg: %.jpg
@flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip $@
il est important de définir un long temps d'attente car make exécutera encore la plupart de ces commandes en parallèle. Par conséquent, les temps d'attente doit être comme le plus profond de la file d'attente temps d'exécution. Si vous avez huit cœurs, et huit grandes images prennent une minute pour optimiser, vous devez régler le temps d'attente à au moins une minute.
Avec des centaines de cœurs et d'énormes images, six cents secondes fixé ci-dessus pourrait ne pas être suffisant.