Kompilacja z g ++ przy użyciu wielu rdzeni

174

Szybkie pytanie: jaka jest flaga kompilatora, która pozwala g ++ na tworzenie wielu własnych instancji w celu szybszego kompilowania dużych projektów (na przykład 4 pliki źródłowe naraz dla wielordzeniowego procesora)?

bsofman
źródło
Czy to naprawdę pomoże? Wszystkie moje zadania kompilacji są powiązane we / wy, a nie z procesorem.
Brian Knoblauch
5
Nawet jeśli są one ograniczone we / wy, prawdopodobnie można utrzymać większe obciążenie we / wy, gdy występują ciężkie bity procesora (przy tylko jednej instancji g ++ wystąpią przerwy) i prawdopodobnie zwiększyć wydajność we / wy, jeśli harmonogram ma większy wybór co dalej czytać z dysku. Z mojego doświadczenia wynika, że ​​rozsądne stosowanie make -jprawie zawsze prowadzi do pewnej poprawy.
Flexo
1
@BrianKnoblauch Ale na mojej maszynie (prawdziwej lub w VirtualBox), jest ona związana z procesorem, zauważyłem, że procesor jest zajęty przez polecenie „top” podczas kompilacji.
大 宝剑
1
Nawet jeśli są one związane we / wy, możemy użyć flagi gcc '-pipe', aby zmniejszyć ból.
大 宝剑
właśnie zobaczyłem to w google: gcc.gnu.org/onlinedocs/libstdc++/manual/…
Jim Michaels,

Odpowiedzi:

240

Możesz to zrobić za pomocą make - za pomocą gnu make jest to flaga -j (pomoże to również na komputerze jednoprocesorowym).

Na przykład, jeśli chcesz, aby marka miała 4 równoległe zadania:

make -j 4

Możesz także uruchomić gcc w potoku z

gcc -pipe

Spowoduje to potokowanie etapów kompilacji, co również pomoże utrzymać zajęcie rdzeni.

Jeśli masz również dodatkowe maszyny, możesz sprawdzić distcc , który będzie kompilował również do nich.

frankodwyer
źródło
36
Twoja liczba -j powinna być 1,5 razy większa od liczby posiadanych rdzeni.
Mark Beckwith
2
Dzięki. Wciąż próbowałem przekazać „-j #” do gcc przez CFLAGS / CPPFLAGS / CXXFLAGS. Zupełnie zapomniałem, że "-j #" jest parametrem dla make GNU (a nie dla GCC).
chriv
33
Dlaczego opcja -j dla GNU Make musi być 1,5 razy większa od liczby rdzeni procesora?
bitek
28
Liczba 1.5 jest spowodowana zauważonym problemem związanym z we / wy . To praktyczna zasada. Około 1/3 zadań będzie czekała na operacje we / wy, więc pozostałe zadania będą wykorzystywać dostępne rdzenie. Liczba większa niż liczba rdzeni jest lepsza i możesz nawet osiągnąć nawet 2x . Zobacz także: Gnu -jargumentuje
bezartowy hałas
4
@JimMichaels Może tak być, ponieważ zależności są źle ustawione w projekcie (cel zaczyna budować, nawet jeśli jego zależności nie są jeszcze gotowe), tak że tylko kompilacja sekwencyjna kończy się sukcesem.
Antonio
42

Nie ma takiej flagi, a posiadanie jednej jest sprzeczne z filozofią Uniksa, zgodnie z którą każde narzędzie wykonuje tylko jedną funkcję i wykonuje ją dobrze. Tworzenie procesów kompilatora jest koncepcyjnie zadaniem systemu kompilacji. To, czego prawdopodobnie szukasz, to flaga -j (praca) do GNU make, a la

zrobić -j4

Lub możesz użyć pmake lub podobnych systemów do tworzenia równoległych.

Mihai Limbășan
źródło
3
„Unixowa pedanteria nie jest pomocna” Dobrze, że to nie była wtedy pedanteria, anonimowy redaktorze. Wycofana. Recenzenci powinni zwracać większą uwagę na to, co robisz.
Wyścigi lekkości na orbicie
12

Ludzie wspominali o podobnej koncepcji, makeale bjamteż ją popierają. Korzystanie z bjam -jxinstrukcji bjam do zbudowaniax współbieżnych poleceń.

Używamy tych samych skryptów kompilacji w systemach Windows i Linux, a użycie tej opcji skraca o połowę czas kompilacji na obu platformach. Miły.

MattyT
źródło
9

