web-dev-qa-db-fra.com

Compiler avec g ++ en utilisant plusieurs cœurs

Question rapide: quel est l'indicateur de compilation permettant à g ++ de créer plusieurs instances pour lui-même afin de compiler des projets volumineux plus rapidement (par exemple, 4 fichiers sources à la fois pour un processeur multicœur)?

Merci beaucoup.

156
bsofman

Vous pouvez faire cela avec make - avec gnu, make c'est le drapeau -j (cela aidera aussi sur une machine à un seul processeur).

Par exemple, si vous voulez 4 tâches parallèles de make:

make -j 4

Vous pouvez également exécuter gcc dans un tuyau avec 

gcc -pipe

Cela acheminera les étapes de compilation, ce qui aidera également à garder les cœurs occupés.

Si vous avez également des machines supplémentaires disponibles, vous pouvez vérifier distcc , qui compilera également celles-ci.

217
frankodwyer

Il n’existe pas de drapeau de ce type, et l’un contre l’autre va à l’encontre de la philosophie Unix selon laquelle chaque outil n’exécute qu’une seule fonction. Les processus de compilation générés sont conceptuellement le travail du système de construction. Ce que vous cherchez probablement, c’est le drapeau -j (jobs) à GNU

make -j4

Ou vous pouvez utiliser pmake ou des systèmes similaires de fabrication parallèle.

37
Mihai Limbășan

Les gens ont mentionné make mais bjam soutient également un concept similaire. Utiliser bjam -jx indique à bjam de créer jusqu'à x commandes concurrentes.

Nous utilisons les mêmes scripts de compilation sous Windows et Linux et cette option divise par deux notre temps de génération sur les deux plates-formes. Agréable.

11
MattyT

make le fera pour vous. Examinez les commutateurs -j et -l dans la page de manuel. Je ne pense pas que g++ est parallélisable.

8
rmeador

distcc peut également être utilisé pour distribuer des compilations non seulement sur la machine actuelle, mais également sur d'autres machines d'une batterie sur laquelle distcc est installé.

5
Jason

Je ne suis pas sûr de g ++, mais si vous utilisez GNU, Make "make -j N" (où N est le nombre de threads que make peut créer) permettra à make d'exécuter plusieurs travaux g ++ de la même manière. temps (tant que les fichiers ne dépendent pas les uns des autres).

2
Andy

Si vous utilisez make, lancez avec -j. De man make:

  -j [jobs], --jobs[=jobs]
       Specifies the number of jobs (commands) to run simultaneously.  
       If there is more than one -j option, the last one is effective.
       If the -j option is given without an argument, make will not limit the
       number of jobs that can run simultaneously.

Et plus particulièrement, si vous souhaitez créer un script ou identifier le nombre de cœurs disponibles (en fonction de votre environnement et de votre exécution dans de nombreux environnements, cela peut beaucoup changer), vous pouvez utiliser la fonction Python omniprésente cpu_count():

https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count

Comme ça:

make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')

Si vous vous demandez pourquoi 1.5, je citerai un commentaire d'artless-noise dans un commentaire ci-dessus:

Le nombre 1.5 est dû au problème lié aux entrées/sorties signalé. C'est une règle de base. Environ le tiers des tâches attendront des E/S, les tâches restantes utiliseront donc les cœurs disponibles. Un nombre supérieur au nombre de cœurs est meilleur et vous pouvez même aller jusqu'à 2x.

2
Havok

GNU parallèle

Je faisais une référence de compilation synthétique et je ne pouvais pas être dérangé pour écrire un Makefile, alors j'ai utilisé:

Sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"

Explication:

  • {.} prend l'argument d'entrée et supprime son extension
  • -t imprime les commandes en cours d'exécution pour nous donner une idée de la progression
  • --will-cite supprime la demande de citer le logiciel si vous publiez des résultats en l'utilisant ...

parallel est tellement pratique que je pourrais même faire une vérification d'horodatage moi-même:

ls | grep -E '\.c$' | parallel -t --will-cite "\
  if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
    gcc -c -o '{.}.o' '{}'
  fi
"

xargs -P peut également exécuter des travaux en parallèle, mais il est un peu moins pratique de manipuler des extensions ou d'exécuter plusieurs commandes avec ce dernier: Appel de plusieurs commandes via xargs

La liaison parallèle a été posée à l'adresse: gcc peut-il utiliser plusieurs cœurs lors de la liaison?

TODO: Je pense avoir lu quelque part que la compilation peut être réduite à la multiplication matricielle. Il est donc peut-être aussi possible d'accélérer la compilation d'un seul fichier pour les gros fichiers. Mais je ne trouve pas de référence maintenant.

Testé sous Ubuntu 18.10.