Почему Mac ABI требует 16-байтового выравнивания стека для x86-32? - PullRequest
31 голосов
/ 05 марта 2009

Я могу понять это требование для старых систем PPC RISC и даже для x86-64, но для старых проверенных x86? В этом случае стек должен быть выровнен только по 4-байтовым границам. Да, некоторые инструкции MMX / SSE требуют выравнивания по 16 байт, но если это требование вызываемого абонента, то это должно гарантировать правильность выравнивания. Зачем обременять каждого абонента этим дополнительным требованием? На самом деле это может привести к некоторым падениям производительности, потому что каждый сайт вызова должен выполнить это требование. Я что-то упустил?

Обновление: После более подробного изучения этого вопроса и консультаций с некоторыми внутренними коллегами у меня появилось несколько теорий по этому поводу:

  1. Согласованность версий ОС для PPC, x86 и x64
  2. Кажется, что кодер GCC теперь последовательно выполняет sub esp, xxx и затем «перемещает» данные в стек, а не просто выполняет команду «push». Это может быть быстрее на некотором оборудовании.
  3. Хотя это немного усложняет сайты вызовов, при использовании соглашения по умолчанию «cdecl», когда вызывающий объект очищает стек, очень мало дополнительных служебных данных.

Проблема, с которой я столкнулся в связи с последним пунктом, заключается в том, что для соглашений о вызовах, которые основаны на очистке стека вызываемым абонентом, вышеуказанные требования действительно"убирают" коден. Например, какой компилятор решил реализовать более быстрый стиль вызовов на основе регистров для своего внутреннего использования (т. Е. Любой код, который не предназначен для вызова из других языков или источников)? Это выравнивание стека может свести на нет некоторые выигрыши в производительности, достигнутые путем передачи некоторых параметров в регистры.

Обновление: До сих пор единственными реальными ответами были последовательность, но для меня это слишком простой ответ. У меня более чем 20-летний опыт работы с архитектурой x86, и если причина в согласованности, а не в производительности или чем-то конкретном, то я с уважением полагаю, что для разработчиков это немного наивно. Они игнорируют почти три десятилетия инструментов и поддержки. Особенно, если они ожидают, что производители инструментов быстро и легко адаптируют свои инструменты для своей платформы (может быть, не ... это , это Apple ...) без необходимости перепрыгивать через несколько, казалось бы, ненужных пялец.

Я дам эту тему в другой день или около того, а затем закрою ...

Относящиеся

Ответы [ 10 ]

29 голосов
/ 22 мая 2009

Из «Справочного руководства по оптимизации архитектур Intel®64 и IA-32», раздел 4.4.2:

"Для обеспечения максимальной производительности потоковые SIMD-расширения и потоковые SIMD-расширения 2 требуют, чтобы их операнды памяти были выровнены по 16-байтовым границам. Нераспределенные данные могут привести к значительным потерям производительности по сравнению с выровненными данными."

Из приложения D:

"Важно обеспечить выравнивание кадра стека по 16-байтовой границе при входе в функцию, чтобы сохранить локальные данные __m128, параметры и местоположения разливов регистра XMM, выровненные по всему вызову функции."

http://www.intel.com/Assets/PDF/manual/248966.pdf

6 голосов
/ 07 мая 2009

Я не уверен, так как у меня нет доказательств из первых рук, но я считаю, что причина в SSE. SSE работает намного быстрее, если ваши буферы уже выровнены по 16-байтовой границе (movps vs movups), и любой x86 имеет как минимум sse2 для mac os x. Об этом может позаботиться пользователь приложения, но его стоимость довольно значительна. Если общие затраты на обязательность в ABI не слишком значительны, это может стоить того. SSE широко используется в Mac OS X: ускорение фреймворка и т. Д. *

5 голосов
/ 07 марта 2009

Я полагаю, что он должен быть согласован с x86-64 ABI.

3 голосов
/ 15 января 2010

Во-первых, обратите внимание, что выравнивание 16 байтов является исключением, введенным Apple в System V IA-32 ABI.

