¿Doble o flotante, que es más rápido?

Estoy leyendo “acelerado C ++”. Encontré una oración que dice “a veces el double es más rápido en la ejecución que el float en C ++”. Después de leer la oración, me confundí acerca de la float y el double trabajo. Por favor explícame este punto.

Depende de lo que haga el hardware nativo.

  • Si el hardware implementa el doble (como hace el x86), entonces flotan se emula extendiéndolo allí, y la conversión costará tiempo. En este caso, el doble será más rápido.

  • Si el hardware implementa float solamente, entonces emular el doble con él costará aún más tiempo. En este caso, el flotador será más rápido.

  • Y si el hardware no implementa ninguno, y ambos deben implementarse en el software. En este caso, ambos serán lentos, pero el doble será un poco más lento (más operaciones de carga y almacenamiento como mínimo).

La cita que menciona probablemente se refiere a la plataforma x86, donde se dio el primer caso. Pero esto no es cierto en general.

Puedes encontrar una respuesta completa en este artículo

Lo que todo informático debería saber sobre la aritmética de coma flotante

Esta es una cita de un hilo de desbordamiento de stack anterior de float x double con respecto al ancho de banda de la memoria

Si un doble requiere más almacenamiento que un flotador, la lectura de los datos tardará más tiempo. Esa es la respuesta ingenua. En un IA32 moderno, todo depende de dónde provienen los datos. Si está en caché L1, la carga es insignificante siempre que los datos provengan de una sola línea de caché. Si abarca más de una línea de caché, hay una pequeña sobrecarga. Si es de L2, tarda un poco más, si está en la RAM, entonces es más largo y, por último, si está en el disco, es un gran momento. Entonces, la elección de flotación o doble es menos importante que la forma en que se usan los datos. Si desea hacer un cálculo pequeño en una gran cantidad de datos secuenciales, es preferible un tipo de datos pequeño. Hacer una gran cantidad de cálculos en un pequeño conjunto de datos le permitirá usar tipos de datos más grandes con algún efecto significativo. Si accede a los datos de forma aleatoria, la elección del tamaño de los datos no es importante: los datos se cargan en páginas / líneas de caché. Entonces, incluso si solo quiere un byte de RAM, podría obtener 32 bytes transferidos (esto es muy dependiente de la architecture del sistema). Además de todo esto, la CPU / FPU podría ser súper escalar (también conocido como “pipeline”). Entonces, aunque una carga puede tomar varios ciclos, la CPU / FPU podría estar ocupada haciendo otra cosa (una multiplicación por ejemplo) que oculta el tiempo de carga en un grado

La respuesta corta es: depende .

La CPU con x87 reducirá las fluctuaciones y se duplicará con la misma rapidez. El código vectorizado se ejecutará más rápido con flotadores, porque SSE puede hacer crujir 4 flotadores o 2 dobles en una sola pasada.

Otra cosa a considerar es la velocidad de la memoria. Dependiendo de su algoritmo, su CPU podría estar funcionando al ralentí mientras espera los datos. El código intensivo en memoria se beneficiará del uso de flotadores, pero el código limitado de ALU no lo hará (a menos que esté vectorizado).

Puedo pensar en dos casos básicos cuando los dobles son más rápidos que los flotadores:

  1. Su hardware admite operaciones dobles pero no operaciones flotantes, por lo que los flotantes serán emulados por el software y, por lo tanto, serán más lentos.

  2. Realmente necesitas la precisión de los dobles. Ahora, si usa flotadores de todos modos, tendrá que usar dos flotadores para alcanzar una precisión similar al doble. La emulación de un verdadero doble con flotadores será más lenta que el uso de flotadores en primer lugar.

    1. No necesariamente necesitas dobles, pero tu algoritmo numérico converge más rápido debido a la precisión mejorada de los dobles. Además, los dobles pueden ofrecer la precisión suficiente para usar un algoritmo más rápido pero numéricamente menos estable.

Para mayor completitud, también doy algunas razones para el caso contrario de que los flotadores sean más rápidos. Puede ver por usted mismo cuáles son las razones que dominan en su caso:

  1. Los flotantes son más rápidos que los dobles cuando no necesitas la precisión del doble y tienes un límite de ancho de banda de memoria y tu hardware no tiene una penalización en los flotadores.

  2. Conservan el ancho de banda de memoria porque ocupan la mitad del espacio por número.

  3. También hay plataformas que pueden procesar más flotadores que dobles en paralelo.

En Intel, el coprocesador (hoy en día integrado) manejará ambas partes igualmente rápido, pero como algunos otros han notado, el doble da como resultado un mayor ancho de banda de memoria que puede causar cuellos de botella. Si está utilizando instrucciones escalares SSE (valor predeterminado para la mayoría de los comstackdores en 64 bits), aplica lo mismo. Por lo tanto, en general, a menos que esté trabajando en un conjunto grande de datos, no importa mucho.

Sin embargo, las instrucciones paralelas de SSE permitirán manejar cuatro flotadores en una instrucción, pero solo dos dobles, por lo que aquí la flotación puede ser significativamente más rápida.

Solo hay una razón por la que los flotantes de 32 bits pueden ser más lentos que los dobles de 64 bits (u 80×87 de 80 bits). Y eso es alineación. Aparte de eso, las carrozas toman menos memoria, lo que generalmente significa un acceso más rápido, un mejor rendimiento de la memoria caché. También se requieren menos ciclos para procesar las instrucciones de 32 bits. E incluso cuando el (co) -procesador no tiene instrucciones de 32 bits, puede realizarlas en registros de 64 bits con la misma velocidad. Probablemente sea posible crear un caso de prueba donde los dobles serán más rápidos que los flotantes, y vv, pero mis medidas de algos de estadísticas reales no mostraron una diferencia notable.

En experimentos de agregar 3.3 por 2000000000 veces, los resultados son:

 Summation time in s: 2.82 summed value: 6.71089e+07 // float Summation time in s: 2.78585 summed value: 6.6e+09 // double Summation time in s: 2.76812 summed value: 6.6e+09 // long double 

Entonces el doble es más rápido y predeterminado en C y C ++. Es más portátil y el valor predeterminado en todas las funciones de la biblioteca C y C ++. Alos double tiene una precisión significativamente mayor que el flotador.

Incluso Stroustrup recomienda doble sobre el flotante:

“El significado exacto de la precisión simple, doble y extendida está definido por la implementación. Elegir la precisión adecuada para un problema donde la elección importa requiere una comprensión significativa del cálculo en coma flotante. Si no tiene esa comprensión, obtenga consejos, tómese el tiempo para aprender, o use el doble y espere lo mejor “.

Quizás el único caso en el que debe usar flotante en lugar de doble es en hardware de 64 bits con un gcc moderno. Porque el flotador es más pequeño; el doble tiene 8 bytes y el flotante tiene 4 bytes.

el flotador es generalmente más rápido. el doble ofrece una mayor precisión. Sin embargo, el rendimiento puede variar en algunos casos si se usan extensiones de procesador especiales como 3dNow o SSE.