2008-10-01 9 views
53

Estoy escribiendo una aplicación que lee grandes matrices de flotadores y realiza algunas operaciones simples con ellos. Estoy usando carrozas, porque pensé que sería más rápido que el doble, pero después de investigar un poco descubrí que hay cierta confusión sobre este tema. ¿Alguien puede explicar esto?¿Los dobles son más rápidos que los flotadores en C#?

Respuesta

63

La respuesta breve es "use la precisión que se requiera para obtener resultados aceptables".

Su única garantía es que las operaciones realizadas en datos de punto flotante se realizan en al menos el miembro de mayor precisión de la expresión. Así que la multiplicación de dos flotador 's se realiza con al menos la precisión de flotador, y multiplicando un flotador y una doble se llevaría a cabo con al menos el doble de precisión. La norma establece que "las operaciones de [coma flotante] se pueden realizar con mayor precisión que el tipo de resultado de la operación".

Dado que el JIT para .NET intenta dejar sus operaciones de punto flotante con la precisión solicitada, podemos echar un vistazo a la documentación de Intel para acelerar nuestras operaciones. En la plataforma Intel, las operaciones de coma flotante se pueden realizar con una precisión intermedia de 80 bits y se pueden convertir a la precisión solicitada.

Desde guía de Intel para C++ de operaciones de punto flotante (lo siento sólo tienen árbol muerto), mencionan:

  • utilizar un solo tipo de precisión (por ejemplo, float) a menos que la precisión adicional obtenido a través de doble o doble largo es obligatorio. Los tipos de mayor precisión aumentan el tamaño de la memoria y los requisitos de ancho de banda. ...
  • Evitar mixta tipo de datos expresiones aritméticas

Este último punto es importante, ya you can slow yourself down with unnecessary casts to/from float and double, que se traducen en código JIT'd que se pide al x87 de esparcir desde su formato intermedio de 80 bits entre operaciones!

1. Sí, dice C++, pero el estándar C# más el conocimiento del CLR nos permite saber que la información para C++ debe ser aplicable en esta instancia.

+3

En una nota al margen (sin relación con su respuesta), ¿utiliza .net JIT x87? Intel ha estado diciéndole a todos que lo abandonen por un tiempo a favor de SSE. –

+2

@Mike F: por lo que puedo decir, no parece elegir las operaciones SSE. No me cites sobre eso, eso es solo por lo que he visto JIT en mi código. Puedo preguntarle a microsoftie y averiguarlo. – user7116

+0

@sixlettervariables: Estaría muy interesado en escuchar la respuesta si alguna vez la encuentras y te apetece publicarla aquí. –

1

Esto indica que los flotadores son ligeramente más rápido que en dobles: http://www.herongyang.com/cs_b/performance.html

En general, cada vez que haces una comparación de rendimiento, debe tener en cuenta los casos especiales, al igual que lo hace usando un tipo requieren conversiones o datos adicionales masajear? Esos se suman y pueden desmentir los puntos de referencia genéricos como este.

+2

No sé si confiaría en los puntos de referencia de algún amigo cuya precisión se reduce a menos de un segundo. ¿Por qué no escribir un punto de referencia más grande (y más real en el mundo real con más tipos diferentes de pruebas) y dejarlo funcionar durante varios minutos? –

+0

Intenté esta prueba y en la compilación Release, tardan el mismo tiempo de procesamiento. –

1

Los flotantes deben ser más rápidos en un sistema de 32 bits, pero el código de perfil para asegurarse de que está optimizando lo correcto.

+2

@Steven A. Lowe: ¡Notaría que algunos sistemas de 32 bits carecen internamente de números de coma flotante de 32 bits! Por lo tanto, disminuyendo el rendimiento general. Su afirmación es correcta desde una perspectiva de ancho de banda de memoria ya que un flotador se adapta mejor que un doble. – user7116

7

Si las operaciones de almacenamiento de la carga & son el cuello de botella, entonces los flotadores serán más rápidos, porque son más pequeños. Si realiza una gran cantidad de cálculos entre cargas y tiendas, debería ser aproximadamente igual.

Alguien más mencionó evitar conversiones entre float & double, y los cálculos que utilizan operandos de ambos tipos.Es un buen consejo, y si usa cualquier función de la biblioteca matemática que devuelva dobles (por ejemplo), entonces mantener todo como dobles será más rápido.

+2

