LINUX.ORG.RU
ФорумTalks

[ELF? FatELF?] Один бинарник на несколько похожих процессоров


0

0

Ряд программ умеют работать на простейшем из процессоров семейства, но использовать команды более новых процессоров, если появляется такая возможность. Пример: можно так собрать 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. С летним вас временем.

★★★★★

обьясню на примере Glibc (2.11)
strlen() (x86_64 asm)
вообщем не нужно знать ассемблер чтобы понять , что тут идет определение способностей процессора к sse2 и sse4.2 и соответственно вызов sse2 или sse4.2 оптимизированной функции

ENTRY(strlen)
.type strlen, @gnu_indirect_function
cmpl $0, __cpu_features+KIND_OFFSET(%rip)
jne 1f
call __init_cpu_features
1: leaq __strlen_sse2(%rip), %rax
testl $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip)
jz 2f
leaq __strlen_sse42(%rip), %rax
2: ret
END(strlen)

Sylvia ★★★★★ ()
Ответ на: комментарий от Sylvia

та же strlen для i686 vs sse2

ENTRY(strlen)
.type strlen, @gnu_indirect_function
pushl %ebx
cfi_adjust_cfa_offset (4)
cfi_rel_offset (ebx, 0)
call __i686.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
cmpl $0, KIND_OFFSET+__cpu_features@GOTOFF(%ebx)
jne 1f
call __init_cpu_features
1: leal __strlen_ia32@GOTOFF(%ebx), %eax
testl $(1<<26), CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_EDX_OFFSET+__cpu_features@GOTOFF(%e
bx)
jz 2f
leal __strlen_sse2@GOTOFF(%ebx), %eax
2: popl %ebx
cfi_adjust_cfa_offset (-4);
cfi_restore (ebx)
ret
END(strlen)

Sylvia ★★★★★ ()

если не флудить ассемблерными листингами, то нужно заметить что несколько версий для одной функции обычно пишут для того что или используется постоянно и повсеместно (glibc) или функций которые постоянно вызываются для обработки данных (кодек например или компрессор), там вполне работает то что выше на ассемблере, размер бинарников увеличивается незначительно, FatELF для этого - толсто )

Sylvia ★★★★★ ()
Ответ на: комментарий от Sylvia

> leaq __strlen_sse2(%rip), %rax

leaq __strlen_sse42(%rip), %rax

Я правильно понял, что вызываются отсюда?

Получается, тип процессора проверяется при каждом вызове strlen. На случай горячей замены?

question4 ★★★★★ ()
Ответ на: комментарий от question4

похоже на то , но как еще можно сделать так, чтобы библиотека работала на разных системах без перекомпиляции?

можно конечно сделать инициализацию 1 раз, а дальше проверять состояние глобальной переменной с флагами процессора, вот только переменная эта будет сидеть в системной памяти скорее всего, проще переопределить cpu_features заново

Sylvia ★★★★★ ()
Ответ на: комментарий от Sylvia

> несколько версий для одной функции обычно пишут для того что или используется постоянно и повсеместно (glibc) или функций которые постоянно вызываются для обработки данных (кодек например или компрессор),

Именно.

Но в данных случаях очевиден выигрыш при оптимизации под каждый процессор. А я всё спрашиваю, можно ли автоматически определять случаи, где есть смысл в такой оптимизации?

размер бинарников увеличивается незначительно, FatELF для этого - толсто

Ну не FatELF. Не все функции сдублированы. Не знаю, как назвать. Идея в том, чтобы выбирать тип процессора 1 раз, при первой загрузке соответствующего файла. И чтобы выбирала не программа, а ОС. Чтобы автоматически оптимизировалось.

question4 ★★★★★ ()
Ответ на: комментарий от Sylvia

> можно конечно сделать инициализацию 1 раз, а дальше проверять состояние глобальной переменной с флагами процессора, вот только переменная эта будет сидеть в системной памяти скорее всего, [быстрее] переопределить cpu_features заново

Для системной библиотеки — пожалуй.

А как насчёт программы, где можно проверять cpu_features, можно сравнивать с глобальной переменной, а можно задать глобальную переменную compress_address и сделать что-то вроде (синтаксис Intel):

mov rax, compress_address call rax

question4 ★★★★★ ()
Ответ на: комментарий от question4

я пока оставлю без комментариев это, я представляю себе физиологию, а не технические подробности, поэтому чтобы не писать ерунды, лучше подождать комментариев от тех, кто разбирается в этом лучше )

Sylvia ★★★★★ ()
Ответ на: комментарий от question4

> mov rax, compress_address call rax

В 2 строки:

mov rax, compress_address
call rax

question4 ★★★★★ ()

Ваша идея нежизнеспособна, потому что ставит разработчиков программ в зависимость от свежести ядра (ведь оно должно знать все фичи процессора, чтобы загрузить наиболее подходящую секцию кода приложения). А ядра у большинства пользователей имеют свойство обновляться раз в полгода (Ubuntu, Fedora), а то и гораздо реже (RHEL).

Relan ★★★★★ ()

Идея отдаёт душком гниения и яблок. Может ещё и универсальные пакеты со всеми зависимостями внутри клепать?

Lighting ★★★★★ ()

Разве это не задача компилятора, типа llvm?

Fredy ()

> Имеет ли это смысл?

Пожалуй, да.

Пытался ли кто-либо так сделать?

Никогда не слышал.

Планируется ли сделать подобное в FatELF?

FatELF вроде бы мертв.

tailgunner ★★★★★ ()
Ответ на: комментарий от Relan

> Ваша идея нежизнеспособна, потому что ставит разработчиков программ в зависимость от свежести ядра (ведь оно должно знать все фичи процессора, чтобы загрузить наиболее подходящую секцию кода приложения).

Интересующая нас часть загрузчика находится в userspace. И в любом случае, нужно знать только таблицу совместимости, чтобы для неизвестного типа процессора грузить секцию, в которой generic-код.

tailgunner ★★★★★ ()
Ответ на: комментарий от Lighting

> Идея отдаёт душком

яблок.

Вообще-то программы с поддержкой 80286, работавшие и на 8088, делались ещё во времена, когда Эпл прочно сидела на Моторолах и слазить не собиралась. Опять себе всю славу заграбастали :)

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

гниения

А это какая фирма?

Может ещё и универсальные пакеты со всеми зависимостями внутри клепать?

Да, в случаях, когда имеет смысл собирать программы статически, имеет смысл добавить несколько вариантов функций под разные процессоры.

question4 ★★★★★ ()
Ответ на: комментарий от tailgunner

>> Имеет ли это смысл?

Пожалуй, да.

Рад, что кто-то не отметает идею с ходу :)

FatELF вроде бы мертв.

Не совсем. Насколько я понял из вебсайта, приняли идею в штыки, автор не рассчитывает на скорое принятие в ванильное ядро и ванильную glibc, но работу потихоньку продолжает, надеясь переубедить отдельные дистрибутивы.

question4 ★★★★★ ()
Ответ на: комментарий от Fredy

> Разве это не задача компилятора, типа llvm?

Для LLVM программы компилируются в процессорно-независимый байткод? Тогда разговор не про них.

Да, важную роль тут должен играть компилятор. Поэтому я и спрашиваю, имеет ли смысл вынести выбор процессора на уровень ОС и автоматизировать для всех программ? Вне зависимости от того, вспомнил ли программист о возможности такого выбора. Чтобы glibc выбирала процессор один раз при старте системы, а не при каждом вызове строковой функции.

question4 ★★★★★ ()
Ответ на: комментарий от tailgunner

> Интересующая нас часть загрузчика находится в userspace.

Часть загрузчика не может находиться в user-space, потому что ядро должно стартовать первый процесс (init) без посторонней помощи. А если вынести загрузчик в отдельную библиотеку, то получится что чтобы загрузить эту библиотеку ядру нужно будет загрузить эту библиотеку. :)

Relan ★★★★★ ()
Ответ на: комментарий от question4

> кто-то не отметает идею с ходу :)

