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.
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.
"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.
+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():
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.
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).
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).
{.} 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
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.
make -j
fast 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:
Sie können gcc auch in einer Pipe mit ausführen
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.
quelle
-j
ArgumenteEs 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
Oder Sie können pmake oder ähnliche parallele Make-Systeme verwenden.
quelle
Die Leute haben ein ähnliches Konzept erwähnt
make
,bjam
unterstützen es aber auch. Verwenden vonbjam -jx
Anweisungen bjam, umx
gleichzeitige Befehle aufzubauen .Wir verwenden dieselben Build-Skripte unter Windows und Linux. Mit dieser Option halbieren wir unsere Build-Zeiten auf beiden Plattformen. Nett.
quelle
make
werde das für dich tun. Untersuchen Sie die-j
und-l
Schalter in der Manpage. Ich denke nicht, dassg++
es parallelisierbar ist.quelle
-l
Option (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
. Vonman make
: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:
Wenn Sie fragen, warum
1.5
ich den Benutzer artless-Noise in einem Kommentar oben zitiere:quelle
make -j`nproc`
mitnproc
in 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).nproc
es nicht verfügbar ist, z. B. inmanylinux1
Containern, spart zusätzliche Zeit, indem das Ausführen vonyum update
/ vermieden wirdyum 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.
quelle
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).
quelle
-j N
verstehen das falsch, sagen aber , wie viele Prozesse gleichzeitig erzeugt werden sollen, nicht Threads. Das ist der Grund, warum es nicht so performant ist wie MScl -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:
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:xargs -P
Sie 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 xargsDie 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.
quelle