В чем разница между жесткими и мягкими числами с плавающей запятой?

98

Когда я компилирую код C с помощью своей кросс-инструментальной цепочки, компоновщик распечатывает страницы с предупреждениями о том, что мой исполняемый файл использует жесткие числа с плавающей запятой, а моя библиотека libc использует мягкие числа с плавающей запятой. Какая разница?

Эван Кроске
источник
Если это архитектура ARM, укажите это в тегах :-)
Нильс Пипенбринк
3
@Nils Pipenbrinck: чипы MIPS также имеют эту проблему
Хавьер,

Ответы:

100

Жесткие числа с плавающей запятой используют встроенный блок с плавающей запятой. Мягкие поплавки имитируют их в программном обеспечении. Разница в скорости. Странно видеть, что оба они используются в одной целевой архитектуре, поскольку чип либо имеет FPU, либо его нет. Вы можете включить мягкую плавающую точку в GCC с помощью -msoft-float. Вы можете перекомпилировать вашу libc для использования аппаратной с плавающей запятой, если вы ее используете.

Nmichaels
источник
3
«Странно видеть, что оба они используются в одной и той же целевой архитектуре». Это может иметь смысл для библиотеки, чтобы быть машинно-независимой и побитовой (soft float) в критических для точности частях и быстрой (hard float) в тех частях, где небольшие отклонения не имеет значения.
PhilLab
Это происходит на 32-битной ARM.
Аарон Франке
31

Есть три способа выполнить арифметику с плавающей запятой:

  • Используйте инструкции с плавающей запятой, если ваш процессор имеет FPU. (быстро)
  • Пусть ваш компилятор переведет арифметику с плавающей запятой в целочисленную. (медленный)
  • Используйте инструкции с плавающей запятой и ЦП без FPU. Ваш ЦП сгенерирует исключение (зарезервированная инструкция, нереализованная инструкция или подобное), и если ядро ​​вашей ОС включает эмулятор с плавающей запятой, он будет эмулировать эти инструкции (самый медленный).
Ninjalj
источник
23

Строго говоря, все эти ответы мне кажутся неправильными.

Когда я компилирую код C с помощью своей кросс-инструментальной цепочки, компоновщик распечатывает страницы с предупреждениями о том, что мой исполняемый файл использует жесткие числа с плавающей запятой, а моя библиотека libc использует мягкие числа с плавающей запятой. Какая разница?

Вики Debian VFP содержит информацию о трех вариантах -mfloat-abi:

  • soft - это чистый софт
  • softfp- это поддерживает аппаратный FPU, но ABI программно совместим.
  • hard- ABI использует регистры с плавающей запятой или VFP .

Ошибка компоновщика (загрузчика) связана с тем, что у вас есть общая библиотека, которая будет передавать значения с плавающей запятой в целочисленные регистры. Вы все еще можете скомпилировать свой код с помощью a -mfpu=vfpи т. Д., Но вы должны использовать его -mfloat-abi=softfpтак, чтобы, если libc требуется float, он передавался способом, понятным библиотеке.

Ядро Linux может поддерживать эмуляцию инструкций VFP. Очевидно, что -mfpu=noneв этом случае лучше выполнить компиляцию с использованием компилятора, генерирующего код напрямую, а не полагаться на какую-либо эмуляцию ядра Linux. Однако я не верю, что ошибка OP действительно связана с этой проблемой. Он отдельный, и с ним также нужно работать вместе с -mfloat-abi.

Совместно используемая библиотека Armv5 с процессором ArmV7 - противоположность этой; Libc было трудно поплавком , но применение только мягкое . У него есть несколько способов обойти эту проблему, но перекомпиляция с правильными параметрами всегда является самым простым.

Другая проблема заключается в том, что ядро ​​Linux должно поддерживать задачи VFP (или любую другую имеющуюся плавающую точку ARM) для сохранения / восстановления регистров при переключении контекста.

бесхитростный шум
источник
1
Современные версии GCC (~ 4.8+) поддерживают 'multi-lib', в которых есть библиотеки с жестким и мягким плаванием. Более ранние версии требовали, чтобы у вас был компилятор, построенный с определенной версией. Иногда путь к правильной библиотеке требуется при компоновке с «multi-lib» дистрибутивом gcc, так как существует несколько версий библиотек (требующих больше времени для сборки компилятора). Имена каталогов могут быть 'hf', 'hardf', 'libhf' или 'hard-float', но обычно они находятся в обычном 'soft' каталоге или в ближайшем месте.
бесхитростный шум
Это правильный ответ. Преобразование вызова для чисел с плавающей запятой должно соответствовать вашему коду и libc. Это может по-прежнему работать с несоответствием, если вы никогда не вызываете никаких функций libc с плавающей запятой.
Тор Клингберг
13

Похоже, ваша библиотека libc была создана для программных операций с плавающей запятой, в то время как ваш exe был скомпилирован с учетом аппаратной поддержки плавающей запятой. В краткосрочной перспективе вы можете использовать мягкие числа с плавающей запятой в качестве флага компилятора. (если вы используете gcc, я думаю, что это -msoft-float)

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

Digikata
источник
8

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

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

В некоторых семействах контроллеров, например ARM, оборудование с плавающей запятой присутствует в некоторых моделях семейства, но отсутствует в других, поэтому gcc для этих семейств поддерживает оба. Кажется, ваша проблема в том, что вы перепутали два варианта.

звездно-голубой
источник