Выгоды надо мерять... технически, линкер может рассматривать relocation'ы только в секции, помеченные кодом соотвествующего процессора. Но, по сравнению со, скажем, вызовом через указатель, ты выигрываешь только одно косвенное обращение к памяти.

tailgunner ★★★★★ ()
Ответ на: комментарий от Relan

>> Интересующая нас часть загрузчика находится в userspace.

Часть загрузчика не может находиться в user-space

Она там уже лет 20 находится.

А если вынести загрузчик в отдельную библиотеку, то получится что чтобы загрузить эту библиотеку ядру нужно будет загрузить эту библиотеку. :)

man ld.so

man program interpreter

tailgunner ★★★★★ ()

Кстати, а почему тема не в Development?

tailgunner ★★★★★ ()
Ответ на: комментарий от Relan

> Ваша идея нежизнеспособна, потому что ставит разработчиков программ в зависимость от свежести ядра (ведь оно должно знать все фичи процессора, чтобы загрузить наиболее подходящую секцию кода приложения). А ядра у большинства пользователей имеют свойство обновляться раз в полгода (Ubuntu, Fedora), а то и гораздо реже (RHEL).

Обычно ядра в линуксе меняют всё же чаще, чем процессоры :) И да, как уже ответил tailgunner, это — в юзерспейсе.

Кроме того, процессор описывается набором флагов, показывающих, что для него оптимально. Для незнакомого процессора просто выберутся не все оптимальные функции. Альтернативы — никаких оптимальных, либо по бинарнику на каждый набор флагов.

Всё упирается скорее в скорость обновления компиляторов у разработчиков программ и сборщиков дистрибутивов.

question4 ★★★★★ ()

Тогда уж проще распространять ПО в виде промежуточного кода и компилировать при первом запуске или установке пакета.
Но плюсы перед непосредственно исходниками разве что в скорости компиляции и отстутсвия необходимости держать в системе кучу всего для сборки.

madcore ★★★★★ ()
Ответ на: комментарий от question4

> Для LLVM программы компилируются в процессорно-независимый байткод? Тогда разговор не про них.

Про них, сама машина оптимизируется под фитчи процессора.

Fredy ()
Ответ на: комментарий от tailgunner

> Кстати, а почему тема не в Development?

Потому, что не очень техническая :)

Лично мне это не нужно и в ближайшее время не понадобится — программы пишу для себя, либо они не требуют высокой производительности, чужие программы собираю под свой процессор (ага, Дженту). В разработке ядра, glibc или gcc не участвую. Просто возникла идея, решил выяснить её состоятельность.

Если кто-то это прочтёт и передаст идею Иккулусу или разработчикам GCC в понятной им форме, будет хорошо. А если нет, то нет. Максимум, на что меня хватит — добавить это пожелание в какие-нибудь багтрекеры.

question4 ★★★★★ ()
Ответ на: комментарий от question4

> Если кто-то это прочтёт и передаст идею Иккулусу или разработчикам GCC в понятной им форме, будет хорошо.

Я подозреваю, что они знают (идея вполне очевидна) :)

tailgunner ★★★★★ ()
Ответ на: комментарий от Fredy

> сама машина оптимизируется под фитчи процессора.

Верно. Сама машина — такая же программа, как и обсуждаемые. Но, имхо, там более жёсткие требования, её автоматизируют под каждый процессор вручную. Она сможет воспользоваться предлагаемым, но полагаться на одну автоматическую оптимизацию не сможет.

question4 ★★★★★ ()
Ответ на: комментарий от tailgunner

> Я подозреваю, что они знают (идея вполне очевидна) :)

Тогда подразумеваемый в первом посте вопрос: почему это до сих пор не пытались внедрить? Или пытались и пролетели? Или настолько боятся невежливого отказа, что и не пытались?

question4 ★★★★★ ()
Ответ на: комментарий от madcore

> Тогда уж проще распространять ПО в виде промежуточного кода и компилировать при первом запуске или установке пакета.

