Odkąd dowiedziałem się o -j, użyłem -j8 beztrosko. Któregoś dnia kompilowałem instalację atlasu, a wykonanie nie powiodło się. W końcu wyśledziłem to wszystko, co było zrobione w porządku - i wszystko poszło dobrze, kiedy wróciłem do singlethreaded. To mnie denerwuje. Jakiego rodzaju warunków muszę przestrzegać podczas pisania własnych plików make, aby uniknąć zrobienia czegoś nieoczekiwanego w make -j?GNU make -j opcja
Odpowiedz
Myślę, że make-j będzie szanował zależności określone w pliku Makefile; tj. jeśli podasz, że objA zależy od objB i objC, make nie zacznie działać na objA do momentu zakończenia objB i objC.
Najprawdopodobniej twój plik Makefile nie określa dokładnie wymaganej kolejności operacji, a to tylko szczęście, że zadziała w twoim przypadku w przypadku pojedynczego wątku.
Zgadza się. Pracuję na bazie kodu około 20 milionów linii, głównie w C z małym C++. Jest podzielony na setki komponentów, z których około połowa używa make, a połowa z nich używa dżemu. Zawsze robię równoległe kompilacje z opcją -j; w przeciwnym razie kompilacje zajęłyby wiele godzin. Dżem generuje własne zależności, więc komponenty, które z niego korzystają, zawsze osiągają sukces. Ale komponenty używające ręcznie tworzonych plików makefile dławią się, niezmiennie z powodu nieodpowiednich zależności. –
Wiele widziałem w Internecie, że '-j' odnosi się do liczby procesorów, z którymi chcesz się skompilować. Przeprowadziłem test na mojej 8-rdzeniowej maszynie i 'make' działa aż do' -j8' włącznie (poza tym jest to 100% użycie na wszystkich rdzeniach, podobne do '-j8'). Przy każdym zwiększeniu liczby całkowitej widzę, że kolejne użycie rdzenia wzrasta o około * 100% *. Czy uważasz, że jest to dobra zasada, aby wiedzieć, co określić jako wartość '-j'? – Jacksonkr
Jedyną dobrą zasadą, jaką znam, jest wykonanie "make clean; time make -jn" w twoim programie, z różnymi wartościami (n), i zobaczenie, ile czasu zajmuje każda kompilacja, a następnie idź z dowolnym ustawieniem ukończonym w najmniej czasu. Istnieje zbyt wiele zmiennych (szybkość procesora, szybkość pamięci RAM, rozmiar pamięci RAM, prędkość dysku twardego, obciążenie procesu systemu operacyjnego itp.), Aby uzyskać przydatne uogólnienia. –
W skrócie - upewnij się, że zależności są poprawne i kompletne.
Jeśli korzystasz z gwintu pojedynczego, możesz ślepo ignorować ukryte zależności między celami. Używając równoległego, nie można polegać na niejawnych zależnościach. Wszystkie one powinny być wyraźne. Jest to prawdopodobnie najczęstsza pułapka. Zwłaszcza jeśli używasz celów .phony jako zależności.
This link jest dobrym podkładem przy niektórych problemach z równoległą marką.
+1 Dla dobrego linku. Teraz czuję, że mogę również zaufać make-j i jak rozwiązywać problemy, kiedy się pojawiają. Warto przeczytać. –
Jeśli masz markę rekurencyjną, rzeczy mogą się łatwo złamać. Jeśli nie robisz rekursywnej marki, to dopóki twoje zależności są poprawne i kompletne, nie powinieneś napotkać żadnych problemów (z wyjątkiem błędu w make). Zobacz Recursive Make Considered Harmful, aby uzyskać bardziej szczegółowy opis problemów z rekurencyjną marką.
Oto przykład problemu, który napotkałem, gdy zacząłem używać równoległych kompilacji. Mam cel o nazwie "świeży", którego używam do odbudowy celu od zera ("świeża" kompilacja). W przeszłości kodowałem "świeży" cel, po prostu wskazując "czyste", a następnie "buduj" jako zależności.
build: ## builds the default target
clean: ## removes generated files
fresh: clean build ## works for -j1 but fails for -j2
To działało w porządku, dopóki nie zaczął używać równolegle buduje, ale równolegle buduje, próbuje zrobić zarówno „czyste” i „budować” jednocześnie. Zmieniłem definicję "świeżej" w następujący sposób, aby zagwarantować prawidłową kolejność operacji.
fresh:
$(MAKE) clean
$(MAKE) build
Jest to zasadniczo kwestia prawidłowego określenia zależności. Sztuczka polega na tym, że równoległe kompilacje są w tym przypadku bardziej restrykcyjne niż kompilacje jednowątkowe. Mój przykład pokazuje, że lista zależności dla danego celu nie musi oznaczać kolejności wykonania.
Robota rekursywna, yuk !. Prawidłowy sposób mówienia, aby _please zawsze czyścić przed build_ to oczywiście 'build: clean'. – bobbogo
@bobbogo: Nie chcę zawsze czyścić przed kompilacją - w większości przypadków jest to niepotrzebne. "Świeży" cel, który opisałem, jest po prostu zwykłym skryptem, który uruchamia "make clean", a następnie "make build" (w tych rzadkich momentach, kiedy chcę to zrobić). Nie widzę żadnej szkody w wykonywaniu rekursywnie w tym scenariuszu. – nobar
Jak o ochronie go warunkowego: 'ifeq ($ (MAKECMDGOALS), fresh); kompilacja: czysta; endif' (zastąp średniki nowymi liniami)? – eriktous
Dobrze jest mieć zautomatyzowany test, aby przetestować opcję -j WSZYSTKICH plików make. Nawet najlepsi programiści mają problemy z opcją -j make. Najczęstsze problemy są najprostsze.
myrule: subrule1 subrule2
echo done
subrule1:
echo hello
subrule2:
echo world
W zwykłej wersji zobaczysz cześć -> świat -> zrobione. Z make -j 4 możesz zobaczyć świat -> cześć -> zrobione
Tam, gdzie to widzę, większość to tworzenie katalogów wyjściowych.Na przykład:
build: $(DIRS) $(OBJECTS)
echo done
$(DIRS):
[email protected] -p [email protected]
$(OBJECTS):
$(CC) ...
Pomyślałem, że dodaję odpowiedź do podsekcji, ponieważ nie pokazuje ona wyraźnie efektu. Dodaje się jednak kilka poleceń dotyczących trybu uśpienia. Działa na Linuksie.
następnie uruchomić make pokazuje różnice z:
- zrobić
- zrobić -j4
all: toprule1
toprule1: botrule2 subrule1 subrule2
@echo toprule 1 start
@sleep 0.01
@echo toprule 1 done
subrule1: botrule1
@echo subrule 1 start
@sleep 0.08
@echo subrule 1 done
subrule2: botrule1
@echo subrule 2 start
@sleep 0.05
@echo subrule 2 done
botrule1:
@echo botrule 1 start
@sleep 0.20
@echo "botrule 1 done (good prerequiste in sub)"
botrule2:
@echo "botrule 2 start"
@sleep 0.30
@echo "botrule 2 done (bad prerequiste in top)"
- 1. Opcja GNU make - zrób w QMAKE
- 2. Make -j Ograniczenia pamięci RAM
- 3. stos „Nieprawidłowy Opcja` --make`
- 4. Zwiększenie bjam versus GNU make
- 5. GNU make: odwracanie sukcesu podprocesowego?
- 6. Kompleksowy poradnik gnu make/gcc
- 7. Unikaj duplikowania reguł GNU Make
- 8. Dlaczego GNU make usunąć plik
- 9. Równoległe make: set -j8 jako domyślna opcja
- 10. Jakie są dobre zasoby dla GNU Make?
- 11. multi-wieloznaczne zasady wzór GNU make
- 12. GNU make Konwersja spacji aby Dwukropki
- 13. działa grep od wewnątrz GNU make
- 14. Jak GNU/Make przystanek de przedstawieniu dowiązania symboliczne do katalogów
- 15. GNU make funkcja wieloznaczny nie znajdzie czasu wykonywania wygenerowanych plików
- 16. GNU Make. Zmienne o zakresie ograniczonym do pojedynczego pliku Makefile
- 17. BSD Make i GNU Utwórz zgodny plik Makefile
- 18. Czy mogę uzyskać tylko drugi warunek wstępny w GNU make?
- 19. Tworzenie kilku skompilowanych plików nagłówkowych za pomocą GNU make
- 20. Jak mogę zobaczyć polecenia uruchamiane przez GNU make?
- 21. Właściwa metoda dla obiektów wieloznacznych w GNU Make
- 22. Implementacja `make check` lub` make test`
- 23. Jak uniknąć problemów z współbieżnością podczas używania GNU make dla równoległych kompilacji plików archiwum?
- 24. dlaczego "make" przed "make install"
- 25. jak wykonać "make" make file
- 26. Dlaczego make -j działa lepiej po przekroczeniu liczby większej niż liczba dostępnych rdzeni?
- 27. RVM zainstalować ruby-1.9.3-p286: Błąd uruchomiony 'make -j 9' (OSX: Mountain Lion)
- 28. Pobierz pierwszą literę zmiennej make
- 29. Czy i +++ j jest zawsze traktowane jako i ++ + j?
- 30. Numpy: Różnica między [i] [j] a [i, j]
Czy jesteś pewien, że to wina zrobić? Pisanie poprawnych plików Makefile jest podatne na błędy. –
Meh, nawet pliki Makefile generowane przez autotools są błędne. Spróbuj skompilować GCC z opcją -j2 lub wyższą. – LiraNuna