Este es el caso con C# donde todas las operaciones matemáticas devuelven el doble. Para valores literales, puede usar f, etc. para el valor mismo. –

19

Hice una pregunta similar hace unas semanas. La conclusión es que para el hardware x86, no hay una diferencia significativa en el rendimiento de los flotantes versus los dobles, a menos que te limites a la memoria, o comiences a tener problemas con el caché. En ese caso, los flotadores generalmente tendrán la ventaja porque son más pequeños.

Las CPU Intel actuales realizan todas las operaciones de coma flotante en registros de 80 bits de ancho por lo que la velocidad real del cálculo no debe variar entre flotantes y dobles.

4

Con la aritmética de 387 FPU, el flotante es solo más rápido que el doble para ciertas operaciones iterativas largas como pow, log, etc. (y solo si el compilador configura apropiadamente la palabra de control FPU).

Con aritmética SSE empaquetada, hace una gran diferencia sin embargo.

7

Estoy escribiendo un rastreador de rayos, y reemplazar los flotadores con dobles para mi clase de color me da una aceleración del 5%. ¡Reemplazar los flotadores de vectores con dobles es otro 5% más rápido! Bastante fresco :)

Eso es con un Core i7 920

+1

Supongo que debido a que algunos de los códigos se lanzan hacia atrás y hacia adelante entre float-> double-> float, p. Ej. con funciones matemáticas que devuelven el doble, por lo que la eliminación del casting es responsable de la aceleración; no necesariamente porque los dobles son innatamente más rápidos. – HoboBen

+7

En realidad, retiro eso. Acabo de probar con un simple bucle, y parece que, por la razón que sea, dobla * es * más rápido. – HoboBen

+0

El procesador es irrelevante. Ya sea que hagas esto en una PC lenta o rápida ... una mejora del 5% es una mejora del 5% :-) – z0mbi3

1

Siempre he pensado que los procesadores se optimizaron o el mismo independientemente de flotador o doble. Buscando optimizaciones en mis cálculos intensivos (muchos obtiene de una matriz, comparaciones de dos valores) descubrí que los flotantes se ejecutan aproximadamente un 13% más rápido.

Esto me sorprendió, pero creo que es debido a la naturaleza de mi problema. No hago lanzamientos entre float y double en el núcleo de las operaciones, y mis cálculos se basan principalmente en sumar, multiplicar y restar.

Esto está en mi i7 920, con un sistema operativo de 64 bits.

19

acabo de leer la "segunda Development Foundation Framework de aplicaciones .NET Microsoft" para el examen de MCTS 70-536 y hay una nota en la página 4 (capítulo 1):

NOTA Optimización del rendimiento con tipos incorporados
El tiempo de ejecución optimiza el rendimiento de los tipos enteros de 32 bits (Int32 y UInt32), por lo tanto, use esos tipos para los contadores y otras variables integrales a las que se accede con frecuencia. Para operaciones de coma flotante, Double es el tipo más eficiente porque esas operaciones están optimizadas por hardware.

Escrito por Tony Northrup. No sé si él es una autoridad o no, pero esperaría que el libro oficial para el examen .NET tenga algo de peso. Por supuesto, no es una garantía. Solo pensé en agregarlo a esta discusión.

4

Matthijs,

usted está equivocado. 32 bits es mucho más eficiente que 16 bits, en los procesadores modernos ... Tal vez no en cuanto a la memoria, pero en la efectividad de 32 bits es el camino a seguir.

Deberías actualizar a tu profesor a algo más "actualizado". ;)

De todos modos, para responder a la pregunta; flotante y doble tiene exactamente el mismo rendimiento, al menos en mi Intel i7 870 (como en teoría).

Éstos son mis medidas:

(hice un "algoritmo" que repite para 10.000.000 de veces y, a continuación, reiteró que durante 300 veces, y de que hice un promedio.)

double 
----------------------------- 
1 core = 990 ms 
4 cores = 340 ms 
6 cores = 282 ms 
8 cores = 250 ms 

float 
----------------------------- 
1 core = 992 ms 
4 cores = 340 ms 
6 cores = 282 ms 
8 cores = 250 ms 
+0

Hmm, supongo que tienes razón. Tal vez la fuente que me llevó a creer que la pregunta era incorrecta estaba mal. Actualizaré mi respuesta para eliminar la actualización (i.a.w. actualizar mi respuesta). –

Cuestiones relacionadas