Фактически, так делают всякие виртуальные машины: Джава, Моно, LLVM. Почему на них до сих пор все не перешли — не знаю :)

question4 ★★★★★ ()
Ответ на: комментарий от Lighting

> Не фирма, а ОС - FreeBSD.

А они чем отличились? Помимо того, что их уже лет 12 безуспешно объявляют мёртвыми.

question4 ★★★★★ ()

>В некоторых дистрибутивах в разные директории ставится несколько версий библиотеки: /usr/lib/i386/, /usr/lib/i686/cmov/, /usr/lib/i686/sse2/cmov/...
Это в каких дистрах такое? Разница между i386 и i686 только в поддерживаемых инструкциях. Другими словами, программа скомпилированная под i386 прекрасно слинкуется с библиотекой скомпилированной под i686 и наоборот.

Может, имеет смысл сделать всего один файл с несколькими вариантами критичных функций?

Это имело бы смысл для статической компоновки или для библиотек поставляемых вместе с программой.

Я правильно понимаю, что стандартный ELF такого не позволяет?

И эльф и другие форматы позволяют хранить в исполняемых файлах какой угодно код в .code секции.

Перед запуском получившегося ELFа ОС должна проверить тип процессора

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

eugene2k ()
Ответ на: комментарий от question4

>> Я подозреваю, что они знают (идея вполне очевидна) :)

Тогда подразумеваемый в первом посте вопрос: почему это до сих пор не пытались внедрить?

Подозреваю, потому что расходы на внедрение (для котого нужны изменения в тулчейне и ld.so или ядре) просто не оправдывали потерю производительности на косвенный вызов.

tailgunner ★★★★★ ()
Ответ на: комментарий от question4

>> сама машина оптимизируется под фитчи процессора.

Верно. Сама машина — такая же программа, как и обсуждаемые. Но, имхо, там более жёсткие требования, её автоматизируют под каждый процессор вручную. Она сможет воспользоваться предлагаемым, но полагаться на одну автоматическую оптимизацию не сможет.

я о то что:

1. для большинства кода, чтобы пользоваться возможностями процессора, уже достаточно один раз скомпилить несколько виртуальных машин

2. сами машины можно устанавливать автоматически, через пакетную систему, не используя бесполезные проверки внутри самих программ.

3. всегда есть gentoo

4. если нужна автоматическая адаптация к фитчам конкретного процессора, то это, в любом случае, должно решаться через компилятор, а не через надстройку вроде fatELF

Fredy ()
Ответ на: комментарий от eugene2k

>> В некоторых дистрибутивах в разные директории ставится несколько версий библиотеки: /usr/lib/i386/, /usr/lib/i686/cmov/, /usr/lib/i686/sse2/cmov/...

Это в каких дистрах такое?

Это в Debian. А в каких дистрах этого _нет_?

tailgunner ★★★★★ ()
Ответ на: комментарий от eugene2k

> Это в каких дистрах такое?

Семейство Дебиана, вроде. Знаю с чужих слов.

Разница между i386 и i686 только в поддерживаемых инструкциях. Другими словами, программа скомпилированная под i386 прекрасно слинкуется с библиотекой скомпилированной под i686 и наоборот.

Ну да. В дистрибутив входит много взаимозаменяемых вариантов библиотеки. Выбирается самая навороченная библиотека из имеющихся и поддерживаемых процессором.

И эльф и другие форматы позволяют хранить в исполняемых файлах какой угодно код в .code секции.

Позволяют ли они загрузчику при запуске переконфигурировать программу и задать ей, которые из функций вызывать?

question4 ★★★★★ ()

1. Поскольку FatELF был каменован до рождения, простого способа загрузки секций под архитектуру нам не видать. Потому что надо заморачиваться с дописыванием-переписыванием ld.so. Это никому не уперлось.

2. Каждый раз в каждой подпрограмме опрашивать фичи процессора не то чтобы неэффективно, я допускаю, что cpuid срабатывает как молния, но очень уж тупо, и работает только в случаях, когда автор программы в явном виде знал, что делает. Но это, похоже, не то, чего хочет ТС, а ТС хочет, чтобы вожжи в руки мог взять тот, кто собирает/пакует программу.

