Нужно ли создавать несколько исполняемых файлов для целевых наборов команд?

Предположим, у меня есть программа для выполнения операций AES.

Некоторые продвинутые процессоры имеют набор команд AES-NI, а другие — нет.

Должен ли я скомпилировать мою программу в два исполняемых файла: A_with_aes_ni.exe и B_without_aes_ni.exe?

5

Решение

То, что вы хотите, называется диспетчером ЦП. Агнер Фог имеет 10 страниц текста по этому вопросу в третьей главе «Создание критического кода в нескольких версиях для разных наборов команд» своего Руководство по оптимизации C ++ . Он обсуждает это как с GCC, так и с ICC.

Вам нужен только один исполняемый файл, но вам нужно скомпилировать два разных объектных файла с включенной AES и без нее. Затем диспетчер определяет, какой набор инструкций доступен, и выбирает путь кода на основании этого.

Я пытался сделать это с MSVC2010 Диспетчер процессора для Visual Studio для AVX и SSE но не удалось. Я подозреваю, что мог бы заставить это работать теперь все же.

Редактировать:
В Agner Fog’s vectorclass у него есть файл dispatch_example.cpp а также instrset_detech.cpp который должен иметь большую часть того, что нужно сделать диспетчеру. Вам все еще нужно выяснить, как определить, есть ли у процессора AES. Вам необходимо увеличить файл intrset_detect.cpp. В соответствии с википедия когда вы читаете CPUID, бит 23 в регистре ECX устанавливается, если у CPU есть AES. В Википедии также есть примеры кода для чтения CPUID (помимо instrset_detech.cpp — еще один хороший пример в https://github.com/Mysticial/Flops в файле cpuid.c)

6

Другие решения

Один из способов сделать это в Solaris — это иметь библиотеки аппаратных возможностей,
которые динамически загружаются компоновщиком во время выполнения.

Другой вариант — сначала загрузить обработчик прерываний для недопустимых инструкций, а затем проверить нужные инструкции на машинном языке. Если вы попали в ловушку,
тогда вы знаете, что не можете использовать оптимизированную версию и должны загружать неоптимизированную (или менее оптимизированную).

Хотя мне нравится предложение Эндрю выше, я думаю, что безопаснее проверить
конкретные инструкции, которые вам нужны. Таким образом, вам не нужно постоянно обновлять
ваше приложение для более нового вывода CPUID.

Отредактировано, чтобы добавить:
Я понимаю, что должен был привести пример. Для Соляриса libc на x64
платформу, мы предоставляем hw-оптимизированные версии библиотеки — три для
32 бита, один для 64 бита. Мы можем увидеть различия, запустив elfdump -H
на интересующий файл:

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap1.so.1

Capabilities Section:  .SUNW_cap

Object Capabilities:
index  tag               value
[0]  CA_SUNW_HW_1     0x86d  [ SSE MMX CMOV SEP CX8 FPU ]

Symbol Capabilities:
index  tag               value
[2]  CA_SUNW_ID       hrt
[3]  CA_SUNW_HW_1     0x40002  [ TSCP TSC ]

Symbols:
index    value      size      type bind oth ver shndx          name
[1]  0x000f306c 0x00000225  FUNC LOCL  D    0 .text          gettimeofday%hrt
[2]  0x000f2efc 0x00000165  FUNC LOCL  D    0 .text          gethrtime%hrt

Capabilities Chain Section:  .SUNW_capchain

Capabilities family: gettimeofday
chainndx  symndx      name
1  [702]       gettimeofday
2  [1]         gettimeofday%hrt

Capabilities family: gethrtime
chainndx  symndx      name
4  [1939]      gethrtime
5  [2]         gethrtime%hrt

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap2.so.1

Capabilities Section:  .SUNW_cap

Object Capabilities:
index  tag               value
[0]  CA_SUNW_HW_1     0x1875  [ SSE2 SSE MMX CMOV AMD_SYSC CX8 FPU ]

Symbol Capabilities:
index  tag               value
[2]  CA_SUNW_ID       hrt
[3]  CA_SUNW_HW_1     0x40002  [ TSCP TSC ]

Symbols:
index    value      size      type bind oth ver shndx          name
[1]  0x000f253c 0x00000225  FUNC LOCL  D    0 .text              gettimeofday%hrt
[2]  0x000f23cc 0x00000165  FUNC LOCL  D    0 .text          gethrtime%hrt

Capabilities Chain Section:  .SUNW_capchain

Capabilities family: gettimeofday
chainndx  symndx      name
1  [702]       gettimeofday
2  [1]         gettimeofday%hrt

Capabilities family: gethrtime
chainndx  symndx      name
4  [1939]      gethrtime
5  [2]         gethrtime%hrt

Угадайте, что из перечисленного выше для систем AMD, а что для Intel?

У компоновщика Solaris есть смарты для загрузки правильной библиотеки hwcap во время выполнения
до того, как ваш процесс ‘_init () вызывается.

2

По вопросам рекламы [email protected]