makezrobi to za Ciebie. Zbadaj przełączniki -ji -lna stronie podręcznika. Nie sądzę, aby g++można go było równolegle.

rmeador
źródło
+1 za -lmożliwość dodania wzmianki (nie rozpoczyna nowej pracy, chyba że wszystkie poprzednie prace zostały zakończone). W przeciwnym razie wydaje się, że zadanie konsolidatora nie rozpoczyna się od zbudowania wszystkich plików obiektowych (ponieważ niektóre kompilacje nadal trwają), więc zadanie konsolidatora kończy się niepowodzeniem.
NGI
8

Jeśli używasz make, problem z -j. Od 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.

A przede wszystkim, jeśli chcesz napisać skrypt lub zidentyfikować liczbę dostępnych rdzeni (w zależności od środowiska i jeśli pracujesz w wielu środowiskach, może to bardzo się zmienić), możesz użyć wszechobecnej funkcji Pythona cpu_count():

https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count

Lubię to:

make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')

Jeśli pytasz, dlaczego 1.5w komentarzu powyżej zacytuję bezartowy szum użytkownika:

Liczba 1.5 jest spowodowana zauważonym problemem związanym z we / wy. To praktyczna zasada. Około 1/3 zadań będzie czekała na operacje we / wy, więc pozostałe zadania będą wykorzystywać dostępne rdzenie. Liczba większa niż liczba rdzeni jest lepsza i możesz nawet osiągnąć nawet 2x.

Havok
źródło
5
Większość użytkowników Linuksa prawdopodobnie będzie wolała krótszy: make -j`nproc` z nprocw GNU Coreutils.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Jeśli używasz dysku SSD, we / wy nie będzie tak dużym problemem. Aby rozwinąć powyższy komentarz Ciro, możesz to zrobić: make -j $(( $(nproc) + 1 ))(upewnij się, że wstawiłeś spacje tam, gdzie je mam).
Ed K
Fajna sugestia użycia Pythona, na systemach, gdzie nprocnie jest dostępny, np. W manylinux1kontenerach, oszczędza dodatkowy czas, unikając uruchamiania yum update/ yum install.
hafling
7

distcc może być również używane do dystrybucji kompilacji nie tylko na bieżącej maszynie, ale także na innych maszynach w farmie, na których zainstalowano distcc.

Jason
źródło
+1, distcc to przydatne narzędzie w swoim arsenale przy dużych kompilacjach.
Flexo
Wygląda na to, że jest kilka, które również działają „jak” distcc: stackoverflow.com/questions/5374106/distributed-make/ ...
rogerdpack
3

Nie jestem pewien co do g ++, ale jeśli używasz GNU Make to "make -j N" (gdzie N to liczba wątków, które może utworzyć) pozwoli make na uruchomienie wielu zadań g ++ w tym samym czasie (tak długo ponieważ pliki nie są od siebie zależne).

Andy
źródło
2
nie Nie ma liczby wątków! Wiele osób źle to rozumie, ale -j Nmówi, że należy uruchomić liczbę procesów naraz, a nie wątków. To jest powód, dla którego nie jest tak wydajny jak MS cl -MT(naprawdę wielowątkowy).
Sebi2020
2

Równolegle z GNU

Robiłem test porównawczy kompilacji syntetycznej i nie mogłem zawracać sobie głowy pisaniem pliku Makefile, więc użyłem:

sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"

Wyjaśnienie:

  • {.} pobiera argument wejściowy i usuwa jego rozszerzenie
  • -t wypisuje wykonywane polecenia, aby dać nam wyobrażenie o postępie
  • --will-cite usuwa prośbę o cytowanie oprogramowania, jeśli publikujesz przy jego użyciu wyniki ...

parallel jest tak wygodny, że mógłbym sam sprawdzić datownik:

ls | grep -E '\.c$' | parallel -t --will-cite "\
  if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
    gcc -c -o '{.}.o' '{}'
  fi
"

xargs -P może również uruchamiać zadania równolegle, ale nieco mniej wygodne jest manipulowanie rozszerzeniami lub uruchamianie z nim wielu poleceń: wielu poleceń Wywoływanie wielu poleceń przez xargs

Poproszono o linkowanie równoległe pod adresem: Czy gcc może używać wielu rdzeni podczas łączenia?

DO ZROBIENIA: Myślę, że gdzieś przeczytałem, że kompilację można zredukować do mnożenia macierzy, więc być może jest też możliwe przyspieszenie kompilacji pojedynczego pliku dla dużych plików. Ale nie mogę teraz znaleźć odniesienia.

Testowane w Ubuntu 18.10.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło