GCC: czym różni się March od Mtune?

88

Próbowałem wyczyścić stronę podręcznika GCC w tym celu, ale nadal nie rozumiem.

Jaka jest różnica między -marchi -mtune?

Kiedy używa się tylko -march, a kiedy obu? Czy jest to kiedykolwiek możliwe -mtune?

Jameson
źródło

Odpowiedzi:

97

Jeśli używasz, -marchGCC będzie mogło generować instrukcje, które działają na określonym CPU, ale (zazwyczaj) nie na wcześniejszych procesorach z rodziny architektur.

Jeśli tylko użyjesz -mtune, kompilator wygeneruje kod, który działa na każdym z nich, ale faworyzuje sekwencje instrukcji, które działają najszybciej na określonym procesorze, który wskazałeś. np. ustawienie heurystyki rozwijania pętli odpowiednio dla tego procesora.


-march=foosugeruje, -mtune=foochyba że określisz również inny -mtune. Jest to jeden z powodów, dla których używanie -marchjest lepsze niż tylko włączanie opcji, takich jak -mavxbez robienia czegokolwiek w zakresie dostrajania.

Uwaga: -march=nativena procesorze, którego GCC nie rozpoznaje, będzie nadal włączał nowe zestawy instrukcji, które GCC może wykryć, ale pozostawi -mtune=generic. Użyj wystarczająco nowego GCC, który wie o Twoim procesorze, jeśli chcesz, aby tworzył dobry kod.

James Youngman
źródło
10
Nie odpowiada, czy sensowne jest używanie obu, czy też mtune jest zbędne, gdy jest ustawione na tę samą wartość.
Pavel Šimerda
12
@ PavelŠimerda Intuicyjnie odpowiedź jest domniemana w definicji dwóch cech. Poza tym dokumentacja wyraźnie to marchsugeruje mtune. Zatem odpowiedzi na twoje zastrzeżenia brzmią odpowiednio: nie i tak.
underscore_d
Dziękuję za tak eleganckie wyjaśnienie! Ułatwiasz zrozumienie.
Rahim Khoja
5
Ludzie potrzebują tl; dr: użyj -march, jeśli uruchamiasz go TYLKO na swoim procesorze, użyj -mtune, jeśli chcesz, aby był bezpieczny dla innych procesorów.
j riv
3
Użytkownicy muszą również zrozumieć, że starsze kompilatory (wydane zanim nie istniały niektóre procesory) mogą dawać różne optymalne mtunei marchkombinacje. Ten post na blogu wyjaśnia
qneill
53

Oto, co wygooglowałem:

Ta -march=Xopcja przyjmuje nazwę procesora Xi umożliwia GCC generowanie kodu, który wykorzystuje wszystkie funkcje X. Podręcznik GCC wyjaśnia dokładnie, które nazwy procesorów oznaczają rodziny procesorów i ich funkcje.

Ponieważ funkcje są zwykle dodawane, ale nie usuwane, plik binarny zbudowany za pomocą -march=Xbędzie działał na procesorze X, ma duże szanse na uruchomienie na procesorach nowszych niż X, ale prawie na pewno nie będzie działał na niczym starszym niż X. Pewne zestawy instrukcji (myślę, że 3DNow!) Mogą być specyficzne dla konkretnego producenta procesora, a ich użycie prawdopodobnie dostaniesz pliki binarne, które nie działają na konkurencyjnych procesorach, nowszych lub innych.

Ta -mtune=Yopcja dostosowuje wygenerowany kod do szybszego działania Yniż na innych procesorach, na których może działać. -march=Xsugeruje -mtune=X. -mtune=Ynie zastąpi -march=X, więc na przykład prawdopodobnie nie ma sensu -march=core2i -mtune=i686- Twój kod nie będzie działał na niczym starszym niż i core2tak, z powodu -march=core2, więc dlaczego na Ziemi miałbyś chcieć zoptymalizować pod kątem czegoś starszego (mniej funkcjonalnego) niż core2? -march=core2 -mtune=haswellma więcej sensu: nie używaj żadnych funkcji poza tym, co core2zapewnia (co wciąż jest o wiele więcej niż to, co -march=i686ci daje!), ale optymalizuj kod dla znacznie nowszych haswellprocesorów, a nie dla core2.

Jest też -mtune=generic. genericsprawia, że ​​GCC tworzy kod, który działa najlepiej na obecnych procesorach (co oznacza genericzmiany z jednej wersji GCC na inną). Na forach Gentoo krążą plotki, że -march=X -mtune=generictworzy kod działający szybciej Xniż kod produkowany przez do -march=X -mtune=X(lub po prostu -march=X, jak -mtune=Xsugeruje). Nie mam pojęcia, czy to prawda, czy nie.

Ogólnie, jeśli nie wiesz dokładnie, czego potrzebujesz, wydaje się, że najlepszym sposobem jest określenie -march=<oldest CPU you want to run on>i -mtune=generic( -mtune=genericjest tutaj, aby przeciwdziałać niejawnemu -mtune=<oldest CPU you want to run on>, ponieważ prawdopodobnie nie chcesz optymalizować dla najstarszego procesora). Lub po prostu -march=native, jeśli kiedykolwiek zamierzasz działać tylko na tej samej maszynie, na której budujesz.

LRN
źródło
4
Ale jeśli używasz -march=native, możesz chcieć sprecyzować -mtune=X, ponieważ wartość domyślna nadal jest -mtune=generic, jak omówiono tutaj: lemire.me/blog/2018/07/25/ ...
Roland Weber
@RolandWeber: Dzieje się tak tylko wtedy, gdy używasz GCC zbyt starego, by wiedzieć o procesorze. -march=nativeoznacza tune=nativeto dobrze, jeśli używasz GCC, który wie o twoim procesorze. Ten artykuł przedstawia tylko zły przypadek. Nowsze wersje GCC generalnie generują lepszy kod, zwłaszcza przy użyciu nowych instrukcji, takich jak AVX2 i AVX-512. Posiadanie ustawień dostrajania (takich jak heurystyka rozwijania pętli) zaprojektowanych dla twojego procesora to zdecydowany plus. Więc jeśli zależy Ci na wydajności na tyle, aby korzystać z tych opcji, użyj nowego GCC, przynajmniej takiego, które wie o Twoim procesorze, najlepiej aktualnej stabilnej wersji.
Peter Cordes
Jest do dupy, że GCC nie może zrobić nic lepszego niż tune=genericdla nowszego członka tej samej rodziny mikroarchitektur, zwłaszcza czegoś takiego jak Kaby Lake, które jest dosłownie identyczne z mikroarchitekturą Skylake. Ale myślę, że nadal ma inną rodzinę / stepping, więc GCC, który wiedział tylko o Skylake i starszym, może nie rozpoznać go do strojenia.
Peter Cordes,