3. Ergo, мы просто выносим все подпрограммы, которые выиграют от оптимизаций, в отдельную .so, как сделано в некоторых дистрибутивах с их зоопарком в /usr/lib, и немножко трахаемся с LD_PRELOAD и друзьями.

Результат, несмотря на зоопарк бинарников, тем не менее, лучше, так как все происходит достаточно прозрачно для конечного пользователя, и не менее прозрачно для изначального автора программы.

shimon ★★★★★ ()
Ответ на: комментарий от tailgunner

>> А если вынести загрузчик в отдельную библиотеку, то получится что чтобы загрузить эту библиотеку ядру нужно будет загрузить эту библиотеку. :)

man ld.so

man program interpreter

$ /lib/ld-linux.so.2 --list /lib/ld-linux.so.2    statically linked

Сам ld.so слинкован статически. Угадайте почему. :) А ТС предлагает повсеместно применять некий селектор оптимальных функций. Именно ввиду его «повсеместности» его невозможно вынести в user-space.

Relan ★★★★★ ()
Ответ на: комментарий от question4

> Обычно ядра в линуксе меняют всё же чаще, чем процессоры :) И да, как уже ответил tailgunner, это — в юзерспейсе.

Всё равно не понимаю, как это можно сделать в user-space. В случае с динамическим линкером это возможно благодаря тому, что есть 2 вида линковки: статическая (не требующая динамического линкера, всё делает ядро) и динамическая (используется линкер, который сам является статически слинкованным исполнимым файлом).

Relan ★★★★★ ()
Ответ на: комментарий от shimon

> каменован

Опечатка? Что-то туплю, какое здесь должно было быть слово?

2. Каждый раз в каждой подпрограмме опрашивать фичи процессора не то чтобы неэффективно, я допускаю, что cpuid срабатывает как молния, но очень уж тупо, и работает только в случаях, когда автор программы в явном виде знал, что делает.

Именно так и поступает glibc.

Но это, похоже, не то, чего хочет ТС, а ТС хочет, чтобы вожжи в руки мог взять тот, кто собирает/пакует программу.

Не совсем так. Чтобы большую часть работы проделывал компилятор. А ld.so ему помогал.

3. Ergo, мы просто выносим все подпрограммы, которые выиграют от оптимизаций, в отдельную .so, как сделано в некоторых дистрибутивах с их зоопарком в /usr/lib, и немножко трахаемся с LD_PRELOAD и друзьями.

Сейчас это сделано, но именно с опросом cpuid при каждом вызове.

надо заморачиваться с дописыванием-переписыванием ld.so.

Это никому не уперлось.

А если формат ELF не трогать? Перевалить всё на компилятор, пусть добавляется маленький рантайм, который при запуске вызовет cpuid и задаст адреса функций. Только не совсем представляю, как сделать это для динамических библиотек. Или у них есть какая-то программа для инициализации, вызываемая при первом обращении?

question4 ★★★★★ ()
Ответ на: комментарий от Relan

> селектор оптимальных функций. Именно ввиду его «повсеместности» его невозможно вынести в user-space.

Если селектор невелик, пусть будет не оптимальным, а совместимым :)

question4 ★★★★★ ()
Ответ на: комментарий от Relan

> Сам ld.so слинкован статически. Угадайте почему. :)

Зачем гадать? Я это просто знаю.

А ТС предлагает повсеместно применять некий селектор оптимальных функций. Именно ввиду его «повсеместности» его невозможно вынести в user-space.

Нельзя выбирать оптимальные функции только в самом ld.so, во всех остальных бинарях - можно.

tailgunner ★★★★★ ()
Ответ на: комментарий от question4

>Ну да. В дистрибутив входит много взаимозаменяемых вариантов библиотеки. Выбирается самая навороченная библиотека из имеющихся и поддерживаемых процессором.
зачем в таком случае хранить на диске несколько версий одной и той же функции различающихся только расширениями которые они поддерживают?

