Compiler avec g ++ en utilisant plusieurs cœurs


174

Question rapide: quel est le drapeau du compilateur pour permettre à g ++ de générer plusieurs instances de lui-même afin de compiler plus rapidement de grands projets (par exemple 4 fichiers source à la fois pour un processeur multicœur)?


Cela aidera-t-il vraiment? Tous mes travaux de compilation sont liés aux E / S plutôt qu'au CPU.
Brian Knoblauch le

5
Même s'ils sont liés aux E / S, vous pouvez probablement maintenir la charge d'E / S plus élevée lorsque les bits lourds du processeur se produisent (avec une seule instance g ++, il y aura des accalmies) et éventuellement gagner en efficacité d'E / S si le planificateur a plus de choix sur que lire ensuite sur le disque. Mon expérience a été que l'utilisation judicieuse de make -jaboutit presque toujours à une certaine amélioration.
Flexo

1
@BrianKnoblauch Mais sur ma machine (vraie ou dans VirtualBox), elle est liée au processeur, j'ai trouvé que le processeur est occupé via la commande «top» lors de la compilation.
大 宝剑

1
Même s'ils sont liés aux E / S, nous pouvons utiliser le drapeau de gcc '-pipe' pour réduire la douleur.
大 宝剑

je viens de voir ça dans google: gcc.gnu.org/onlinedocs/libstdc++/manual/…
Jim Michaels

Réponses:


240

Vous pouvez le faire avec make - avec gnu make it est le drapeau -j (cela aidera également sur une machine monoprocesseur).

Par exemple, si vous voulez 4 jobs parallèles de make:

make -j 4

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

gcc -pipe

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

Si vous disposez également de machines supplémentaires, vous pouvez consulter distcc , qui les compilera également.


36
Votre nombre -j doit être 1,5x le nombre de cœurs que vous avez.
Mark Beck avec le

2
Merci. J'ai continué à essayer de passer "-j #" à gcc via CFLAGS / CPPFLAGS / CXXFLAGS. J'avais complètement oublié que "-j #" était un paramètre pour GNU make (et pas pour GCC).
chriv

33
Pourquoi l' option -j de GNU Make doit-elle être égale à 1,5 fois le nombre de cœurs de processeur?
bitek

28
Le nombre 1.5 est dû au problème de liaison d'E / S noté . C'est une règle de base. Environ 1/3 des travaux seront en attente d'E / S, les travaux restants utiliseront donc les cœurs disponibles. Un nombre supérieur aux cœurs est meilleur et vous pouvez même aller jusqu'à 2x . Voir aussi: Gnu make -jarguments
artless noise

4
@JimMichaels Cela peut être dû au fait que les dépendances sont mal définies dans votre projet (une cible commence à se construire même si ses dépendances ne sont pas encore prêtes) de sorte que seule une construction séquentielle aboutit.
Antonio

42

Il n'y a pas de tel drapeau, et en avoir un va à l'encontre de la philosophie Unix qui veut que chaque outil exécute une seule fonction et l'exécute correctement. La création de processus de compilation est conceptuellement le travail du système de construction. Ce que vous recherchez probablement, c'est l'indicateur -j (jobs) pour GNU make, a la

faire -j4

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



3
"Le pédantisme Unix n'est pas utile" Heureusement que ce n'était pas du pédantisme alors, éditeur anonyme. Annulées. Les évaluateurs doivent prêter plus d'attention à ce que vous faites.
Courses de légèreté en orbite

12

Les gens ont mentionné makemais bjamsoutiennent également un concept similaire. L'utilisation bjam -jxindique à bjam de créer xdes commandes simultanées.

Nous utilisons les mêmes scripts de construction sur Windows et Linux et l'utilisation de cette option réduit de moitié nos temps de construction sur les deux plates-formes. Agréable.


9

makefera cela pour vous. Examinez les commutateurs -jet -ldans la page de manuel. Je ne pense pas que ce g++soit parallélisable.


+1 pour mentionner l' -loption (ne démarre pas un nouvel emploi à moins que tous les emplois précédents ne se terminent) Sinon, il semble que le travail de l'éditeur de liens ne commence pas avec tous les fichiers objets créés (car certaines compilations sont toujours en cours), de sorte que le travail de l'éditeur de liens échoue.
NGI

8

Si vous utilisez make, sortez 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 dont vous disposez (en fonction de votre environnement, et si vous exécutez 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 demandez pourquoi 1.5je citerai l'utilisateur artless-noise dans un commentaire ci-dessus:

Le nombre 1.5 est dû au problème de liaison d'E / S noté. C'est une règle de base. Environ 1/3 des travaux seront en attente d'E / S, les travaux restants utiliseront donc les cœurs disponibles. Un nombre supérieur aux cœurs est meilleur et vous pouvez même aller jusqu'à 2x.


5
La plupart des utilisateurs de Linux préféreront probablement le plus court: make -j`nproc` avec nprocdans GNU Coreutils.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Si vous utilisez un SSD, les E / S ne seront pas autant un problème. Juste pour construire sur le commentaire de Ciro ci-dessus, vous pouvez faire ceci: make -j $(( $(nproc) + 1 ))(assurez-vous de mettre des espaces là où je les ai).
Ed K

Belle suggestion utilisant python, sur les systèmes où il nprocn'est pas disponible, par exemple dans les manylinux1conteneurs, cela permet de gagner du temps en évitant d'exécuter yum update/ yum install.
hoefling

7

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


+1, distcc est un outil utile à avoir dans son arsenal pour les grosses constructions.
Flexo

On dirait qu'il y en a quelques-uns qui fonctionnent "comme" distcc aussi: stackoverflow.com/questions/5374106/distributed-make/…
rogerdpack

3

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


2
no N ist pas le nombre de threads! Beaucoup de gens comprennent mal cela, mais -j Ndisent à make combien de processus à la fois doivent être générés, pas de threads. C'est la raison pour laquelle il n'est pas aussi performant que MS cl -MT(vraiment multithread).
Sebi2020

2

GNU parallèle

Je faisais un benchmark de compilation synthétique et je ne pouvais pas être dérangé d'é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 si 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 -Ppeut également exécuter des tâches en parallèle, mais il est un peu moins pratique de faire la manipulation d'extension ou d'exécuter plusieurs commandes avec: Appel de plusieurs commandes via xargs

La liaison parallèle a été posée à l' adresse suivante : 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, donc il est peut-être également 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é dans Ubuntu 18.10.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.