计算能力的速度(在python中)

我很好奇,为什么它乘法的速度要快于在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,po​​w1需要约2500ms,pow2需要约1700ms。
我承认,对于n的大数值,pow1确实比pow2快得多。 但这并不令人感到意外。


基本上天真的乘法是O(n),其常数因子很低。 采取的权力是O(log n)具有较高的常数因子(有些特殊情况需要测试......分数指数,负指数等)。 编辑:只需要清楚,那就是O(n),其中n是指数。

当然,对于小n来说,天真的方法会更快,你只是真正实现了指数数学的一个小子集,所以你的常数因子可以忽略不计。


添加支票也是一项开支。 你总是希望那里的支票? 编译语言可以检查一个常量指数,看它是否是一个相对较小的整数,因为没有运行时成本,只是编译时成本。 解释型语言可能不会进行检查。

这取决于特定的实现,除非该语言指定了这种细节。

Python不知道你要给它分配什么指数。 如果它将是99%的非整数值,你是否希望代码每次检查一个整数,使运行时更慢?


在指数检查中这样做会减慢并非两次的简单次幂的情况,所以不一定是胜利。 但是,在指数已知的情况下(例如使用文字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 ”,但是解决这个问题要困难得多。 例如。 在我的例子中是不可能的,因为任何对象都可以传递给平方函数。

链接地址: http://www.djcxy.com/p/85693.html

上一篇: Speed of calculating powers (in python)

下一篇: Dynamic attributes in a jsp tag