Próbowałem wyczyścić stronę podręcznika GCC w tym celu, ale nadal nie rozumiem.
Jaka jest różnica między -march
i -mtune
?
Kiedy używa się tylko -march
, a kiedy obu? Czy jest to kiedykolwiek możliwe -mtune
?
Odpowiedzi:
Jeśli używasz, -march
GCC 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=foo
sugeruje, -mtune=foo
chyba że określisz również inny -mtune
. Jest to jeden z powodów, dla których używanie -march
jest lepsze niż tylko włączanie opcji, takich jak -mavx
bez robienia czegokolwiek w zakresie dostrajania.
Uwaga: -march=native
na 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.
march
sugeruje mtune
. Zatem odpowiedzi na twoje zastrzeżenia brzmią odpowiednio: nie i tak.
Oto, co wygooglowałem:
Ta -march=X
opcja przyjmuje nazwę procesora X
i 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=X
bę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=Y
opcja dostosowuje wygenerowany kod do szybszego działania Y
niż na innych procesorach, na których może działać. -march=X
sugeruje -mtune=X
. -mtune=Y
nie zastąpi -march=X
, więc na przykład prawdopodobnie nie ma sensu -march=core2
i -mtune=i686
- Twój kod nie będzie działał na niczym starszym niż i core2
tak, 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=haswell
ma więcej sensu: nie używaj żadnych funkcji poza tym, co core2
zapewnia (co wciąż jest o wiele więcej niż to, co -march=i686
ci daje!), ale optymalizuj kod dla znacznie nowszych haswell
procesorów, a nie dla core2
.
Jest też -mtune=generic
. generic
sprawia, że GCC tworzy kod, który działa najlepiej na obecnych procesorach (co oznacza generic
zmiany z jednej wersji GCC na inną). Na forach Gentoo krążą plotki, że -march=X -mtune=generic
tworzy kod działający szybciej X
niż kod produkowany przez do -march=X -mtune=X
(lub po prostu -march=X
, jak -mtune=X
sugeruje). 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=generic
jest 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.
-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/ ...
-march=native
oznacza tune=native
to 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.
tune=generic
dla 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.