Позволяют ли они загрузчику при запуске переконфигурировать программу и задать ей, которые из функций вызывать?

Зачем?

eugene2k ()
Ответ на: комментарий от shimon

>2. Каждый раз в каждой подпрограмме опрашивать фичи процессора не то чтобы неэффективно, я допускаю, что cpuid срабатывает как молния, но очень уж тупо, и работает только в случаях, когда автор программы в явном виде знал, что делает. Но это, похоже, не то, чего хочет ТС, а ТС хочет, чтобы вожжи в руки мог взять тот, кто собирает/пакует программу.
что значит «очень уж тупо» и что значит «автор знал, что делает»?

eugene2k ()
Ответ на: комментарий от eugene2k

> зачем в таком случае хранить на диске несколько версий одной и той же функции различающихся только расширениями которые они поддерживают?

Бинарный дистрибутив — общий для всех архитектур совместимых с i386. Но старается повышать производительность, если конкретный процессор это позволяет. Почему ставятся все варианты библиотеки — вопрос к мэйнтэйнерам Дебиана. Причин можно придумать несколько, начиная с внезапной замены процессора :)

Позволяют ли они загрузчику при запуске переконфигурировать программу и задать ей, которые из функций вызывать?

Зачем?

Одна из причин — в первом посте :) Если существуют ещё какие-то причины так сделать, это могли сделать, поэтому и спросил. Существуют?

question4 ★★★★★ ()
Ответ на: комментарий от eugene2k

> что значит «очень уж тупо»

Примеры в начале:
http://www.linux.org.ru/jump-message.jsp?msgid=4708098&cid=4708148
http://www.linux.org.ru/jump-message.jsp?msgid=4708098&cid=4708154

Очень хочется проверять эти условия всего 1 раз — при запуске ОС :)

Не исключаю, что авторы glibc выбрали лучшее возможное решение. Но если так, хочу понять, почему оно лучшее.

что значит «автор знал, что делает»?


Озаботился сделать по варианту функции на каждый набор команд и такую проверку для выбора оптимальной функции. Хотелось бы, чтобы это делали компилятор и ОС (разделение этих функций между ними — отдельный вопрос).

question4 ★★★★★ ()
Ответ на: комментарий от question4

>Причин можно придумать несколько, начиная с внезапной замены процессора :)
Обычно процессор заменяется на более новый, а более новый обычно поддерживает больше инструкций, а не меньше. Особенно если без смены материнской платы это делается. Если же со сменой матплаты, то ничто не поможет если плата будет под спарки или что-то еще. Кроме того смена матплаты очень часто означает что и драйверы новые ставить придется. Другими словами в этом случае лучше написать программу запускающуюся при старте системы, проверяющую что изменилось и предлагающую удалить ненужные и установить необходимые компоненты системы.

Существуют?

ИМХО, нет.

eugene2k ()
Ответ на: комментарий от question4

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

Очень хочется проверять эти условия всего 1 раз — при запуске ОС :)

Можно вообще не проверять, если речь идет о динамической линковке к shared библиотекам, если нет, тогда статическая линковка к библиотеке с проверяющей функцией спасет тебя.

Не исключаю, что авторы glibc выбрали лучшее возможное решение. Но если так, хочу понять, почему оно лучшее.

Если вопрос в том почему в glibc идет проверка при каждом вызове функции вместо инициализации указателей на нужные функции и последующем экспорте их, то мне тоже интересно.

Озаботился сделать по варианту функции на каждый набор команд и такую проверку для выбора оптимальной функции. Хотелось бы, чтобы это делали компилятор и ОС (разделение этих функций между ними — отдельный вопрос).

Для динамической линковки достаточно чтобы программа запускалась из скрипта устанавливающего LD_PRELOAD в зависимости от архитектуры, для статической нет смысла это делать вообще, ибо FatELF лучше.

eugene2k ()
Ответ на: комментарий от eugene2k

ах да, забыл: «по варианту функции на каждый набор команд» - лучше сразу по варианту библиотеки на каждый набор команд, что вполне нормально делается в makefile.

eugene2k ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.