2012-05-21 3 views
12

-freciprocal-math in GCC cambia il seguente codicePerché è -freciprocal-math non sicuro in GCC?

double a = b/c; 

a

double tmp = 1/c; 
double a = b * tmp; 

Nel manuale di GCC, si dice che una tale ottimizzazione è pericoloso e non è incollata agli standard IEEE. Ma non riesco a pensare ad un esempio. Puoi dare un esempio a riguardo?

+1

Considerare b = c = 3 –

+0

I IEEE non dispone di regole su come un compilatore deve utilizzare il punto mobile. Ad esempio, X^2 è spesso ridotto a X * X con intensità ridotta producendo programmi in genere più veloci ma con errore diverso dal calcolo specificato dal programmatore originale. Quindi, @Kid, hai guardato lo standard IEEE per vedere quali limiti pone ai compilatori che utilizzano tale aritmetica? –

+0

@RaymondChen: dopo aver applicato l'arrotondamento IEEE (su? Giù? Pari? Nessuno?), L'esempio b = c = 3 potrebbe non produrre esattamente lo stesso risultato in a? –

risposta

12

Dividendo per 10 e moltiplicando per 0.1000000000000000055511151231257827021181583404541015625 non sono la stessa cosa.

+0

Vero, non lo è. Ma allora il punto fluttuante non ti dà una risposta precisa se dividi per dieci. Quindi l'argomento qui sembra essere quanto errore si è disposti ad accettare nella propria aritmetica in virgola mobile. Se si esegue il float IEEE standard, si ottiene una certa quantità di errori nel calcolo (inclusa la completa perdita di precisione in determinate circostanze). Se si esegue la matematica reciproca, non si ottiene un errore in virgola mobile definito da IEEE; se ottieni più o meno dipenderà dall'effettivo calcolo che stai facendo. –

+1

@IraBaxter, divisione fornisce un risultato preciso se entrambi gli operandi sono esattamente rappresentati, quali saranno per i valori interi. –

+0

@MarkRansom: Uh, come faccio a ottenere un risultato preciso (intendo esattamente?) Per "1.0/3.0"? –

0

Forse sto pensando di un diverso flag di compilazione, ma ...

Alcuni processori hanno istruzioni per il calcolo del reciproco approssimativa. Viene in mente RCPSS om x86 (istruzione SIMD); ha un errore relativo 1.5 * 2^-12. L'uso di questo flag può consentire al compilatore di selezionare un'istruzione reciproca approssimativa, che potrebbe non essere una cosa sicura da fare a seconda dell'applicazione.

Spero che questo aiuti.

+0

Con GCC, questo è il flag -mrecip. – janneb