sol rapidamente quemaduras que hacer como aliviar c++ c logarithm math.h cmath

rapidamente - sqr c++



C/C++ operación de registro cmath más rápida (5)

En el conjunto de instrucciones 8087, solo hay una instrucción para que el logaritmo base 2, por lo que diría que este es el más rápido.

Por supuesto, este tipo de pregunta depende en gran medida de su procesador / arquitectura, por lo que sugeriría hacer una prueba simple y cronometrarla.

Estoy intentando calcular log a b (y recuperar un punto flotante, no un entero). Estaba planeando hacer esto como log(b)/log(a) . Hablando matemáticamente, puedo usar cualquiera de las cmath registro de cmath (base 2, e, o 10) para hacer este cálculo; sin embargo, ejecutaré este cálculo mucho durante mi programa, así que me preguntaba si uno de ellos es significativamente más rápido que los otros (o mejor aún, si hay una manera más rápida, pero sencilla, de hacerlo). Si importa, tanto ayb son números enteros.


En las plataformas para las que tengo datos, log2 es un poco más rápido que los demás, en línea con mis expectativas. Sin embargo, tenga en cuenta que la diferencia es extremadamente leve (solo un par de porcentajes). Realmente no vale la pena preocuparse por esto.

Escribe una implementación que sea clara. Luego mide el rendimiento.


La respuesta es:

  • depende
  • perfilarlo

Ni siquiera menciona su tipo de CPU, el tipo de variable, las banderas del compilador, el diseño de datos. Si necesita hacer muchos de estos en paralelo, estoy seguro de que habrá una opción SIMD. Su compilador lo optimizará siempre y cuando use la alineación y borre los bucles simples (o valarray si le gustan los enfoques arcaicos).

Es probable que el compilador de Intel tenga trucos específicos para los procesadores de Intel en esta área.

Si realmente quisiera, podría usar CUDA y aprovechar GPU.

Supongo que, si tiene la mala suerte de no tener estos conjuntos de instrucciones , podría bajar al nivel de bits y escribir un algoritmo que haga una buena aproximación . En este caso, puedo apostar a más de una tarta de manzana que 2-log será más rápido que cualquier otra base-log.


Primero, precalcule 1.0/log(a) y multiplique cada log(b) por esa expresión.

Edición: Originalmente dije que el logaritmo natural (base e) sería más rápido, pero otros afirman que la base 2 es soportada directamente por el procesador y sería más rápida. No tengo ninguna razón para dudarlo.

Edición 2: originalmente asumí que a era una constante, pero al volver a leer la pregunta nunca se formuló. De ser así, no habría ningún beneficio en el cálculo previo. Sin embargo, si lo es, puede mantener la legibilidad con una selección adecuada de nombres de variables:

const double base_a = 1.0 / log(a); for (int b = 0; b < bazillions; ++b) double result = log(b) * base_a;

Por extraño que parezca, Microsoft no proporciona una función de registro de base 2, lo que explica por qué no estaba familiarizado con ella. Además, la instrucción x86 para calcular registros incluye una multiplicación automática, y las constantes requeridas para las diferentes bases también están disponibles a través de una instrucción optimizada , por lo que espero que las 3 funciones de registro diferentes tengan una sincronización idéntica (incluso la base 2 tendría que multiplicarse por 1).


Ya que b y a son enteros, puedes usar toda la gloria de las combinaciones de bits para encontrar sus registros en la base 2. Aquí hay algunos:

  • Encuentre el log base 2 de un entero con el MSB N configurado en operaciones O (N) (la forma obvia)
  • Encuentre la base de registro de enteros 2 de un entero con un flotante IEEE de 64 bits
  • Encuentre el log base 2 de un entero con una tabla de búsqueda
  • Encuentre el log base 2 de un entero de N bits en operaciones O (lg (N))
  • Encuentre el log base 2 de un entero de N bits en operaciones O (lg (N)) con multiplicación y búsqueda

Dejaré que elija la mejor función de "registro rápido" para sus necesidades.