Eu estive pensando nisso há algum tempo. Como o título diz, o que é mais rápido, a função real ou simplesmente aumentar para a metade da potência?
ATUALIZAR
Não se trata de otimização prematura. Isso é simplesmente uma questão de como o código subjacente realmente funciona. Qual é a teoria de como o código Python funciona?
Enviei um email a Guido van Rossum porque eu realmente queria saber as diferenças nesses métodos.
Meu email:
Existem pelo menos três maneiras de criar uma raiz quadrada no Python: math.sqrt, o operador '**' e pow (x, .5). Estou apenas curioso sobre as diferenças na implementação de cada uma delas. Quando se trata de eficiência, qual é melhor?
Sua resposta:
pow e ** são equivalentes; math.sqrt não funciona para números complexos e links para a função C sqrt (). Quanto a qual é mais rápido, não faço ideia ...
fonte
math.sqrt
é uma rotina mais otimizada (como é) e expressa a intenção com mais clareza, sempre deve ser preferidax**.5
. Não é uma otimização prematura saber o que você escreve e escolheu a alternativa que é mais rápida e oferece mais clareza de código. Nesse caso, você precisa argumentar igualmente bem por que escolheria as outras alternativas.Respostas:
math.sqrt(x)
é significativamente mais rápido quex**0.5
.Usando Python 3.6.9 ( notebook ).
fonte
Aqui estão alguns horários (Python 2.5.2, Windows):
Este teste mostra que
x**.5
é um pouco mais rápido quesqrt(x)
.Para o Python 3.0, o resultado é o oposto:
math.sqrt(x)
é sempre mais rápido quex**.5
em outra máquina (Ubuntu, Python 2.6 e 3.1):fonte
Quantas raízes quadradas você realmente está realizando? Você está tentando escrever algum mecanismo de gráficos 3D em Python? Se não, então por que usar um código que é enigmático sobre um código fácil de ler? A diferença horária é menor do que qualquer um poderia notar em praticamente qualquer aplicativo que eu pudesse prever. Realmente não pretendo fazer sua pergunta, mas parece que você está indo longe demais com a otimização prematura.
fonte
Nesses micro-benchmarks,
math.sqrt
será mais lento, devido ao pouco tempo necessário para pesquisarsqrt
no espaço para nome matemático. Você pode melhorar um pouco comMesmo assim, executando algumas variações ao longo do tempo, mostra uma pequena vantagem de desempenho (4-5%) para
x**.5
Curiosamente, fazendo
acelerou ainda mais, com uma diferença de velocidade de 1%, com muito pouca significância estatística.
Vou repetir o Kibbee e dizer que essa é provavelmente uma otimização prematura.
fonte
No python 2.6, a
(float).__pow__()
função usa apow()
função C e asmath.sqrt()
funções usam asqrt()
função C.No compilador glibc, a implementação de
pow(x,y)
é bastante complexa e está bem otimizada para vários casos excepcionais. Por exemplo, chamar Cpow(x,0.5)
simplesmente chama asqrt()
funçãoA diferença na velocidade de uso
.**
oumath.sqrt
é causada pelos wrappers usados em torno das funções C e a velocidade depende fortemente dos sinalizadores de otimização / compilador C usados no sistema.Editar:
Aqui estão os resultados do algoritmo de Claudiu na minha máquina. Eu obtive resultados diferentes:
fonte
Para o que vale a pena (veja a resposta de Jim). Na minha máquina, executando o python 2.5:
fonte
usando o código de Claudiu, na minha máquina, mesmo com "from math import sqrt" x **. 5 é mais rápido, mas o uso de psyco.full () sqrt (x) se torna muito mais rápido, pelo menos em 200%
fonte
Provavelmente math.sqrt (x), porque é otimizado para o enraizamento quadrado.
Os benchmarks fornecerão a resposta que você está procurando.
fonte
Alguém comentou sobre a "raiz quadrada rápida de Newton-Raphson" do Quake 3 ... eu implementei com ctypes, mas é super lento em comparação com as versões nativas. Vou tentar algumas otimizações e implementações alternativas.
Aqui está outro método usando struct, sai cerca de 3,6x mais rápido que a versão ctypes, mas ainda 1/10 da velocidade de C.
fonte
Os resultados de Claudiu diferem dos meus. Estou usando o Python 2.6 no Ubuntu em uma antiga máquina P4 2.4Ghz ... Aqui estão meus resultados:
O sqrt é consistentemente mais rápido para mim ... Até o Codepad.org AGORA parece concordar que o sqrt, no contexto local, é mais rápido ( http://codepad.org/6trzcM3j ). O Codepad parece estar executando o Python 2.5 atualmente. Talvez eles estivessem usando o 2.4 ou mais quando Claudiu respondeu pela primeira vez?
De fato, mesmo usando math.sqrt (i) no lugar de arg (i), ainda tenho tempos melhores para o sqrt. Nesse caso, o timeit2 () levou entre 0,53 e 0,55 segundos na minha máquina, o que ainda é melhor do que os valores de 0,56-0,60 do timeit1.
Eu diria que, no Python moderno, use math.sqrt e traga-o definitivamente para o contexto local, com somevar = math.sqrt ou com math import sqrt.
fonte
O ideal para otimizar é a legibilidade. Para isso, acho melhor o uso explícito da
sqrt
função. Dito isto, vamos investigar o desempenho de qualquer maneira.Atualizei o código de Claudiu para Python 3 e também impossibilitei otimizar os cálculos (algo que um bom compilador Python pode fazer no futuro):
Os resultados variam, mas uma saída de amostra é:
Tente você mesmo.
fonte
O problema que SQRMINSUM que resolvi recentemente exige o cálculo da raiz quadrada repetidamente em um grande conjunto de dados. Os 2 envios mais antigos da minha história , antes de fazer outras otimizações, diferem apenas substituindo ** 0,5 por sqrt (), reduzindo assim o tempo de execução de 3,74s para 0,51s no PyPy. Isso é quase o dobro da já massiva melhoria de 400% que Claudiu mediu.
fonte
Obviamente, se alguém está lidando com literais e precisa de um valor constante, o tempo de execução do Python pode pré-calcular o valor em tempo de compilação, se ele estiver escrito com operadores - não há necessidade de criar um perfil de cada versão neste caso:
fonte
O que seria ainda mais rápido é se você entrou no math.py e copiou a função "sqrt" para o seu programa. Leva tempo para o seu programa encontrar math.py, abra-o, encontre a função que você está procurando e, em seguida, traga-a de volta ao programa. Se essa função for mais rápida, mesmo com as etapas de "pesquisa", a função em si deve ser extremamente rápida. Provavelmente reduzirá seu tempo pela metade. Em suma:
fonte
from math import sqrt
?