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)?
make -jfast immer zu Verbesserungen führt.
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)?
make -jfast immer zu Verbesserungen führt.
Antworten:
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.
-jArgumente
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.
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.
makewerde das für dich tun. Untersuchen Sie die -jund -lSchalter in der Manpage. Ich denke nicht, dass g++es parallelisierbar ist.
-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.
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.
make -j`nproc` mit nprocin GNU Coreutils.
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).
nproces nicht verfügbar ist, z. B. in manylinux1Containern, spart zusätzliche Zeit, indem das Ausführen von yum update/ vermieden wird yum install.
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.
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).
-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).
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.