Яка різниця між твердими та м’якими числами із плаваючою комою?


98

Коли я компілюю код C моїм перехресним ланцюжком інструментів, компонувальник друкує сторінки з попередженнями про те, що мій виконуваний файл використовує жорсткі поплавки, але мій libc використовує м'які поплавки. Яка різниця?


Якщо це архітектура ARM, будь ласка,
впишіть

3
@Nils Pipenbrinck: У мікросхем MIPS також є ця проблема
Хав'єр

Відповіді:


100

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


3
"Дивно бачити, як використовуються в одній цільовій архітектурі". Це може мати сенс для бібліотеки бути машинно незалежною і біточною (м'який поплавк) в критично важливих частинах і швидкий (жорсткий поплавок) в частинах, де невеликі відхилення не мають не має значення.
PhilLab

Це відбувається на 32-розрядному ARM.
Аарон Франке

31

Існує три способи арифметики з плаваючою комою:

  • Використовуйте плаваючі інструкції, якщо ваш процесор має FPU. (швидко)
  • Нехай ваш компілятор перекладе арифметику з плаваючою комою в цілу арифметику. (повільно)
  • Використовуйте плаваючі інструкції та центральний процесор без FPU. Ваш процесор створить виняток (Зарезервована інструкція, Невиконана інструкція або подібне), і якщо ваше ядро ​​ОС містить емулятор з плаваючою комою, воно буде імітувати ці вказівки (найповільніші).

23

Власне кажучи, всі ці відповіді здаються мені неправильними.

Коли я компілюю код C моїм перехресним ланцюжком інструментів, компонувальник друкує сторінки з попередженнями про те, що мій виконуваний файл використовує жорсткі поплавки, але мій libc використовує м'які поплавки. Яка різниця?

Вікі-програма Debian VFP містить інформацію про три варіанти -mfloat-abi,

  • soft - це чисте програмне забезпечення
  • softfp- це підтримує апаратний FPU, але ABI сумісний із програмним забезпеченням.
  • hard- ABI використовує плаваючі або VFP регістри.

Помилка лінкера (навантажувача) пов’язана з тим, що у вас є спільна бібліотека, яка передаватиме значення з плаваючою комою в цілочисельні регістри. Ви все ще можете скомпілювати свій код за допомогою -mfpu=vfpі т.д., але ви повинні використовувати -mfloat-abi=softfpтак, щоб, якщо libc потребує плаваючої форми, він передавався так, як це розуміє бібліотека.

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

Спільна бібліотека Armv5 із процесором ArmV7 є протилежністю цій; Libc було важко поплавком , але застосування тільки м'яке . У ньому є кілька способів вирішити проблему, але перекомпіляція з правильними параметрами завжди є найпростішою.

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


1
Сучасні версії GCC (~ 4.8 +) підтримують "multi-lib", які мають бібліотеки жорсткого плаваючого та плавного плаваючого середовища. У попередніх версіях потрібно було створити компілятор із певною версією. Іноді шлях до правильної бібліотеки потрібен під час зв’язку з розподілом gcc “multi-lib”, оскільки існує декілька версій бібліотек (для побудови компілятора потрібно більше часу). Імена каталогів можуть бути "hf", "hardf", "libhf" або "hard-float", але вони, як правило, знаходяться в звичайному "м'якому" каталозі або поблизу.
бездумний шум

Це правильна відповідь. Перетворення викликів для плаваючих значень має відповідати вашому коду та libc. Це все одно може працювати з невідповідністю, якщо ви ніколи не викликаєте жодної функції libc з плаваючою комою.
Тор Клінгберг,

13

Схоже, ваш libc був створений для програмних операцій з плаваючою комою, тоді як ваш exe був складений, передбачаючи апаратну підтримку з плаваючою комою. У короткостроковій перспективі ви можете примусити м'які плаваючі функції як прапор компілятора. (якщо ви використовуєте gcc, я думаю, що це -msoft-float)

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


8

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

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

У деяких сімействах контролерів, наприклад ARM, апаратне забезпечення з плаваючою точкою присутнє в деяких моделях сімейства, але не в інших, тому gcc для цих сімей підтримує обидва. Здається, ваша проблема полягає в тому, що ви змішали два варіанти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.