Kompilieren mit g ++ mit mehreren Kernen


174

Kurze Frage: Was ist das Compiler-Flag, mit dem g ++ mehrere Instanzen von sich selbst erzeugen kann, um große Projekte schneller zu kompilieren (z. B. 4 Quelldateien gleichzeitig für eine Multi-Core-CPU)?


Wird es wirklich helfen? Alle meine Kompilierungsjobs sind E / A-gebunden und nicht CPU-gebunden.
Brian Knoblauch

5
Selbst wenn sie E / A-gebunden sind, können Sie wahrscheinlich die E / A-Last höher halten, wenn die CPU-schweren Bits auftreten (mit nur einer g ++ - Instanz kommt es zu Flauten) und möglicherweise E / A-Effizienz erzielen, wenn der Scheduler mehr Auswahlmöglichkeiten hat was als nächstes von der Festplatte zu lesen. Ich habe die Erfahrung gemacht, dass ein umsichtiger Umgang mit make -jfast immer zu Verbesserungen führt.
Flexo

1
@BrianKnoblauch Aber auf meinem Computer (real oder in VirtualBox), der an die CPU gebunden ist, habe ich festgestellt, dass die CPU beim Kompilieren über den Befehl 'top' ausgelastet ist.
宝剑

1
Selbst wenn sie E / A-gebunden sind, können wir die gcc-Flagge '-pipe' verwenden, um Schmerzen zu lindern.
宝剑

Antworten:


240

Sie können dies mit make tun - mit gnu make ist es das Flag -j (dies hilft auch auf einem Einprozessor-Computer).

Zum Beispiel, wenn Sie 4 parallele Jobs von make möchten:

make -j 4

Sie können gcc auch in einer Pipe mit ausführen

gcc -pipe

Dadurch werden die Kompilierungsphasen weitergeleitet, wodurch auch die Kerne beschäftigt bleiben.

Wenn Sie auch zusätzliche Maschinen zur Verfügung haben, können Sie sich distcc ansehen , das auch Kompilierungen für diese bewirtschaftet.


36
Ihre -j-Zahl sollte das 1,5-fache der Anzahl Ihrer Kerne betragen.
Mark Beckwith

2
Vielen Dank. Ich habe immer wieder versucht, "-j #" über CFLAGS / CPPFLAGS / CXXFLAGS an gcc zu übergeben. Ich hatte völlig vergessen, dass "-j #" ein Parameter für GNU make (und nicht für GCC) war.
Chris

33
Warum muss die Option -j für GNU Make das 1,5-fache der Anzahl der CPU-Kerne betragen?
Bitek

28
Die Zahl 1,5 ist auf das festgestellte Problem mit der E / A-Bindung zurückzuführen . Es ist eine Faustregel. Etwa 1/3 der Jobs warten auf E / A, sodass die verbleibenden Jobs die verfügbaren Kerne verwenden. Eine Zahl größer als die Kerne ist besser und Sie könnten sogar bis zu 2x gehen . Siehe auch: Gnu machen -jArgumente
Kunstloses Rauschen

4
@JimMichaels Dies kann daran liegen, dass Abhängigkeiten in Ihrem Projekt schlecht festgelegt sind (ein Ziel beginnt mit der Erstellung, auch wenn seine Abhängigkeiten noch nicht bereit sind), sodass nur eine sequentielle Erstellung erfolgreich ist.
Antonio

42

Es gibt kein solches Flag, und wenn ein Flag gegen die Unix-Philosophie verstößt, dass jedes Tool nur eine Funktion ausführt und diese gut ausführt. Das Laichen von Compilerprozessen ist konzeptionell die Aufgabe des Build-Systems. Was Sie wahrscheinlich suchen, ist das Flag -j (jobs) für GNU make, a la

mache -j4

Oder Sie können pmake oder ähnliche parallele Make-Systeme verwenden.



3
"Unix-Pedanterie ist nicht hilfreich" Gut, dass es damals keine Pedanterie war, anonymer Editor. Zurückgerollt. Rezensenten achten bitte mehr auf das, was Sie tun.
Leichtigkeitsrennen im Orbit

12

Die Leute haben ein ähnliches Konzept erwähnt make, bjamunterstützen es aber auch. Verwenden von bjam -jxAnweisungen bjam, um xgleichzeitige Befehle aufzubauen .

Wir verwenden dieselben Build-Skripte unter Windows und Linux. Mit dieser Option halbieren wir unsere Build-Zeiten auf beiden Plattformen. Nett.


9

