Я попытался почистить для этого справочную страницу GCC, но все равно не понял.
В чем разница между -march
и -mtune
?
Когда использовать только один -march
или оба варианта? Возможно ли когда-нибудь просто -mtune
?
Ответы:
Если вы используете, -march
то GCC сможет генерировать инструкции, которые работают на указанном ЦП, но (обычно) не на более ранних ЦП в семействе архитектуры.
Если вы просто используете -mtune
, то компилятор сгенерирует код, который работает на любом из них, но будет отдавать предпочтение последовательностям инструкций, которые выполняются быстрее всего на указанном вами конкретном процессоре. например, установка эвристики развертывания цикла для этого процессора.
-march=foo
подразумевает, -mtune=foo
если вы также не укажете другое -mtune
. Это одна из причин, почему использование -march
лучше, чем просто включение параметров, например, -mavx
без каких-либо действий по настройке.
Предостережение: -march=native
на процессоре, который GCC не распознает, будут по-прежнему доступны новые наборы инструкций, которые GCC может обнаружить, но они останутся -mtune=generic
. Используйте достаточно новый GCC, который знает о вашем процессоре, если вы хотите, чтобы он делал хороший код.
march
подразумевается mtune
. Итак, ответы на ваши возражения - нет и да соответственно.
mtune
и march
комбинации. Это сообщение в блоге освещает этот момент вместе с другими: lemire.me/blog/2018/07/25/…
Вот что я погуглил:
Эта -march=X
опция принимает имя ЦП X
и позволяет GCC генерировать код, использующий все функции X
. Руководство GCC объясняет, какие именно имена ЦП означают, какие семейства ЦП и функции.
Поскольку функции обычно добавляются, но не удаляются, двоичный файл, созданный с помощью, -march=X
будет работать на ЦП X
, имеет хорошие шансы работать на ЦП новее X
, но почти наверняка он не будет работать на чем-либо старше X
. Некоторые наборы инструкций (3DNow !, я полагаю?) Могут быть специфичными для конкретного поставщика ЦП, их использование, вероятно, даст вам двоичные файлы, которые не работают на конкурирующих ЦП, более новых или иных.
Эта -mtune=Y
опция настраивает сгенерированный код так, чтобы он работал быстрее, Y
чем на других процессорах, на которых он мог бы работать. -march=X
подразумевает -mtune=X
. -mtune=Y
не будет переопределяться -march=X
, поэтому, например, вероятно, нет смысла -march=core2
и -mtune=i686
- ваш код не будет работать на чем-то более старом, чем в core2
любом случае, из-за того -march=core2
, почему вы хотите оптимизировать для чего-то более старого (менее функционального), чем core2? -march=core2 -mtune=haswell
имеет больше смысла: не используйте никаких функций, кроме того, что core2
предоставляет (что по-прежнему намного больше, чем то, что -march=i686
дает вам!), но оптимизируйте код для гораздо более новых haswell
процессоров, а не для core2
.
Также есть -mtune=generic
. generic
заставляет GCC создавать код, который лучше всего работает на текущих процессорах (имеется в виду generic
изменения от одной версии GCC к другой). На форумах Gentoo ходят слухи, что -march=X -mtune=generic
код работает быстрее, X
чем код, созданный самим -march=X -mtune=X
(или просто -march=X
, как -mtune=X
подразумевается). Не знаю, правда это или нет.
Как правило, если вы точно не знаете, что вам нужно, кажется, что лучше всего указать -march=<oldest CPU you want to run on>
и -mtune=generic
( -mtune=generic
здесь, чтобы противостоять неявному -mtune=<oldest CPU you want to run on>
, потому что вы, вероятно, не хотите оптимизировать для самого старого процессора). Или просто -march=native
, если вы когда-нибудь собираетесь работать только на той же машине, на которой построили.
-march=native
, вы можете указать -mtune=X
, потому что по умолчанию все еще -mtune=generic
, как обсуждается здесь: lemire.me/blog/2018/07/25/…
-march=native
подразумевает tune=native
просто отлично, если вы используете GCC, который знает о вашем процессоре. Эта статья представляет только плохой случай. Более новые версии GCC в целом улучшают код, особенно при использовании новых инструкций, таких как AVX2 и AVX-512. И наличие настроек (например, эвристики развертки цикла), разработанных для вашего процессора, является несомненным плюсом. Поэтому, если вы достаточно заботитесь о производительности, чтобы использовать эти параметры, используйте новый GCC, по крайней мере, тот, который знает о вашем процессоре, предпочтительно текущий стабильный выпуск.
tune=generic
для нового члена того же семейства микроархитектур, особенно для чего-то вроде Kaby Lake, которое буквально идентично микроархитектуре Skylake. Но я думаю, что у него все еще другое семейство / степпинг, поэтому GCC, который знал только о Skylake и старше, мог не распознать его для настройки.