2011-01-24 27 views
51

Mam Makefile na komputerze, który ma mnóstwo rdzeni w nim, ale zawsze wydaje mi się, aby zapomnieć napisać -jX podczas kompilacji mojego projektu i trwa to znacznie dłużej niż powinno.Automatyczne ustawianie znaczników zadań (-j) dla maszyny wielordzeniowej?

Czy jest jakiś sposób ustawić flagę -j za pomocą zmiennej środowiskowej lub innego trwałego pliku konfiguracyjnego, aby make automatycznie wykonywał równolegle wiele zadań na tym komputerze?

+0

Powiązane: http: // stackoverflow.com/questions/2527496/how-can-i-write-a-makefile-auto-detect-and-parallelize-build-with-gnu-make –

+0

@sanmai, do którego OS potrzebujesz? Dlaczego "alias make = 'make -j $ (getconf _NPROCESSORS_ONLN)" nie działa? –

+0

Alias ​​nie wystarczy, ponieważ muszę opublikować plik Makefile i nadal działać. Potrzebuję tego dla GNU Make 4.1. @TarunLalwani – sanmai

Odpowiedz

29

Wygląda na to, że zmienna środowiskowa MAKEFLAGS może przekazywać flagi, które są częścią każdego biegu make (przynajmniej dla wersji GNU). Sam nie miałem z tym dużo szczęścia, ale może być możliwe użycie -l zamiast -j do automatycznego uruchamiania wielu zadań, które są odpowiednie dla liczby dostępnych rdzeni.

+0

Cóż, możesz przekazać '-l' lub' -j', ale bez argumentów. Spróbuj sam: https://gist.github.com/sanmai/dcc31ae20afa6e8ba4721f174fe05fd9 – sanmai

6

Możesz dodać linię do Twojego Makefile podobny do następującego:

NUMJOBS=${NUMJOBS:-" -j4 "} 

Następnie dodać ${NUMJOBS} linię w regułach, lub dodać go do innego Makefile var (jak MAKEFLAGS). Będzie to używać envvar NUMJOBS, jeśli istnieje; jeśli nie, automatycznie używaj -j4. Możesz dostroić lub zmienić nazwę na swój gust.

(NB: Osobiście wolałbym domyślnego być -j1 lub "", zwłaszcza jeśli zamierza być dystrybuowane do innych, bo chociaż mam wiele rdzeni także skompilować na wielu różnych platformach, a często zapominają dis -able ustawienie -jX).

+0

Dziękuję za tę odpowiedź. Poszedłem z odpowiedzią Jeremiaha, ponieważ jest to trochę łatwiejsze do zrozumienia i nie muszę w ogóle modyfikować pliku Makefile (pozwalając ludziom pobierającym projekt ustawić dowolną flagę -j, jakiej chcą, jak chcą). Informacyjny niemniej jednak. – KarateSnowMachine

+0

O ile mi wiadomo, dodanie -jX do MAKEFLAGS przestało działać na ostatnim wydaniu GNU, które miało miejsce w zeszłym roku. Czy ktoś inny tego doświadczył? – golvok

33

Zakładam, że korzystasz z Linuksa. To z mojego użytkowania próbki ~/.bashrc

# parallel make 
export NUMCPUS=`grep -c '^processor' /proc/cpuinfo` 
alias pmake='time nice make -j$NUMCPUS --load-average=$NUMCPUS' 

[email protected] src> echo $NUMCPUS 
8 
[email protected] src> pmake 

staje time nice make -j8 --load-average=8.

Aby odpowiedzieć na twoje konkretne pytanie dotyczące umieszczenia tego w Makefile, nie wydaje mi się praktyczne rozpraszanie tej logiki po moich plikach Makefile. Umieszczenie tego na najwyższym poziomie Makefile również nie jest dobrym rozwiązaniem, ponieważ często buduję z podkatalogów i chciałbym je również budować równolegle. Jeśli jednak masz dość płaską hierarchię źródłową, może ona działać dla Ciebie.

+1

Dobry pomysł autodetekcję liczby rdzeni. Chociaż skończyło się na tym, że korzystałem z $ ((NUMCPUS * 2)), ponieważ zazwyczaj to się kompiluje. Dzięki! – KarateSnowMachine

+1

% NUMBER_OF_PROCESSORS% może być użyty z gnu make na systemach Windows – davenpcj

+2

Możesz także mieć numer cpus z poleceniem np.proc. – Soullivaneuh

-1

bym po prostu umieścić

alias make='make -j' 

w ~/.profile lub ~/.bashrc.

