Gestern habe ich versucht, das ROOT- Paket aus dem Quellcode zu kompilieren . Da ich es auf einem 6-Kern-Monstercomputer kompilierte, entschied ich mich, mit mehreren Kernen zu bauen make -j 6
. Die Kompilierung verlief zunächst reibungslos und sehr schnell, aber irgendwann make
hing die Verwendung von 100% CPU auf nur einem Kern.
Ich habe ein bisschen gegoogelt und diesen Beitrag in den ROOT- Foren gefunden . Da ich diesen Computer selbst gebaut habe, war ich besorgt, dass ich den Kühlkörper nicht richtig angebracht habe und die CPU überhitzt ist oder so. Leider habe ich hier bei der Arbeit keinen Kühlschrank, in den ich ihn stecken kann ;-)
Ich installierte das lm-sensors
Paket und lief make -j 6
erneut, diesmal mit Überwachung der CPU-Temperatur. Obwohl es hoch wurde (nahe 60 ° C), überschritt es nie die hohe oder kritische Temperatur.
Ich habe versucht zu rennen, habe make -j 4
aber make
irgendwann während des Kompilierens wieder aufgehängt, diesmal an einer anderen Stelle.
Am Ende habe ich nur das Laufen kompiliert make
und es hat gut funktioniert. Meine Frage ist: Warum hing es? Aufgrund der Tatsache, dass es an zwei verschiedenen Stellen anhielt, würde ich vermuten, dass es an einer Art Rennbedingung lag, aber ich würde denken, make
dass es klug genug sein sollte, um alles in die richtige Reihenfolge zu bringen, da es die -j
Option bietet .
strace -p <pid>
prüfen, ob Sie herausfinden können, wonach er sucht. strace zeigt Ihnen nur Systemaufrufe (keine Funktionsaufrufe), aber es kann Ihnen trotzdem wertvolle Informationen geben, wenn es sich dreht, während Sie nach einer bestimmten Datei suchen.-j >1
.$(shell ...)
die letztendlich einen Befehl ausführte, der auf die Eingabe von wartetestdin
. Dies wurde verursacht, wenn eine Variable leer war und keine Dateiargumente an den Befehl übergeben wurden.Antworten:
Ich habe keine Antwort auf dieses präzise Problem, aber ich kann versuchen, Ihnen einen Hinweis darauf zu geben, was möglicherweise passiert: Fehlende Abhängigkeiten in Makefiles.
Beispiel:
Wenn Sie aufrufen, wird
make target
alles korrekt kompiliert. Die Kompilierung vona.source
wird zuerst (willkürlich, aber deterministisch) durchgeführt. Dann wird die Kompilierung vonb.source
durchgeführt.Aber wenn Sie
make -j2 target
beidecompile
Befehle parallel ausgeführt werden. Und Sie werden feststellen, dass die Abhängigkeiten Ihres Makefiles beschädigt sind. Die zweite Kompilierungsannahmea.bytecode
ist bereits kompiliert, wird jedoch nicht in Abhängigkeiten angezeigt. Es ist also wahrscheinlich, dass ein Fehler auftritt. Die richtige Abhängigkeitszeile fürb.bytecode
sollte sein:Um auf Ihr Problem zurückzukommen: Wenn Sie kein Glück haben, kann es sein, dass ein Befehl aufgrund einer fehlenden Abhängigkeit in einer 100% -CPU-Schleife hängen bleibt. Das ist wahrscheinlich das, was hier passiert. Die fehlende Abhängigkeit konnte nicht durch einen sequentiellen Build aufgedeckt werden, sondern wurde durch Ihren parallelen Build aufgedeckt.
quelle
Ich weiß nicht, wie lange Sie den Computer schon haben, aber meine erste Empfehlung wäre, einen Speichertest durchzuführen und zu überprüfen, ob der Speicher ordnungsgemäß funktioniert. Ich weiß, es ist oft nicht der Speicher, der das Problem ist, aber wenn ja, ist es am besten, ihn zuerst als Ursache zu beseitigen, bevor Sie versuchen, andere mögliche Probleme aufzuspüren.
quelle
Mir ist klar, dass dies eine sehr alte Frage ist, aber sie taucht immer noch oben in den Suchergebnissen auf. Hier ist meine Lösung:
GNU make verfügt über einen Jobserver-Mechanismus, der sicherstellt, dass make und seine rekursiven Kinder nicht mehr als die angegebene Anzahl von Kernen verbrauchen: http://make.mad-scientist.net/papers/jobserver-implementation/
Es basiert auf einer Pipe, die von allen Prozessen gemeinsam genutzt wird. Jeder Prozess, bei dem zusätzliche Kinder gezählt werden sollen, muss zuerst Token aus der Pipe konsumieren und diese anschließend wieder abgeben. Wenn ein untergeordneter Prozess die verbrauchten Token nicht zurückgibt, bleibt die Ausführung auf oberster Ebene für immer hängen und wartet darauf, dass sie zurückgegeben werden.
https://bugzilla.redhat.com/show_bug.cgi?id=654822
Ich bin auf diesen Fehler gestoßen, als ich Binutils mit GNU make auf meiner Solaris-Box erstellt habe, wobei "sed" nicht GNU sed ist. Das Fummeln mit PATH, damit sed == gsed Vorrang vor dem System hat, hat das Problem behoben. Ich weiß allerdings nicht, warum sed Token aus der Pipe verbraucht hat.
quelle
Ihr System mag in Ordnung sein, aber es könnte eine Racebedingung sein,
make
wenn Sie Builds parallel ausführen.Wenn etwas mit Ihrem System nicht stimmt, kann es in anderen Szenarien zum Absturz kommen, nicht nur bei parallelen Builds.
quelle
Dies kann eine Racebedingung sein, aber auch, wenn alle erforderlichen Kompilierungen parallel durchgeführt werden und auf andere gewartet wird. Das Verknüpfen kostet Ihre Zeit auf Ihrem Computer. Ich denke, dass, wenn das Verknüpfen auf vorherige notwendige Kompilierung parallel wartet, Sie hohe CPU-Frequenz auf dem Verknüpfen des Threads erhalten, was auch immer Sie kompilieren.
quelle