makewerde das für dich tun. Untersuchen Sie die -jund -lSchalter in der Manpage. Ich denke nicht, dass g++es parallelisierbar ist.


+1 für die Erwähnung der -lOption (startet keinen neuen Job, es sei denn, alle vorherigen Jobs wurden beendet). Andernfalls scheint der Linker-Job nicht mit allen erstellten Objektdateien zu beginnen (da einige Kompilierungen noch laufen), sodass der Linker-Job fehlschlägt.
NGI

8

Wenn Sie make verwenden, geben Sie ein Problem mit -j. Von 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.

Und vor allem, wenn Sie die Anzahl der verfügbaren Kerne skripten oder identifizieren möchten (abhängig von Ihrer Umgebung und wenn Sie in vielen Umgebungen ausgeführt werden, kann sich dies stark ändern), können Sie die allgegenwärtige Python-Funktion verwenden cpu_count():

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

So was:

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

Wenn Sie fragen, warum 1.5ich den Benutzer artless-Noise in einem Kommentar oben zitiere:

Die Zahl 1,5 ist auf das festgestellte Problem mit der E / A-Bindung zurückzuführen. Es ist eine Faustregel. Etwa 1/3 der Jobs warten auf E / A, sodass die verbleibenden Jobs die verfügbaren Kerne verwenden. Eine Zahl größer als die Kerne ist besser und Sie könnten sogar bis zu 2x gehen.


5
Die meisten Linux-Benutzer werden wahrscheinlich das kürzere bevorzugen: make -j`nproc` mit nprocin GNU Coreutils.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Wenn Sie eine SSD verwenden, ist die E / A kein so großes Problem. make -j $(( $(nproc) + 1 ))Um auf Ciros Kommentar oben aufzubauen, können Sie Folgendes tun: (Stellen Sie sicher, dass Sie Leerzeichen dort platzieren, wo ich sie habe).
Ed K

Netter Vorschlag mit Python, auf Systemen, auf denen nproces nicht verfügbar ist, z. B. in manylinux1Containern, spart zusätzliche Zeit, indem das Ausführen von yum update/ vermieden wird yum install.
Hacke

7

distcc kann auch verwendet werden, um Kompilierungen nicht nur auf dem aktuellen Computer, sondern auch auf anderen Computern in einer Farm zu verteilen, auf denen distcc installiert ist.


+1, distcc ist ein nützliches Werkzeug für große Builds im Arsenal.
Flexo

Es sieht so aus, als ob es einige gibt, die auch "wie" distcc funktionieren
rogerdpack

3

Ich bin mir bei g ++ nicht sicher, aber wenn Sie GNU Make verwenden, ermöglicht "make -j N" (wobei N die Anzahl der Threads ist, die make erstellen kann), dass make mehrere g ++ - Jobs gleichzeitig ausführen kann (so lange) da die Dateien nicht voneinander abhängen).


2
nein N ist nicht die Anzahl der Threads! Viele Leute -j Nverstehen das falsch, sagen aber , wie viele Prozesse gleichzeitig erzeugt werden sollen, nicht Threads. Das ist der Grund, warum es nicht so performant ist wie MS cl -MT(wirklich Multithreaded).
Sebi2020

2

GNU parallel

Ich habe einen synthetischen Kompilierungs-Benchmark erstellt und konnte mir nicht die Mühe machen, ein Makefile zu schreiben. Deshalb habe ich Folgendes verwendet:

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

Erläuterung:

  • {.} Nimmt das Eingabeargument und entfernt seine Erweiterung
  • -t druckt die ausgeführten Befehle aus, um uns eine Vorstellung vom Fortschritt zu geben
  • --will-cite Entfernt die Anforderung, die Software zu zitieren, wenn Sie Ergebnisse damit veröffentlichen ...

parallel ist so praktisch, dass ich selbst eine Zeitstempelprüfung durchführen könnte:

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

xargs -PSie können Jobs auch parallel ausführen, es ist jedoch etwas weniger bequem, die Erweiterungsmanipulation durchzuführen oder mehrere Befehle damit auszuführen: Aufrufen mehrerer Befehle über xargs

Die parallele Verknüpfung wurde gefragt unter: Kann gcc beim Verknüpfen mehrere Kerne verwenden?

TODO: Ich glaube, ich habe irgendwo gelesen, dass die Kompilierung auf Matrixmultiplikation reduziert werden kann. Vielleicht ist es auch möglich, die Kompilierung einzelner Dateien für große Dateien zu beschleunigen. Aber ich kann jetzt keine Referenz finden.

Getestet in Ubuntu 18.10.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.