Выравнивание стека необходимо только при вызове системных функций, поскольку многие системные библиотеки используют расширения SSE или Altivec, для которых требуется выравнивание 16 байтов. Я нашел явную ссылку на странице libgmalloc MAN .

Вы можете отлично обрабатывать свой фрейм стека так, как вам хочется, но если вы попытаетесь вызвать системную функцию со смещенным стеком, вы получите сообщение misaligned_stack_error .

Edit: Для справки: вы можете избавиться от проблем с выравниванием при компиляции с GCC, используя опцию mstack-realign .

2 голосов
/ 25 января 2010

Я предполагаю, что Apple верит, что все просто используют XCode (gcc), который выравнивает стек для вас. Поэтому требование выравнивания стека, чтобы ядру не требовалось, - это просто микрооптимизация.

2 голосов
/ 08 января 2010

Это вопрос эффективности.

Проверка того, что стек выровнен по 16 байтов в каждой функции, использующей новые инструкции SSE, добавляет много накладных расходов для использования этих инструкций, эффективно снижая производительность.

С другой стороны, постоянное выравнивание 16-байтового стека гарантирует, что вы можете свободно использовать инструкции SSE без потери производительности. Там нет никаких затрат для этого (стоимость измеряется в инструкциях по крайней мере). Это включает только изменение константы в прологе функции.

Трата пространства стека стоит дешево, это, вероятно, самая горячая часть кэша.

1 голос
/ 22 мая 2009

Хотя я не могу ответить на ваш вопрос ПОЧЕМУ, вы можете найти руководства на следующем сайте полезными:

http://www.agner.org/optimize/

Что касается ABI, обратите особое внимание на:

http://www.agner.org/optimize/calling_conventions.pdf

Надеюсь, это полезно.

1 голос
/ 22 мая 2009

Хм, разве OS X ABI также не делает забавные RISC, такие как передача небольших структур в регистрах?

Таким образом, это указывает на соответствие теории других платформ.

Если подумать, API-интерфейс системного вызова FreeBSD также выравнивает 64-битные значения. (например, lseek и mmap)

0 голосов
/ 12 июля 2011

Не уверен, почему никто не рассмотрел возможность легкой переносимости с устаревшей платформы на основе PowerPC?

Читать это:

http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/100-32-bit_PowerPC_Function_Calling_Conventions/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-SW20

А затем увеличьте масштаб до «Соглашения о вызове 32-разрядной функции PowerPC» и, наконец, выполните следующее:

"Это режимы выравнивания встраивания, доступные в 32-битном режиме. Среда PowerPC:

Режим выравнивания мощности выводится из правил выравнивания, используемых Компилятор IBM XLC для операционной системы AIX. Это по умолчанию режим выравнивания для версии GCC с архитектурой PowerPC, используемой в AIX и Mac OS X. Потому что этот режим, скорее всего, будет совместимым между компиляторами архитектуры PowerPC от разных производителей, это обычно используется со структурами данных, которые разделяются между программы ".

С учетом унаследованного опыта OSX, основанного на PowerPC, переносимость является основным соображением - она ​​требует соблюдения соглашения вплоть до компилятора XLC AIX. Когда вы думаете о необходимости обеспечения того, чтобы все инструменты и приложения работали вместе с минимальными переделками, я думаю, что важно придерживаться того же устаревшего ABI, насколько это возможно.

Это дает философию, и чтение далее является правилом, явно упомянутым («Пролог и Эпилог»):

Вызываемая функция отвечает за распределение свой собственный кадр стека, сохраняя 16-байтовое выравнивание в стек. Эта операция выполняется разделом кода, который называется пролог, который компилятор помещает перед телом подпрограммы. После тела подпрограммы компилятор помещает эпилог в восстановить процессор до состояния, в котором он был до подпрограммы звоните.

0 голосов
/ 07 марта 2009

Для поддержания согласованности в ядре. Это позволяет загружать одно и то же ядро ​​на нескольких архитектурах без какой-либо модификации.

...