Według manual:

Jeśli nic nie wygląda jak liczba całkowita po opcji „-j”, nie ma ograniczeń co do liczby szczelin pracy.

+9

Na mojej 2 rdzeniowej maszynie niewykwalifikowane' -j' szybko zżera całą moją pamięć w dużej kompilacji. Niepolecane. – ntc2

+0

Tak, to wydaje się być czymś, co spowodowałoby bomba na widelec na komputerze z dużym plikiem Makefile. – gib

24

Jak powiedział Jeremiasz Willcock użyć MAKEFLAGS, ale oto jak to zrobić:

export MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)" 

lub można po prostu ustawić stałą wartość takiego:

export MAKEFLAGS="-j 8" 

Jeśli naprawdę Jeśli chcesz zwiększyć wydajność, powinieneś użyć ccache, dodając coś podobnego do poniższego w swoim Makefile:

CCACHE_EXISTS := $(shell ccache -V) 
ifdef CCACHE_EXISTS 
    CC := ccache $(CC) 
    CXX := ccache $(CXX) 
endif 
+1

nie działa dla osx (i okien też) – bibi

+0

Nie działa dla GNU Make 4.1 - [patrz przykład tutaj] (https://gist.github.com/sanmai/dcc31ae20afa6e8ba4721f174fe05fd9) – sanmai

+0

@sanmai, używam MAKEFLAGS tutaj nie MAKEOPTS jak użyto w twoim przykładzie. Wierzę, że GNU Make 4.1 nadal ma MAKEFLAGY. – jcoffland

9

I zazwyczaj to zrobić w następujący sposób w moich skryptach bash:

make -j$(nproc) 
1

aż kiedyś w ciągu ostatniego roku, można to zrobić w swoim makefile: (GNU make testowane)

MAKEFLAGS += "-j$(NUM_CORES) -l$(NUM_CORES) 

(gdzie NUM_PPROCS oblicza lub zestaw według jednego z wielu innych odpowiedzi tutaj) A, bam! prowadzisz wieloprocesowy budynek.

Biorąc pod uwagę, że to przestało działać, najlepszą rzeczą jaką mogłem wymyślić jest to, gdzie plik Makefile się nazywa, ale z -jX i -lX.

# add parallelism equal to number of cores every time. 
# it seems that adding -jX to MAKEFLAGS directly doesn't work any more. 
# included some "random" strings to ensure uniqueness 
ifneq ($(PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB),done) 

NUM_CORES ?= $(shell grep -c "vendor_id" /proc/cpuinfo) 
MAKEFLAGS +=" -j$(NUM_CORES) -l$(NUM_CORES) " 

# for the default target case 
parallel_wrapper_default_target_anthsqjkshbeohcbmeuthnoethoaeou: 
    $(MAKE) PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB=done 

# catches everything else 
% : 
    $(MAKE) [email protected] PARALELL_WRAPPER_ABXCOEOEKCOEBMQJKHTOEUB=done 

# the match for this else is at the end of the file 
else 

##### rest of makefile here ##### 
all: ... 
    ... 

other_target: ... 
    ... 

##### etc. ##### 

endif 
1

Na Ubuntu 16.4 wykorzystując wszystkie rdzenie CPU:

export MAKEFLAGS='-j$(nproc)' 

lub

export MAKEFLAGS='-j 2' 
1

Na początku Makefile:

MAKEFLAGS+="j" 

To nie zajmie Argumenty numeryczne dla dowolnej wersji słonia GNU Make before 4.2.

Jeśli masz trochę wolnych zadań, możesz je uruchamiać tylko pojedynczo za pomocą flock z util-linux-ng. Na przykład narzędzie convert z ImageMagick będzie używać wszystkich zasobów, jakie może uzyskać, gdy zostanie użyte do optimize images according to Google's recommendations, więc nie ma sensu, aby był uruchamiany równolegle.

%.min.jpg: %.jpg 
    @flock --wait 600 Makefile convert $< -sampling-factor 4:2:0 -strip [email protected] 

Ważne jest, aby ustawić długi czas oczekiwania, ponieważ make nadal będzie działać większość z tych poleceń równolegle. Dlatego czas oczekiwania musi być taki, jak najgłębszy czas wykonania kolejki. Jeśli masz osiem rdzeni i osiem dużych obrazów zajmuje minutę, aby zoptymalizować, musisz ustawić czas oczekiwania na co najmniej minutę.

Z setkami rdzeni i ogromnymi obrazami, setka setek sekund może nie wystarczyć.