Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

172
Visualizações
¿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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda