В Линуксе 3.4 запилили новую фенечку: X32 ABI
Как известно, процессор архитектуры x86_64 под управлением 64-разрядной ОС может работать в двух режимах: Long Mode (для нормальных 64-разрядных приложений) и Compatibility Mode (в котором выполняются 32-разрядные программы, скомпилированные в далеком 1995 году из расчёта на 32-битное ядро и процессор). Например, в ОС Windows, Compatibility Mode является аппаратной подпоркой для программной подсистемы WoW64.
Классический 32-разрядный режим, совместимый с классическими 32-разрядными процессорами, имеет свои плюсы и минусы.
+ меньший расход памяти для тех же приложений в 64-битном виде
+ из-за лучшего попадания данных в кэш: более высокая скорость работы
– малый регистровый файл: это снижает скорость работы
– большое количество расширений архитектуры i386, поддержка которых в компиляторе по дефолту отключена: это снижает скорость работы
Например, в 64-разрядном режиме gcc активно использует регистры SSE2 (XMMn), для предвыборки значений из памяти, которые вскоре понадобятся; ну и просто для хранения локальных переменных, не влезающих в основной регистровый файл. Для i386 эти регистры доступны не всегда, и эта фича компилятора требует тонкой настройки с помощью опций -march и -mtune.
Новый способ вызова ядра под названием X32 ABI работает так: процессор работает в Long Mode, но sizeof(void*)==4. Пользовательской программе доступны 4 первых Гб в начале 64-разрядного адресного пространства. Остальные страницы вплоть до адреса 0x7FFF`FFFF`FFFF`FFFF включительно — никогда не отображены. Ядро, как обычно, задействует для своих целей адреса, старше чем 0x8000`0000`0000`0000, ввиду аппаратных ограничений современных процессоров — это адреса, близкие к виртуальному адресу 0xFFFF`FFFF`FFFF`FFFF. Страница VDSO отображена в первые 4 виртуальных гигабайта.
Таким образом, адресное пространство практически такое же как для 32-разрядных программ. Так каков смысл затеи? Ну, профит в удвоенном количестве регистров общего назначения, а также в наличии старшей 32-разрядной части 64-разрядных регистров (которая программно доступна в Long Mode, игнорируется системными вызовами ядра, но сохраняется ядром при переключении контекста) — эта старшая часть может использоваться компилятором для хранения локальных переменных, также у нас всегда есть XMM-регистры и их вдвое больше, чем в "чистом" 32-разрядном режиме (доступны XMM8..XMM15). Общий эффект заключается в снижении регистрового давления при той же эффективности использования памяти, что и в i386 (все указатели — 32-разрядные), ну и в целом бинарики станут чуть быстрее, т.к. всё равно почти никто не возится с -march и -mtune (особенно это касается шаредлиб).
Надо ли это вообще? Ну, пуристы из FreeBSD никогда на такое не согласятся — эпоха 32-разрядных вычислений на x86 подходит к концу; но в Линуксе должно быть всё!
Ведь если подумать, прожорливые по памяти программы всё равно должны быть собраны в 64-разрядном режиме (2-4 Гб им в конечном итоге мало), ну а те проги, которые кушают мало памяти, выиграют от X32 ABI незначительно: ну, к примеру, рабочий набор какой-нибудь ls в x86_64 исполнении составляет 32 Мбайт, мы перекомпилировали её под X32 ABI и рабочий набор стал 24 Мбайт. Много ли значит выигрыш 8 Мбайт на современном десктопе?
В сухом остатке, в X32 ABI мы имеем best of both worlds только по скорости — этому способствует как большой регистровый файл, так и более вероятное попадание в кэш указателей уменьшенного размера в условиях уменьшенного оверхеда на выравнивание.
Как известно, процессор архитектуры x86_64 под управлением 64-разрядной ОС может работать в двух режимах: Long Mode (для нормальных 64-разрядных приложений) и Compatibility Mode (в котором выполняются 32-разрядные программы, скомпилированные в далеком 1995 году из расчёта на 32-битное ядро и процессор). Например, в ОС Windows, Compatibility Mode является аппаратной подпоркой для программной подсистемы WoW64.
Классический 32-разрядный режим, совместимый с классическими 32-разрядными процессорами, имеет свои плюсы и минусы.
+ меньший расход памяти для тех же приложений в 64-битном виде
+ из-за лучшего попадания данных в кэш: более высокая скорость работы
– малый регистровый файл: это снижает скорость работы
– большое количество расширений архитектуры i386, поддержка которых в компиляторе по дефолту отключена: это снижает скорость работы
Например, в 64-разрядном режиме gcc активно использует регистры SSE2 (XMMn), для предвыборки значений из памяти, которые вскоре понадобятся; ну и просто для хранения локальных переменных, не влезающих в основной регистровый файл. Для i386 эти регистры доступны не всегда, и эта фича компилятора требует тонкой настройки с помощью опций -march и -mtune.
Новый способ вызова ядра под названием X32 ABI работает так: процессор работает в Long Mode, но sizeof(void*)==4. Пользовательской программе доступны 4 первых Гб в начале 64-разрядного адресного пространства. Остальные страницы вплоть до адреса 0x7FFF`FFFF`FFFF`FFFF включительно — никогда не отображены. Ядро, как обычно, задействует для своих целей адреса, старше чем 0x8000`0000`0000`0000, ввиду аппаратных ограничений современных процессоров — это адреса, близкие к виртуальному адресу 0xFFFF`FFFF`FFFF`FFFF. Страница VDSO отображена в первые 4 виртуальных гигабайта.
Таким образом, адресное пространство практически такое же как для 32-разрядных программ. Так каков смысл затеи? Ну, профит в удвоенном количестве регистров общего назначения, а также в наличии старшей 32-разрядной части 64-разрядных регистров (которая программно доступна в Long Mode, игнорируется системными вызовами ядра, но сохраняется ядром при переключении контекста) — эта старшая часть может использоваться компилятором для хранения локальных переменных, также у нас всегда есть XMM-регистры и их вдвое больше, чем в "чистом" 32-разрядном режиме (доступны XMM8..XMM15). Общий эффект заключается в снижении регистрового давления при той же эффективности использования памяти, что и в i386 (все указатели — 32-разрядные), ну и в целом бинарики станут чуть быстрее, т.к. всё равно почти никто не возится с -march и -mtune (особенно это касается шаредлиб).
Надо ли это вообще? Ну, пуристы из FreeBSD никогда на такое не согласятся — эпоха 32-разрядных вычислений на x86 подходит к концу; но в Линуксе должно быть всё!
Ведь если подумать, прожорливые по памяти программы всё равно должны быть собраны в 64-разрядном режиме (2-4 Гб им в конечном итоге мало), ну а те проги, которые кушают мало памяти, выиграют от X32 ABI незначительно: ну, к примеру, рабочий набор какой-нибудь ls в x86_64 исполнении составляет 32 Мбайт, мы перекомпилировали её под X32 ABI и рабочий набор стал 24 Мбайт. Много ли значит выигрыш 8 Мбайт на современном десктопе?
В сухом остатке, в X32 ABI мы имеем best of both worlds только по скорости — этому способствует как большой регистровый файл, так и более вероятное попадание в кэш указателей уменьшенного размера в условиях уменьшенного оверхеда на выравнивание.