我很好奇为什么乘法比在python中获得超能力要快得多(尽管据我所读到,这在许多其他语言中也很可能是正确的)。例如,这样做要快得多
x*x比
x**2我认为**算子更一般,也可以处理分数次方。但是如果这就是为什么它要慢得多,为什么它不检查一个int指数,然后做乘法呢?
编辑:,这是我试过的一些示例代码..。
def pow1(r, n):
for i in range(r):
p = i**n
def pow2(r, n):
for i in range(r):
p = 1
for j in range(n):
p *= i现在,pow2只是一个快速的例子,显然没有被优化!
但即使如此,我发现使用n=2和r= 1,000,000,则pow1取2500 so,pow2取1700 so。
我承认,对于n的大值,pow1确实比pow2快得多。但这并不奇怪。
发布于 2009-06-19 20:33:46
基本上,朴素乘法是一个非常低常数因子的O(n)。取幂为O(log )具有较高的常数因子(有特殊情况需要测试.分数指数、负指数等)。编辑:为了弄清楚,这是O(n),其中n是指数。
当然,对于小n,朴素的方法会更快,你实际上只是在实现指数数学的一个小子集,所以你的常数因子可以忽略不计。
发布于 2009-06-19 20:07:50
增加支票也是一项开支。你总想要那张支票吗?编译后的语言可以检查常量指数,看看它是否是一个相对较小的整数,因为没有运行时成本,只有编译时间成本。一种解释的语言可能无法进行这种检查。
这取决于特定的实现,除非语言指定了这种细节。
Python不知道你要给它提供什么指数分布。如果它将是99%的非整数值,您是否希望代码每次检查一个整数,从而使运行时更慢?
发布于 2009-06-19 22:05:31
在指数检查中这样做会减缓这种情况,在这种情况下,它不是简单的二次幂,也不一定是胜利。然而,在指数提前知道的情况下(例如。(使用文字2),生成的字节码可以通过简单的窥视孔优化来优化。据推测,这根本不值得去做(这是一个相当具体的案例)。
这里有一个概念的快速证明,它可以进行这样的优化(可作为装饰者使用)。注意:您需要拜特雷模块来运行它。
import byteplay, timeit
def optimise(func):
c = byteplay.Code.from_code(func.func_code)
prev=None
for i, (op, arg) in enumerate(c.code):
if op == byteplay.BINARY_POWER:
if c.code[i-1] == (byteplay.LOAD_CONST, 2):
c.code[i-1] = (byteplay.DUP_TOP, None)
c.code[i] = (byteplay.BINARY_MULTIPLY, None)
func.func_code = c.to_code()
return func
def square(x):
return x**2
print "Unoptimised :", timeit.Timer('square(10)','from __main__ import square').timeit(10000000)
square = optimise(square)
print "Optimised :", timeit.Timer('square(10)','from __main__ import square').timeit(10000000)这就给出了时间:
Unoptimised : 6.42024898529
Optimised : 4.52667593956实际上,编辑了,再考虑一下,有一个很好的理由来解释为什么这个优化没有完成。不能保证有人不会创建一个用户定义的类,该类覆盖__mul__和__pow__方法,并为每个方法执行不同的操作。唯一安全的方法是确保堆栈顶部的对象具有相同的结果"x**2“和"x*x",但要解决这个问题要困难得多。例如:在我的例子中,这是不可能的,因为任何对象都可以传递给平方函数。
https://stackoverflow.com/questions/1019740
复制相似问题