Ряд программ умеют работать на простейшем из процессоров семейства, но использовать команды более новых процессоров, если появляется такая возможность. Пример: можно так собрать mplayer/mencoder, что он будет нормально работать на 386-ом, но если тот же файл запустить на Athlon 64 или Core, то задействуются возможности новых процессоров: MMX, SSE, SSE3 и т.д.
(Далее для простоты я рассматриваю программы в формате ELF, написанные на Си. Если не рассматривать бинарники в байткоде, принципиальных отличий не будет. А из наборов команд сверх минимального возьму только SSE.)
Насколько я понимаю, при запуске такой программы она проверяет возможности процессора и далее выбирает, какие версии функций вызывать: использующие SSE или не использующие. Правильно ли я понимаю, что не существует единого стандарта написания таких универсальных программ, и каждый разработчик изобретает что-то своё?
Нельзя ли поступить следующим образом?
- Если функцию выгодно собрать с поддержкой SSE, пускай компилятор скомпилирует 2 её варианта: быстрый с SSE и медленный без.
- Далее пускай в ELF слинкуются оба варианта.
- Перед запуском получившегося ELFа ОС должна проверить тип процессора, определить оптимальный из 2 вариантов функции и подставить его для каждого вызова этой функции.
Я правильно понимаю, что стандартный ELF такого не позволяет?
Получится нечто вроде FatELF. Но насколько я понял, FatELF — просто несколько склеенных бинарников. И Гордон (icculus) предлагал его для использования на несовместимых процессорах, вроде x86 и PPC, а не для односторонне совместимых, как Pentium и Pentium 3. В этом случае будет не склейка целых бинарников, а, скажем, одного варианта main(), одного варианта read_file() и двух вариантов decomperss().
Имеет ли это смысл? Пытался ли кто-либо так сделать? Планируется ли сделать подобное в FatELF?
В некоторых дистрибутивах в разные директории ставится несколько версий библиотеки: /usr/lib/i386/, /usr/lib/i686/cmov/, /usr/lib/i686/sse2/cmov/... А система при каждом запуске программы сканирует все эти директории и использует библиотеку, лучше всего соответствующую текущей конфигурации. Может, имеет смысл сделать всего один файл с несколькими вариантами критичных функций?
Если кто-то скажет, что такая проблема отомрёт с 32-разрядными x86, отвечу, что она уже назревает для x86_64. Та же Убунту сейчас собирает пакеты под «generic x86_64», что соответствует первым 64-разрядным Атлонам и Пентиумам. Авторы программ, желающие полнее использовать возможности новых процессоров, выкручиваются, кто во что горазд. Именно недавнее сравнение сорцовых и бинарных дистрибутивов вызвало данный вопрос.
P.S. С летним вас временем.