Come determinare il numero massimo da passare per rendere l'opzione -j?


31

Voglio compilare il più velocemente possibile. Vai a capire. E vorrei automatizzare la scelta del numero seguendo l' -jopzione. Come posso scegliere programmaticamente quel valore, ad esempio in uno script di shell?

L'output è nprocequivalente al numero di thread che ho a disposizione per compilare?

make -j1 make -j16

Risposte:


34

nprocfornisce il numero di core / thread della CPU disponibili, ad esempio 8 su una CPU quad-core che supporta SMT a due vie.

Il numero di lavori che è possibile eseguire in parallelo con l' makeutilizzo -jdell'opzione dipende da una serie di fattori:

  • la quantità di memoria disponibile
  • la quantità di memoria utilizzata da ciascun makelavoro
  • la misura in cui i makelavori sono associati a I / O o CPU

make -j$(nproc) è un buon punto di partenza, ma di solito è possibile utilizzare valori più alti, purché non si esaurisca la memoria disponibile e si inizi a battere.

Per build molto veloci, se hai abbastanza memoria, ti consiglio di usare a tmpfs, in questo modo la maggior parte dei lavori sarà legata alla CPU e make -j$(nproc)funzionerà il più velocemente possibile.


3
e ccacheper la ricostruzione successiva, ma questo è OT
solsTiCe

1
Vale la pena usare qualcosa come GNU parallel?
terdon

Se uso un tmpfs, sarò limitato a una dimensione della directory sempre più piccola della mia dimensione RAM fisica?
Tarabyte,

2
Non è un'ottima risposta, ma nello spirito rigoroso della questione della determinazione programmatica del valore "j" più veloce, è possibile eseguire il ciclo j da 1 a un limite superiore ragionevole (2x nproc ??) e concludere il make in una timechiamata. Pulisci i risultati, ripeti il ​​lavaggio con schiuma e finisci per ordinare i valori di volte / j.
Jeff Schaller

3
@terdon No. Make è tutto sulla risoluzione delle dipendenze, il che significa che i lavori devono ancora essere eseguiti in un certo ordine. A GNU parallel non importa. Da un lato, decidere quali lavori possono essere eseguiti in parallelo in parallelo e quali no è un problema difficile. Tutti i programmi che offrivano build parallele impiegarono anni prima che diventassero in qualche modo utilizzabili.
lcd047

6

Sfortunatamente anche porzioni diverse della stessa build possono essere ottimali con valori di fattore j contrastanti, a seconda di cosa viene costruito, come, quali risorse di sistema sono il collo di bottiglia in quel momento, cos'altro sta succedendo sulla macchina di build, cosa sta succedendo in la rete (se si utilizzano tecniche di compilazione distribuite), stato / posizione / prestazioni dei numerosi sistemi di memorizzazione nella cache coinvolti in una build, ecc.

Compilare 100 minuscoli file C potrebbe essere più veloce della compilazione di un singolo enorme o viceversa. La creazione di piccoli codici altamente contorti può essere più lenta della creazione di enormi quantità di codice diretto / lineare.

Anche il contesto della build è importante: l'utilizzo di un fattore j ottimizzato per build su server dedicati ottimizzati per build esclusive e non sovrapposte può produrre risultati molto deludenti se utilizzato dagli sviluppatori che costruiscono in parallelo sullo stesso server condiviso (ciascuna build potrebbe richiedere più tempo di tutti combinati se serializzati) o su server con diverse configurazioni hardware o virtualizzati.

C'è anche l'aspetto della correttezza delle specifiche di build. Build molto complessi possono avere condizioni di gara che causano fallimenti di build intermittenti con tassi di occorrenza che possono variare selvaggiamente con l'aumento o la diminuzione del fattore j.

Posso andare avanti all'infinito. Il punto è che devi effettivamente valutare la tua build nel tuo contesto per cui desideri ottimizzare il fattore j. Si applica il commento di @Jeff Schaller: scorrere fino a trovare la soluzione migliore. Personalmente inizierei dal valore nproc, proverei prima verso l'alto e verso il basso solo se i tentativi verso l'alto mostrano un degrado immediato.

Potrebbe essere una buona idea misurare prima diverse build identiche in contesti apparentemente identici solo per avere un'idea della variabilità delle tue misurazioni - se troppo elevata potrebbe compromettere l'intero sforzo di ottimizzazione (una variabilità del 20% significherebbe eclissare completamente un miglioramento del 10% / lettura del degrado nella ricerca del fattore j).

Infine, IMHO è meglio usare un server di lavoro (adattivo) se supportato e disponibile invece di un fattore j fisso - fornisce costantemente una migliore prestazione di compilazione in una più ampia gamma di contesti.


ben messo per quanto riguarda le dipendenze della build sottostante. puoi commentare il passaggio di un numero fisso con il -jparametro? ad es.make -j
tarabyte,

4
make -jgenererà tutti i lavori che le dipendenze consentono come una bomba ( superuser.com/questions/927836/… ); la build eseguirà la scansione al meglio spendendo la maggior parte della CPU per la gestione dei processi piuttosto che eseguirli ( superuser.com/questions/934685/… ) e in build altamente parallele il sistema esaurirà la memoria / lo scambio o il numero pid e la build avrà esito negativo .
Dan Cornilescu,

3

Il modo più diretto è usare nproccosì:

make -j`nproc`

Il comando nprocrestituirà il numero di core sulla tua macchina. Avvolgendolo tra i segni di spunta, il nproccomando verrà eseguito per primo, restituirà un numero e quel numero verrà passato make.

Potresti avere qualche esperienza aneddotica in cui fare il conteggio dei core + 1 porta a tempi di compilazione più veloci. Ciò ha più a che fare con fattori come i ritardi di I / O, altri ritardi di risorse e altre disponibilità di vincoli di risorse.

Per fare questo nproc+1, prova questo:

make -j$((`nproc`+1))

0

Se desideri scrivere un makecomando per utilizzare tutti i lavoratori paralleli quante sono le CPU virtuali, ti suggerisco di usare:

nproc | xargs -I % make -j%

Che può essere scritto come comando autonomo o come RUNdirettiva all'interno Dockerfile(poiché Docker non supporta i comandi nidificati)

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.