Me he estado preguntando esto por algún tiempo. Como dice el título, ¿cuál es más rápido, la función real o simplemente elevar a la mitad la potencia?
ACTUALIZAR
Esto no es una cuestión de optimización prematura. Esto es simplemente una cuestión de cómo funciona realmente el código subyacente. ¿Cuál es la teoría de cómo funciona el código Python?
Le envié un correo electrónico a Guido van Rossum porque realmente quería saber las diferencias en estos métodos.
Mi email:
Hay al menos 3 formas de hacer una raíz cuadrada en Python: math.sqrt, el operador '**' y pow (x, .5). Tengo curiosidad por las diferencias en la implementación de cada uno de estos. Cuando se trata de eficiencia, ¿cuál es mejor?
Su respuesta:
pow y ** son equivalentes; math.sqrt no funciona para números complejos y enlaza con la función C sqrt (). En cuanto a cuál es más rápido, no tengo idea ...
math.sqrt
es una rutina más optimizada (tal como es) y expresa la intención con mayor claridad, siempre debe preferirse a ellax**.5
. No es una optimización prematura saber lo que escribes, y elegir la alternativa que sea más rápida y proporcione más claridad de código. Si es así, debe argumentar igualmente bien por qué elegiría las otras alternativas.Respuestas:
math.sqrt(x)
es significativamente más rápido quex**0.5
.Usando Python 3.6.9 ( cuaderno ).
fuente
Aquí hay algunos tiempos (Python 2.5.2, Windows):
Esta prueba muestra que
x**.5
es un poco más rápido quesqrt(x)
.Para Python 3.0, el resultado es el opuesto:
math.sqrt(x)
siempre es más rápido quex**.5
en otra máquina (Ubuntu, Python 2.6 y 3.1):fuente
¿Cuántas raíces cuadradas realmente estás realizando? ¿Estás tratando de escribir algún motor de gráficos 3D en Python? Si no es así, ¿por qué elegir el código que es críptico sobre el código que es fácil de leer? La diferencia horaria es menor de lo que cualquiera podría notar en casi cualquier aplicación que pudiera prever. Realmente no pretendo dejar tu pregunta, pero parece que vas demasiado lejos con la optimización prematura.
fuente
En estos micro-puntos de referencia,
math.sqrt
será más lento, debido al poco tiempo que lleva buscarsqrt
en el espacio de nombres matemático. Puedes mejorarlo ligeramente conAun así, sin embargo, ejecutando algunas variaciones a través del tiempo, muestra una ligera ventaja de rendimiento (4-5%) para
x**.5
Curiosamente, haciendo
acelere aún más, hasta una diferencia de velocidad del 1%, con muy poca significación estadística.
Repetiré Kibbee y diré que esta es probablemente una optimización prematura.
fuente
En python 2.6, la
(float).__pow__()
función usa lapow()
función C y lasmath.sqrt()
funciones usan lasqrt()
función C.En el compilador glibc, la implementación
pow(x,y)
es bastante compleja y está bien optimizada para varios casos excepcionales. Por ejemplo, llamar a Cpow(x,0.5)
simplemente llama a lasqrt()
función.La diferencia en la velocidad de uso
.**
omath.sqrt
es causada por los envoltorios utilizados alrededor de las funciones de C y la velocidad depende en gran medida de los indicadores de optimización / compilador de C utilizados en el sistema.Editar:
Aquí están los resultados del algoritmo de Claudiu en mi máquina. Obtuve resultados diferentes:
fuente
Por lo que vale (ver la respuesta de Jim). En mi máquina, ejecutando python 2.5:
fuente
usando el código de Claudiu, en mi máquina incluso con "from math import sqrt" x **. 5 es más rápido pero usando psyco.full () sqrt (x) se vuelve mucho más rápido, al menos en un 200%
fuente
Lo más probable es que math.sqrt (x), porque está optimizado para el enraizamiento cuadrado.
Los puntos de referencia le proporcionarán la respuesta que está buscando.
fuente
Alguien comentó sobre la "raíz cuadrada rápida de Newton-Raphson" del Quake 3 ... La implementé con ctypes, pero es muy lenta en comparación con las versiones nativas. Voy a probar algunas optimizaciones e implementaciones alternativas.
Aquí hay otro método que usa struct, sale aproximadamente 3.6 veces más rápido que la versión ctypes, pero aún 1/10 de la velocidad de C.
fuente
Los resultados de Claudiu difieren de los míos. Estoy usando Python 2.6 en Ubuntu en una vieja máquina P4 2.4Ghz ... Aquí están mis resultados:
sqrt es consistentemente más rápido para mí ... Incluso Codepad.org NOW parece estar de acuerdo en que sqrt, en el contexto local, es más rápido ( http://codepad.org/6trzcM3j ). Codepad parece estar ejecutando Python 2.5 actualmente. ¿Quizás estaban usando 2.4 o más cuando Claudiu respondió por primera vez?
De hecho, incluso usando math.sqrt (i) en lugar de arg (i), todavía obtengo mejores tiempos para sqrt. En este caso, timeit2 () tardó entre 0,53 y 0,55 segundos en mi máquina, lo que sigue siendo mejor que las cifras de 0,56-0,60 de timeit1.
Yo diría que en Python moderno, use math.sqrt y definitivamente tráigalo al contexto local, ya sea con somevar = math.sqrt o con math import sqrt.
fuente
Lo pitónico para optimizar es la legibilidad. Para esto, creo que el uso explícito de la
sqrt
función es mejor. Dicho esto, investiguemos el rendimiento de todos modos.Actualicé el código de Claudiu para Python 3 y también hice imposible optimizar los cálculos (algo que un buen compilador de Python puede hacer en el futuro):
Los resultados varían, pero una salida de muestra es:
Inténtalo tú mismo.
fuente
El problema SQRMINSUM que he resuelto recientemente requiere calcular la raíz cuadrada repetidamente en un gran conjunto de datos. Las 2 presentaciones más antiguas de mi historia , antes de hacer otras optimizaciones, difieren únicamente al reemplazar ** 0.5 con sqrt (), lo que reduce el tiempo de ejecución de 3.74s a 0.51s en PyPy. Esto es casi el doble de la mejora ya masiva del 400% que midió Claudiu.
fuente
Por supuesto, si se trata de literales y necesita un valor constante, el tiempo de ejecución de Python puede calcular previamente el valor en tiempo de compilación, si está escrito con operadores; no es necesario perfilar cada versión en este caso:
fuente
Lo que sería aún más rápido es si ingresó a math.py y copió la función "sqrt" en su programa. A su programa le lleva tiempo encontrar math.py, luego abrirlo, encontrar la función que está buscando y luego traerla nuevamente a su programa. Si esa función es más rápida incluso con los pasos de "búsqueda", entonces la función en sí misma debe ser terriblemente rápida. Probablemente reducirá su tiempo a la mitad. En resumen:
fuente
from math import sqrt
?