web-dev-qa-db-de.com

Kompilieren mit g ++ unter Verwendung mehrerer Kerne

Kurze Frage: Wie lautet das Compiler-Flag, damit g ++ mehrere Instanzen von sich erzeugen kann, um große Projekte schneller zu kompilieren (z. B. jeweils 4 Quelldateien für eine Multicore-CPU)?

Danke vielmals.

156
bsofman

Sie können dies mit make machen - mit gnu make ist es das Flag -j (dies wird auch auf einem Einzelprozessor-Rechner hilfreich sein).

Zum Beispiel, wenn Sie 4 parallele Aufträge von make erhalten möchten:

make -j 4

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

gcc -pipe

Dadurch werden die Kompilierungsschritte in einer Pipeline dargestellt, wodurch auch die Kerne beschäftigt werden.

Wenn Sie auch weitere Maschinen zur Verfügung haben, können Sie distcc auschecken, das dann auch von den Farmcomputern kompiliert wird.

217
frankodwyer

Es gibt kein solches Flag, und wenn man gegen die Unix-Philosophie verstößt, dass jedes Werkzeug nur eine Funktion ausführt und gut ausführt. Das Erzeugen von Compiler-Prozessen ist konzeptionell die Aufgabe des Build-Systems. Was Sie wahrscheinlich suchen, ist das Flag -j (Jobs) für GNU, a la

machen Sie -j4

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

37

Leute haben make erwähnt, aber bjam unterstützt auch ein ähnliches Konzept. Mit bjam -jx wird bjam angewiesen, gleichzeitig x-Befehle aufzubauen.

Wir verwenden dieselben Build-Skripts unter Windows und Linux, und mit dieser Option halbieren wir die Build-Zeiten auf beiden Plattformen. Nett.

11
MattyT

make erledigt dies für Sie. Untersuchen Sie die Schalter -j und -l in der Manpage. Ich glaube nicht, dass g++ parallelisierbar ist.

8
rmeador

mit distcc können Sie Kompilierungen nicht nur auf dem aktuellen Computer verteilen, sondern auch auf anderen Computern in einer Farm, die distcc installiert haben.

5
Jason

Ich bin nicht sicher über g ++, aber wenn Sie GNU Make verwenden, dann erlaubt "make -j N" (wobei N die Anzahl der von make erstellten Threads ist), dass make mehrere g ++ - Jobs gleichzeitig ausführen kann Zeit (solange die Dateien nicht voneinander abhängen).

2
Andy

Wenn Sie make verwenden, geben Sie -j aus. 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 ein Skript erstellen oder die Anzahl der verfügbaren Kerne ermitteln möchten (abhängig von Ihrer Umgebung, und wenn Sie in vielen Umgebungen laufen, kann sich dies sehr ändern), können Sie die allgegenwärtige Python-Funktion cpu_count() verwenden:

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 sich fragen, warum 1.5 ich in einem Kommentar oben das artless-noise des Benutzers zitiere:

Die Zahl 1.5 liegt an dem festgestellten E/A-gebundenen Problem. Es ist eine Faustregel. Etwa 1/3 der Jobs warten auf E/A, sodass die verbleibenden Jobs die verfügbaren Kerne verwenden. Eine Nummer größer als die Kerne ist besser und Sie können sogar bis zu 2x hochgehen.

2
Havok

GNU parallel

Ich machte einen synthetischen Compilier-Benchmark und konnte mich nicht die Mühe machen, ein Makefile zu schreiben, also benutzte ich:

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 Befehle aus, die ausgeführt werden, um eine Vorstellung vom Fortschritt zu erhalten
  • --will-cite entfernt die Anforderung, die Software zu zitieren, wenn Sie Ergebnisse mit dieser 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 -P kann auch Jobs parallel ausführen, aber es ist etwas unpraktischer, die Erweiterungsmanipulation auszuführen oder mehrere Befehle auszuführen: Aufruf mehrerer Befehle über xargs

Parallele Verlinkung wurde gefragt: Kann gcc beim Verlinken mehrere Kerne verwenden?

TODO: Ich denke, ich habe irgendwo gelesen, dass die Kompilierung auf die Matrixmultiplikation reduziert werden kann. Daher ist es möglicherweise 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.