Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

178
Vistas
¿Por qué math.sqrt es masivamente más lento que la exponenciación?

No puedo creer lo que acabo de medir:

 python3 -m timeit -s "from math import sqrt" "sqrt(2)" 5000000 loops, best of 5: 42.8 nsec per loop python3 -m timeit "2 ** 0.5" 50000000 loops, best of 5: 4.93 nsec per loop

Esto va en contra de cualquier intuición... ¡debería ser exactamente lo contrario!

Python 3.8.3 en macOS Catalina

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Python 3 calcula previamente el valor de 2 ** 0.5 en tiempo de compilación, ya que ambos operandos se conocen en ese momento. Sin embargo, el valor de sqrt no se conoce en tiempo de compilación, por lo que el cálculo necesariamente ocurre en tiempo de ejecución.

No está midiendo cuánto tiempo lleva calcular 2 ** 0.5 , sino solo el tiempo que lleva cargar una constante.

Una comparación más justa sería

 $ python3 -m timeit -s "from math import sqrt" "sqrt(2)" 5000000 loops, best of 5: 50.7 nsec per loop $ python3 -m timeit -s "x = 2" "x**0.5" 5000000 loops, best of 5: 56.7 nsec per loop

No estoy seguro de si hay una forma de mostrar el código de bytes no optimizado. Python comienza analizando el código fuente en un árbol de sintaxis abstracta (AST):

 >>> ast.dump(ast.parse("2**0.5")) 'Module(body=[Expr(value=BinOp(left=Num(n=2), op=Pow(), right=Num(n=0.5)))])'

Actualización : esta optimización particular ahora se aplica directamente al árbol de sintaxis abstracta , por lo que el código de bytes se genera directamente desde algo como

 Module(body=Num(n= 1.4142135623730951))

El módulo ast no parece aplicar la optimización.

El compilador toma el AST y genera un código de bytes no optimizado; en este caso, creo que se vería (según la salida de dis.dis("2**x") y dis.dis("x**0.5") ) como

 LOAD_CONST 0 (2) LOAD_CONST 1 (0.5) BINARY_POWER RETURN_VALUE

El código de bytes sin procesar está sujeto a modificaciones por parte del optimizador de mirilla, que puede reducir estas 4 instrucciones a 2, como se muestra en el módulo dis .

Luego, el compilador genera un código de bytes a partir del AST.

 >>> dis.dis("2**0.5") 1 0 LOAD_CONST 0 (1.4142135623730951) 2 RETURN_VALUE

[Si bien el siguiente párrafo se escribió originalmente con la idea de optimizar el código de bytes en mente, el razonamiento también se aplica a la optimización del AST].

Dado que nada en el tiempo de ejecución afecta cómo se evalúan las dos LOAD_CONST y BINARY_POWER (por ejemplo, no hay búsquedas de nombres), el optimizador de mirilla puede tomar esta secuencia de códigos de bytes, realizar el cálculo de 2**0.5 y reemplazar el primeras tres instrucciones con una sola instrucción LOAD_CONST que carga el resultado inmediatamente.

over 4 years ago · Santiago Trujillo Denunciar

0

Para mejorar la respuesta de Chepner , aquí hay una prueba:

 Python 3.5.3 (default, Sep 27 2018, 17:25:39) [GCC 6.3.0 20170516] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import dis >>> dis.dis('2 ** 0.5') 1 0 LOAD_CONST 2 (1.4142135623730951) 3 RETURN_VALUE

contra

 >>> dis.dis('sqrt(2)') 1 0 LOAD_NAME 0 (sqrt) 3 LOAD_CONST 0 (2) 6 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 9 RETURN_VALUE
over 4 years ago · Santiago Trujillo Denunciar

0

>>> dis.dis('44442.3123 ** 0.5') 0 LOAD_CONST 0 (210.81345379268373) 2 RETURN_VALUE

No creo que 44442.3123 ** 0.5 esté precalculado en tiempo de compilación. Deberíamos comprobar mejor el AST del código.

 >>> import ast >>> import math >>> code = ast.parse("2**2") >>> ast.dump(code) 'Module(body=[Expr(value=BinOp(left=Num(n=2), op=Pow(), right=Num(n=2)))])' >>> code = ast.parse("math.sqrt(3)") >>> ast.dump(code) "Module(body=[Expr(value=Call(func=Attribute(value=Name(id='math', ctx=Load()), attr='sqrt', ctx=Load()), args=[Num(n=3)], keywords=[]))])"
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda