Jak ustalić maksymalną liczbę do przekazania do opcji make -j?

31

Chcę skompilować tak szybko, jak to możliwe. Domyśl. I chciałby zautomatyzować wybór numeru po -jopcji. Jak mogę programowo wybrać tę wartość, np. W skrypcie powłoki?

Czy wynik jest nprocrównoważny liczbie wątków, z którymi mogę się skompilować?

make -j1 make -j16

tarabajt
źródło

Odpowiedzi:

34

nprocpodaje liczbę dostępnych rdzeni / wątków procesora, np. 8 na czterordzeniowym procesorze obsługującym dwukierunkową SMT.

Liczba zadań, które można uruchomić równolegle z makeużyciem tej -jopcji, zależy od wielu czynników:

  • ilość dostępnej pamięci
  • ilość pamięci używanej przez każde makezadanie
  • zakres, w jakim makezadania są związane z operacjami we / wy lub procesorem

make -j$(nproc) jest przyzwoitym miejscem do rozpoczęcia, ale zwykle możesz użyć wyższych wartości, o ile nie wyczerpiesz dostępnej pamięci i nie zaczniesz przeładowywać.

W przypadku naprawdę szybkich kompilacji, jeśli masz wystarczającą ilość pamięci, polecam użycie tmpfs, w ten sposób większość zadań będzie związana z procesorem i make -j$(nproc)będzie działać tak szybko, jak to możliwe.

Stephen Kitt
źródło
3
i ccachedo późniejszej przebudowy, ale jest to OT
solsTiCe
1
Czy warto byłoby zastosować coś takiego jak GNU równoległy?
terdon
Jeśli użyję a tmpfs, czy będę ograniczony do rozmiaru katalogu, który zawsze jest mniejszy niż rozmiar mojej fizycznej pamięci RAM?
tarabyte
2
To nie jest świetna odpowiedź, ale w ścisłym duchu programowego określenia najszybszej wartości „j”, możesz zapętlić j od 1 do rozsądnej górnej granicy (2x nproc ??) i zawrzeć make w timewywołaniu. Wyczyść wyniki, powtórz spłukiwanie piany i zakończ sortowanie wartości razy / j.
Jeff Schaller
3
@terdon Nie. Marka polega na rozwiązywaniu zależności, co oznacza, że ​​zadania nadal muszą być uruchamiane w określonej kolejności. GNU równolegle się tym nie przejmuje. Na marginesie, podejmowanie decyzji, które zadania mogą być uruchamiane równolegle, a które nie, jest trudnym problemem. Wszystkie programy, które oferowały równoległe kompilacje, trwały lata, zanim stały się nieco użyteczne.
lcd047,
6

Niestety, nawet różne części tej samej kompilacji mogą być optymalne przy sprzecznych wartościach współczynnika j, w zależności od tego, co jest budowane, w jaki sposób zasoby systemowe są wąskim gardłem w tym czasie, co jeszcze dzieje się na maszynie kompilacji, co się dzieje w sieć (w przypadku korzystania z technik kompilacji rozproszonej), status / lokalizacja / wydajność wielu systemów buforowania zaangażowanych w kompilację itp.

Kompilacja 100 małych plików C może być szybsza niż kompilacja jednego ogromnego pliku lub odwrotnie. Budowanie małego, wysoce skomplikowanego kodu może być wolniejsze niż budowanie ogromnych ilości kodu prostego / liniowego.

Nawet kontekst kompilacji ma znaczenie - użycie współczynnika aj zoptymalizowanego dla kompilacji na dedykowanych serwerach, dostosowanych do ekskluzywnych, nie nakładających się kompilacji, może dawać bardzo rozczarowujące wyniki, gdy deweloperzy budują równolegle na tym samym serwerze współużytkowanym (każda taka kompilacja może zająć więcej czas niż wszystkie z nich połączone, jeśli są serializowane) lub na serwerach o różnych konfiguracjach sprzętowych lub zwirtualizowanych.

Istnieje również aspekt poprawności specyfikacji kompilacji. Bardzo złożone kompilacje mogą mieć warunki wyścigu powodujące nieregularne niepowodzenia kompilacji, a częstości występowania mogą się bardzo różnić wraz ze wzrostem lub spadkiem współczynnika j.

Mogę iść i iść. Chodzi o to, że musisz ocenić swoją kompilację w swoim kontekście, dla którego chcesz zoptymalizować współczynnik j. @Jeff Schaller ma zastosowanie: iteruj, aż znajdziesz najlepsze dopasowanie. Osobiście zacznę od wartości nproc, spróbuj najpierw w górę i w dół tylko wtedy, gdy próby w górę wykazują natychmiastową degradację.

Dobrym pomysłem może być najpierw zmierzenie kilku identycznych kompilacji w rzekomo identycznych kontekstach, aby uzyskać pojęcie o zmienności twoich pomiarów - jeśli zbyt wysoka może zagrozić całemu wysiłkowi optymalizacji (20% zmienność całkowicie przyćmi 10% poprawę / odczyt degradacji w wyszukiwaniu współczynnika j).

Wreszcie, IMHO lepiej jest użyć (adaptacyjnego) serwera zadań, jeśli jest on obsługiwany i dostępny zamiast stałego współczynnika j - konsekwentnie zapewnia lepszą wydajność kompilacji w szerszym zakresie kontekstów.

Dan Cornilescu
źródło
dobrze postawiony w odniesieniu do zależności podstawowej wersji. czy możesz skomentować przekazanie nie ustalonej liczby za pomocą -jparametru? np.make -j
tarabyte
4
make -jodrodzi się tyle miejsc pracy, ile pozwalają zależności, jak bomba widelca ( superuser.com/questions/927836/… ); kompilacja będzie się czołgać w najlepszym przypadku, wydając najwięcej procesora na zarządzanie procesami niż na ich uruchamianie ( superuser.com/questions/934685/... ), aw kompilacjach wysoce równoległych w systemie zabraknie pamięci / swapów lub numerów pid i kompilacja zakończy się niepowodzeniem .
Dan Cornilescu,
3

Najprostszym sposobem jest użycie nproctakiego:

make -j`nproc`

Polecenie nproczwróci liczbę rdzeni na twoim komputerze. Po zawinięciu go w znaczniki, nprocpolecenie wykona się jako pierwsze, zwróci liczbę i ta liczba zostanie przekazana make.

Możesz mieć trochę niepotwierdzonych doświadczeń, w których wykonanie liczby rdzeni + 1 skutkuje szybszymi czasami kompilacji. Ma to więcej wspólnego z czynnikami takimi jak opóźnienia we / wy, inne opóźnienia zasobów i inna dostępność ograniczeń zasobów.

Aby to zrobić nproc+1, spróbuj tego:

make -j$((`nproc`+1))
010110110101
źródło
0

Jeśli chcesz napisać makepolecenie użycia tak wielu równoległych pracowników, jak masz wirtualne procesory, sugeruję użyć:

nproc | xargs -I % make -j%

Które można zapisać jako samodzielne polecenie lub jako RUNdyrektywę wewnątrz Dockerfile(ponieważ Docker nie obsługuje zagnieżdżonych poleceń)

Maksym Ganenko
źródło