Qual è la differenza tra numeri in virgola mobile rigidi e morbidi?


98

Quando compilo il codice C con la mia toolchain incrociata, il linker stampa pagine di avvertimenti dicendo che il mio eseguibile utilizza float rigidi ma la mia libc usa float morbidi. Qual è la differenza?


Se è un'architettura ARM, inseriscila nei tag :-)
Nils Pipenbrinck

3
@Nils Pipenbrinck: Anche i chip MIPS hanno questo problema
Javier

Risposte:


100

Gli hard float utilizzano un'unità a virgola mobile su chip. I float morbidi ne emulano uno nel software. La differenza è la velocità. È strano vederli entrambi utilizzati sulla stessa architettura di destinazione, poiché il chip ha una FPU o no. Puoi abilitare il soft floating point in GCC con -msoft-float. Potresti voler ricompilare la tua libc per usare l'hardware in virgola mobile se la usi.


3
"È strano vedere entrambi usati sulla stessa architettura di destinazione" Può avere senso che una libreria sia indipendente dalla macchina e bit-esatta (soft float) in parti critiche per la precisione e veloce (hard float) in parti in cui si verificano piccole deviazioni importa.
PhilLab

Succede su ARM a 32 bit.
Aaron Franke

31

Esistono tre modi per eseguire operazioni aritmetiche in virgola mobile:

  • Usa istruzioni float se la tua CPU ha una FPU. (veloce)
  • Chiedi al tuo compilatore di tradurre l'aritmetica in virgola mobile in aritmetica intera. (lento)
  • Usa istruzioni float e una CPU senza FPU. La tua CPU genererà un'eccezione (istruzione riservata, istruzione non implementata o simili) e se il kernel del tuo sistema operativo include un emulatore a virgola mobile, emulerà quelle istruzioni (la più lenta).

23

A rigor di termini, tutte queste risposte mi sembrano sbagliate.

Quando compilo il codice C con la mia toolchain incrociata, il linker stampa pagine di avvertimenti dicendo che il mio eseguibile utilizza float rigidi ma la mia libc usa float morbidi. Qual è la differenza?

Il wiki Debian VFP contiene informazioni sulle tre scelte per -mfloat-abi,

  • soft - questo è puro software
  • softfp- questo supporta una FPU hardware, ma l' ABI è soft compatibile.
  • hard- l'ABI utilizza registri float o VFP .

L'errore del linker (caricatore) è dovuto al fatto che si dispone di una libreria condivisa che passerà i valori in virgola mobile nei registri interi. Puoi ancora compilare il tuo codice con -mfpu=vfp, ecc, ma dovresti usarlo in -mfloat-abi=softfpmodo che se la libc ha bisogno di un float, venga passato in un modo comprensibile dalla libreria.

Il kernel Linux può supportare l'emulazione delle istruzioni VFP. Ovviamente, è meglio compilare -mfpu=noneper questo caso e fare in modo che la compilazione generi il codice direttamente invece di fare affidamento su qualsiasi emulazione del kernel Linux. Tuttavia, non credo che l'errore dell'OP sia effettivamente correlato a questo problema. È separato e deve essere affrontato insieme al file -mfloat-abi.

La libreria condivisa Armv5 con CPU ArmV7 è l'opposto di questa; la libc era hard float ma l'applicazione era solo soft . Ha alcuni modi per aggirare il problema, ma la ricompilazione con le opzioni corrette è sempre la più semplice.

Un altro problema è che il kernel Linux deve supportare le attività VFP (o qualsiasi altra virgola mobile ARM presente) per salvare / ripristinare i registri su un cambio di contesto.


1
Le versioni moderne di GCC (~ 4.8 +) supportano 'multi-lib', che ha librerie hard float e soft float. Le versioni precedenti richiedevano che avessi un compilatore creato con una versione specifica. Occasionalmente è necessario il percorso per la libreria corretta quando ci si collega a una distribuzione gcc "multi-lib" poiché ci sono diverse versioni delle librerie (che richiedono più tempo per compilare il compilatore). I nomi delle directory potrebbero essere "hf", "hardf", "libhf" o "hard-float" ma di solito si trovano nella normale directory "soft" o in una posizione vicina.
rumore senza

Questa è la risposta esatta. La conversione di chiamata per i float deve corrispondere tra il tuo codice e libc. Potrebbe ancora funzionare con una mancata corrispondenza, se non si chiama mai alcuna funzione libc in virgola mobile.
Tor Klingberg

13

Sembra che la tua libc sia stata creata per operazioni software in virgola mobile mentre il tuo exe è stato compilato assumendo il supporto hardware per virgola mobile. A breve termine, potresti forzare i float morbidi come flag del compilatore. (se stai usando gcc penso che sia -msoft-float)

A lungo termine, se il processore del tuo obiettivo ha il supporto hardware per le operazioni in virgola mobile, generalmente vorrai costruire o trovare una toolchain incrociata con il float hardware abilitato per la velocità. Alcune famiglie di processori hanno varianti di modello alcune con e altre senza supporto hardware. Quindi, ad esempio, solo dire che il tuo processore è un ARM non è sufficiente per sapere se hai supporto hardware in virgola mobile.


8

Il calcolo può essere eseguito tramite hardware a virgola mobile o software basato sull'aritmetica dei numeri interi.

Farlo in hardware è molto più veloce, ma molti microcontrollori non hanno hardware a virgola mobile. In tal caso, è possibile evitare di utilizzare la virgola mobile (di solito l'opzione migliore) o fare affidamento su un'implementazione nel software, che farà parte della libreria C.

In alcune famiglie di controller, ad esempio ARM, l'hardware in virgola mobile è presente in alcuni modelli della famiglia ma non in altri, quindi gcc per queste famiglie supporta entrambi. Il tuo problema sembra essere che hai confuso le due opzioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.