Cosa potrebbe causare il blocco di make durante la compilazione su più core?


17

Ieri stavo cercando di compilare il pacchetto ROOT dal sorgente. Da quando lo stavo compilando su una macchina mostro a 6 core, ho deciso di andare avanti e costruire usando più core usando make -j 6. La compilazione è stata semplice e molto veloce all'inizio, ma a un certo punto si è makebloccata usando la CPU al 100% su un solo core.

Ho cercato su Google e ho trovato questo post nelle bacheche dei messaggi ROOT. Da quando ho costruito questo computer da solo, ero preoccupato di non aver applicato correttamente il dissipatore di calore e la CPU si stava surriscaldando o qualcosa del genere. Sfortunatamente, non ho un frigorifero qui al lavoro in cui posso attaccarlo. ;-)

Ho installato il lm-sensorspacchetto ed eseguito di make -j 6nuovo, questa volta monitorando la temperatura della CPU. Sebbene sia diventato alto (vicino a 60 ° C), non ha mai superato la temperatura alta o critica.

Ho provato a correre make -j 4ma ancora una volta ho makeappeso durante la compilazione, questa volta in un punto diverso.

Alla fine, ho compilato solo in esecuzione makee ha funzionato bene. La mia domanda è: perché era sospeso? A causa del fatto che si è fermato in due punti diversi, immagino che fosse dovuto a una sorta di condizione di gara, ma penso che makedovrebbe essere abbastanza intelligente da ottenere tutto nel giusto ordine poiché offre l' -jopzione.


4
Sembra una condizione di razza. Una cosa che potresti fare è collegarti al processo di esecuzione in esecuzione (quello che sta ruotando) usando, ad esempio, strace -p <pid>e vedi se riesci a scoprire cosa sta cercando / per. strace ti mostrerà solo syscall (non chiamate di funzione), ma potrebbe comunque darti informazioni preziose se gira mentre guarda o per un determinato file.
jlp,

Il thread che hai trovato tramite Google porta alla conclusione che nessuno è stato in grado di compilarlo -j >1.
Nils,

Non correlato alla compilazione parallela, ma avevo un makefile sospeso che impiegava un'eternità a eseguire il debug. Si scopre che era semplicemente nell'inizializzazione di una variabile, $(shell ...)stava infine eseguendo un comando in attesa di input dastdin . Ciò è stato causato quando una variabile era vuota e nessun argomento di file è stato passato al comando.
jozxyqk,

Risposte:


13

Non ho una risposta a questo preciso problema, ma posso provare a darti un suggerimento su ciò che potrebbe accadere: dipendenze mancanti nei Makefile.

Esempio:

target: a.bytecode b.bytecode
    link a.bytecode b.bytecode -o target

a.bytecode: a.source
    compile a.source -o a.bytecode

b.bytecode: b.source
    compile b.source a.bytecode -o a.bytecode

Se chiami make targettutto verrà compilato correttamente. La compilazione di a.sourceviene eseguita (arbitrariamente, ma deterministicamente) per prima. Quindi b.sourceviene eseguita la compilazione di .

Ma se make -j2 targetentrambi i compilecomandi verranno eseguiti in parallelo. E noterai che le dipendenze del tuo Makefile sono rotte. La seconda compilazione presuppone che a.bytecodesia già stata compilata, ma non appare nelle dipendenze. Quindi è probabile che accada un errore. La riga di dipendenza corretta per b.bytecodedovrebbe essere:

b.bytecode: b.source a.bytecode

Per tornare al tuo problema, se non sei fortunato è possibile che un comando si blocchi in un ciclo CPU al 100%, a causa di una dipendenza mancante. Questo è probabilmente ciò che sta accadendo qui, la dipendenza mancante non può essere rivelata da una build sequenziale, ma è stata rivelata dalla tua build parallela.


Interessante. Sai se sono disponibili strumenti in grado di eseguire un makefile e controllare queste dipendenze?
user545424

Non ne conosco nessuno. In ogni caso, uno strumento del genere potrebbe trovare solo errori evidenti. A meno che non capisca la sintassi per ciascun comando che appare nel Makefile e sappia quali sono le dipendenze (potenzialmente implicite).
Stéphane Gimenez,

2

Non so da quanto tempo hai la macchina, ma la mia prima raccomandazione sarebbe quella di provare un test di memoria e verificare che la memoria funzioni correttamente. So che spesso non è la memoria il problema, ma se lo è, è meglio eliminarlo come causa prima di provare a rintracciare altri problemi probabilmente.


1

Mi rendo conto che questa è una domanda molto vecchia, ma si apre ancora nella parte superiore dei risultati di ricerca, quindi ecco la mia soluzione:

GNU make ha un meccanismo di jobserver per garantire make e i suoi figli ricorsivi non consumano più del numero specificato di core: http://make.mad-scientist.net/papers/jobserver-implementation/

Si basa su una pipe condivisa da tutti i processi. Ogni processo che vuole rovesciare altri bambini deve prima consumare i token dalla pipa, quindi abbandonarli al termine. Se un processo figlio non restituisce i token che ha consumato, il livello più alto si blocca in attesa per sempre che vengano restituiti.

https://bugzilla.redhat.com/show_bug.cgi?id=654822

Ho riscontrato questo errore durante la creazione di binutils con GNU make sul mio box Solaris, dove "sed" non è GNU sed. Giocare con PATH per rendere sed == gsed prioritario rispetto al sistema sed ha risolto il problema. Non so perché sed consumasse token dalla pipa, comunque.


0

il tuo sistema potrebbe essere ok, ma potrebbe esserci una condizione di competizione makequando si eseguono build in parallelo.

Se qualcosa non va nel tuo sistema, si bloccherebbe / si arresterebbe in modo anomalo per altri scenari, non solo quando si eseguivano build parallele.


0

Questa potrebbe essere una condizione di gara, ma anche se tutta la compilazione necessaria viene eseguita in parallelo e in attesa di altri, il collegamento richiede tempo sulla tua macchina. Penso che se il collegamento attende la precedente compilazione necessaria in parallelo, allora si ottiene un'alta frequenza della CPU sul collegamento del thread qualunque cosa si compili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.