GCC: чем марш отличается от mtune?

88

Я попытался почистить для этого справочную страницу GCC, но все равно не понял.

В чем разница между -marchи -mtune?

Когда использовать только один -marchили оба варианта? Возможно ли когда-нибудь просто -mtune?

Джеймсон
источник

Ответы:

97

Если вы используете, -marchто GCC сможет генерировать инструкции, которые работают на указанном ЦП, но (обычно) не на более ранних ЦП в семействе архитектуры.

Если вы просто используете -mtune, то компилятор сгенерирует код, который работает на любом из них, но будет отдавать предпочтение последовательностям инструкций, которые выполняются быстрее всего на указанном вами конкретном процессоре. например, установка эвристики развертывания цикла для этого процессора.


-march=fooподразумевает, -mtune=fooесли вы также не укажете другое -mtune. Это одна из причин, почему использование -marchлучше, чем просто включение параметров, например, -mavxбез каких-либо действий по настройке.

Предостережение: -march=nativeна процессоре, который GCC не распознает, будут по-прежнему доступны новые наборы инструкций, которые GCC может обнаружить, но они останутся -mtune=generic. Используйте достаточно новый GCC, который знает о вашем процессоре, если вы хотите, чтобы он делал хороший код.

Джеймс Янгман
источник
10
Не отвечает, имеет ли смысл использовать и то, и другое, или mtune является избыточным, если установлено одинаковое значение.
Павел Шимерда
12
@ PavelŠimerda Интуитивно ответ подразумевается в определении двух функций. Кроме того, в документации прямо указано, что marchподразумевается mtune. Итак, ответы на ваши возражения - нет и да соответственно.
underscore_d
Спасибо, что объяснили это так красиво! Вы упрощаете понимание.
Рахим Ходжа
5
Людям нужен tl; dr: используйте -march, если вы ТОЛЬКО запускаете его на своем процессоре, используйте -mtune, если хотите, чтобы он был безопасным для других процессоров.
j
3
Кроме того, пользователи должны понимать , что старые компиляторы (выпущенные до некоторого CPU не существовало) , может привести к различным оптимальным mtuneи marchкомбинации. Это сообщение в блоге освещает этот момент вместе с другими: lemire.me/blog/2018/07/25/…
qneill
52

Вот что я погуглил:

Эта -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, если вы когда-нибудь собираетесь работать только на той же машине, на которой построили.

LRN
источник
4
Но если вы используете -march=native, вы можете указать -mtune=X, потому что по умолчанию все еще -mtune=generic, как обсуждается здесь: lemire.me/blog/2018/07/25/…
Роланд Вебер
@RolandWeber: Это происходит только в том случае, если вы используете GCC, слишком старый, чтобы знать о вашем процессоре. -march=nativeподразумевает tune=nativeпросто отлично, если вы используете GCC, который знает о вашем процессоре. Эта статья представляет только плохой случай. Более новые версии GCC в целом улучшают код, особенно при использовании новых инструкций, таких как AVX2 и AVX-512. И наличие настроек (например, эвристики развертки цикла), разработанных для вашего процессора, является несомненным плюсом. Поэтому, если вы достаточно заботитесь о производительности, чтобы использовать эти параметры, используйте новый GCC, по крайней мере, тот, который знает о вашем процессоре, предпочтительно текущий стабильный выпуск.
Питер Кордес,
Отстойно, что GCC не может сделать ничего лучше, чем tune=genericдля нового члена того же семейства микроархитектур, особенно для чего-то вроде Kaby Lake, которое буквально идентично микроархитектуре Skylake. Но я думаю, что у него все еще другое семейство / степпинг, поэтому GCC, который знал только о Skylake и старше, мог не распознать его для настройки.
Питер Кордес,