2013-02-28 7 views
34

nell'ultimo aggiornamento delle API di Android il FloatMath è contrassegnato con il seguente lint-avvertimento:Utilizzo di FloatMath o Math e un cast?

Nelle versioni precedenti di Android, utilizza android.util.FloatMath era consigliata per motivi di prestazioni quando si lavora su carri. Tuttavia, lo standard su hardware moderno è veloce quanto float (anche se prendono più memoria ), e nelle ultime versioni di Android, FloatMath è in realtà più lento dell'utilizzo di java.lang.Math a causa del modo in cui JIT ottimizza java .lang.Math. Pertanto, dovresti utilizzare Math invece di FloatMath se hai scelto come target solo Froyo e versioni successive.

Viene anche menzionato here che doppio e float hanno uguale velocità sull'hardware recente.

Sto usando alcuni calcoli trigonometrici in un'applicazione a cui sto lavorando (Froyo mirato e sopra), ma non è necessaria un'elevata precisione, quindi ho utilizzato float e FloatMath finora, e non c'è assolutamente bisogno di passare a doppio.
Tuttavia, la raccomandazione "use Math over FloatMath" non indica quale utilizzare se float è il risultato desiderato.

Quindi, in breve; quale è preferibile?

float foo = FloatMath.sin(bar); 

o

float foo = (float) Math.sin(bar); 

Su un lato nota, ho solo un Froyo-dispositivo, quindi non posso davvero fare qualsiasi analisi comparativa adeguata per conto mio.

A partire dal livello di API 22 il FloatMath-classe è stata deprecata a favore della regolare Math-class.

+0

Penso che il testo che hai citato significhi che se float è il risultato desiderato, dovresti usare la matematica invece di floatmath e cast. –

+2

Prenderò qualsiasi richiesta relativa alla performance relativa di 'int' /' float'/'double' con un granello di sale molto grande. 'float' può essere leggermente più veloce semplicemente a causa dell'impronta di cache più piccola, e su iPhone 3GS,' float' è * significativamente * più veloce poiché può utilizzare l'unità NEON invece dell'unità VFP più lenta (l'unità NEON non supporta i doppi); questo potrebbe essere specifico per iDevice. Inoltre, un JIT auto-vettorico beneficerà automaticamente di 'float' più di' double' semplicemente perché può adattarsi a più di essi in ogni registro vettoriale. –

+0

Potrebbe essere che i float vengano tutti memorizzati come doppi sugli ultimi dispositivi Android ?! – Philip

risposta

14

Come si può vedere dai risultati seguenti, l'uso di java.lang.Math è più veloce per i float che per i doppi e più veloce di FloatMath. Inoltre, FloatMath ha .exp() o .pow() prima API di livello 17.

Su un Samsung GT_i9295 (4.2.2), 2^24 cicli

Math.exp(D)  Total:  7405 ms,  Per Op: 0.0004414 ms 
(F)Math.exp(F) Total:  5153 ms,  Per Op: 0.0003071 ms 
FloatMath.exp(F) Total:  8533 ms,  Per Op: 0.0005086 ms 

Nessuna dati per Math. peccato sul Samsung perché ha deciso di ignorare in modo casuale Log.d()> :(

su un HTC Hero_HT99VL (2.3.7), 2^12 cicli

Math.sin(D)  Total:  42 ms,  Per Op: 0.0102539 ms 
(F)Math.sin(F) Total:  33 ms,  Per Op: 0.0080566 ms 
FloatMath.sin(F) Total:  38 ms,  Per Op: 0.0092773 ms 

Math.exp(D)  Total:  56 ms,  Per Op: 0.0136719 ms 
(F)Math.exp(F) Total:  47 ms,  Per Op: 0.0114746 ms 

FloatMath.exp(), .pos() e .hypot() richiedono il livello API 17

5

Il docs for FloatMath dicono:

routine matematiche simili a quelli trovati in matematica. Esegue calcoli su valori float direttamente senza incorrere nel sovraccarico delle conversioni da e verso il doppio.

e il tuo preventivo dice:

utilizzando android.util.FloatMath è stato raccomandato per motivi di prestazioni quando si opera su carri

Presumibilmente il beneficio di FloatMath era sempre specificamente per quando vuoi un float, ma questo vantaggio è stato ora negato.

in modo da utilizzare:

float foo = (float) Math.sin(bar); 

Considera anche che se le prestazioni è così critico che avete bisogno di preoccuparsi di questo, forse il passaggio a double è garantito dopo tutto (per non sostenere il costo della conversione).

+0

Se non ci sono differenze nell'operare il doppio o il float al giorno d'oggi, può ancora esserci un sovraccarico nella conversione dei float in double e viceversa.Quindi, usando Math si verificherà la conversione da un tipo all'altro e FloatMath opererà direttamente sui float. Quindi, perché usare la matematica è meglio? – Egor

+0

alcuni dei metodi matematici accettano il doppio come argomenti, quindi c'è anche un cast implicito. – Jave

+3

@Egor Non conosco i dettagli del perché esattamente l'uso di 'Math' è migliore di ciò che è stato menzionato, tutto quello che sto dicendo è che il doc e lint warning sembra implicare che dovresti usare' Math' su 'FloatMath' anche considerando il costo della conversione. Inoltre, usare semplicemente 'double' invece di' float' in generale è [consigliato] (http://developer.android.com/training/articles/perf-tips.html#AvoidFloat) a meno che lo spazio non sia un problema. – kabuko

-1

Se le prestazioni sono così importanti, probabilmente non si vuole perdere tempo a trasmettere da e verso double s ogni volta che si calcola qualcosa.

Come ho capito, su dispositivi hardware precedenti i float erano più veloci del doppio, quindi era necessaria una libreria Math per i float. Ora, "su hardware moderno raddoppia sono veloci quanto float", quindi dovresti usare il valore predefinito Math con il doppio.

Se è importante per l'applicazione che i valori siano float (ad es. A causa del consumo di memoria), è necessario continuare a utilizzare FloatMath, perché float foo = (float) Math.sin(bar); diventerà fastidioso se lo si utilizza molto.

2

Stavo esaminando lo stesso problema recentemente e ho trovato questo bug report sul problema. Le funzioni Math superano i FloatMath quelli di un ordine di grandezza, come mostrato di seguito la citazione:

Utilizzando DDMS, ho fatto il profilo il codice in questione. Ciascuna delle funzioni seguenti è stata chiamata oltre 100x.

 Name     | Cpu Time/Call 
---------------------------------------------- 
java/lang/Math.sin (D)D  | 0.005 
java/lang/Math.cos (D)D  | 0.007 
java/lang/Math.sqrt (D)D | 0.004 
android/util/FloatMath.sin | 0.017 
android/util/FloatMath.cos | 0.017 
android/util/FloatMath.sqrt | 0.016 

Se si segue il documentation changes nell'albero AOSP vedrete here che Math funzioni sono da preferire per FloatMath sulle versioni di Android con un JIT, che è fondamentalmente qualsiasi cosa, da Froyo (2.2) e fino.