Quelle est la différence entre les nombres à virgule flottante durs et souples?

98

Lorsque je compile du code C avec ma chaîne d'outils croisée, l'éditeur de liens imprime des pages d'avertissements indiquant que mon exécutable utilise des flottants fixes, mais ma libc utilise des flottants souples. Quelle est la différence?

Evan Kroske
la source
Si c'est l'architecture ARM, veuillez le mettre dans les balises :-)
Nils Pipenbrinck
3
@Nils Pipenbrinck: les puces MIPS ont également ce problème
Javier

Réponses:

100

Les flotteurs durs utilisent une unité à virgule flottante intégrée. Les flotteurs souples en émulent un dans le logiciel. La différence est la vitesse. Il est étrange de voir les deux utilisés sur la même architecture cible, car la puce a un FPU ou non. Vous pouvez activer la virgule flottante douce dans GCC avec -msoft-float. Vous pouvez recompiler votre libc pour utiliser la virgule flottante matérielle si vous l'utilisez.

nmichaels
la source
3
"Il est étrange de voir les deux utilisés sur la même architecture cible." Cela peut avoir du sens pour une bibliothèque d'être indépendante de la machine et peu exacte (flottement souple) dans les pièces critiques en précision et rapide (flottement dur) dans les pièces où de petits écarts ne sont pas peu importe.
PhilLab
Cela se produit sur ARM 32 bits.
Aaron Franke
31

Il existe trois façons de faire de l'arithmétique en virgule flottante:

  • Utilisez des instructions flottantes si votre CPU a un FPU. (vite)
  • Demandez à votre compilateur de traduire l'arithmétique à virgule flottante en arithmétique entière. (lent)
  • Utilisez des instructions flottantes et un CPU sans FPU. Votre CPU générera une exception (Instruction réservée, Instruction non implémentée ou similaire), et si votre noyau OS inclut un émulateur à virgule flottante, il émulera ces instructions (la plus lente).
ninjalj
la source
23

À proprement parler, toutes ces réponses me semblent fausses.

Lorsque je compile du code C avec ma chaîne d'outils croisée, l'éditeur de liens imprime des pages d'avertissements indiquant que mon exécutable utilise des flottants fixes, mais ma libc utilise des flottants souples. Quelle est la différence?

Le wiki Debian VFP contient des informations sur les trois choix pour -mfloat-abi,

  • soft - c'est un logiciel pur
  • softfp- cela prend en charge un FPU matériel, mais l' ABI est compatible avec le logiciel .
  • hard- l'ABI utilise des registres float ou VFP .

L'erreur de l'éditeur de liens (chargeur) est due au fait que vous disposez d'une bibliothèque partagée qui transmettra des valeurs à virgule flottante dans des registres d'entiers. Vous pouvez toujours compiler votre code avec a -mfpu=vfp, etc. mais vous devez l'utiliser -mfloat-abi=softfppour que si la libc a besoin d'un float, il soit passé d'une manière que la bibliothèque comprend.

Le noyau Linux peut prendre en charge l'émulation des instructions VFP. De toute évidence, vous feriez mieux de compiler avec -mfpu=nonedans ce cas et que la compilation génère directement du code au lieu de vous fier à une émulation de noyau Linux. Cependant, je ne pense pas que l'erreur du PO soit réellement liée à ce problème. Il est séparé et doit également être traité avec le -mfloat-abi.

La bibliothèque partagée Armv5 avec le processeur ArmV7 est l'opposé de celle-ci; la libc était hard float mais l'application n'était que douce . Il existe plusieurs moyens de contourner le problème, mais la recompilation avec les options correctes est toujours la plus simple.

Un autre problème est que le noyau Linux doit prendre en charge les tâches VFP (ou tout autre point flottant ARM présent) pour enregistrer / restaurer les registres sur un commutateur de contexte.

bruit naïf
la source
1
Les versions modernes de GCC (~ 4.8 +) supportent «multi-lib», qui ont des bibliothèques hard float et soft float. Les versions antérieures exigeaient que vous ayez un compilateur construit avec une version spécifique. Parfois, le chemin vers la bibliothèque correcte est nécessaire lors de la liaison avec une distribution gcc 'multi-lib' car il existe plusieurs versions des bibliothèques (nécessitant plus de temps pour construire le compilateur). Les noms de répertoire peuvent être «hf», «hardf», «libhf» ou «hard-float», mais ils se trouvent généralement sous le répertoire normal «soft» ou dans un emplacement à proximité.
bruit artless
C'est la bonne réponse. La conversion d'appel pour les flottants doit correspondre entre votre code et la libc. Cela peut toujours fonctionner avec une incompatibilité, si vous n'appelez jamais de fonctions libc en virgule flottante.
Tor Klingberg
13

Il semble que votre libc a été construite pour les opérations logicielles en virgule flottante tandis que votre exe a été compilé en supposant la prise en charge matérielle de la virgule flottante. À court terme, vous pouvez forcer les flottants souples comme indicateur de compilateur. (si vous utilisez gcc, je pense que c'est -msoft-float)

À plus long terme, si le processeur de votre cible prend en charge le matériel pour les opérations en virgule flottante, vous voudrez généralement créer ou trouver une chaîne d'outils croisée avec le flottement matériel activé pour la vitesse. Certaines familles de processeurs ont des variantes de modèle, certaines avec et d'autres sans support matériel. Ainsi, par exemple, il ne suffit pas de dire que votre processeur est un ARM pour savoir si vous avez un support matériel en virgule flottante.

Digikata
la source
8

Le calcul peut être effectué soit par du matériel à virgule flottante, soit par un logiciel basé sur l'arithmétique des nombres entiers.

Le faire dans le matériel est beaucoup plus rapide, mais de nombreux microcontrôleurs n'ont pas de matériel en virgule flottante. Dans ce cas, vous pouvez soit éviter d'utiliser la virgule flottante (généralement la meilleure option), soit vous fier à une implémentation dans un logiciel, qui fera partie de la bibliothèque C.

Dans certaines familles de contrôleurs, par exemple ARM, le matériel en virgule flottante est présent dans certains modèles de la famille mais pas dans d'autres, donc gcc pour ces familles prend en charge les deux. Votre problème semble être que vous avez mélangé les deux options.

starblue
la source