Python的:为什么*和**的速度比/和SQRT()? [英] Python: why are * and ** faster than / and sqrt()?

查看:231
本文介绍了Python的:为什么*和**的速度比/和SQRT()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在优化我的code,我意识到以下内容:

While optimising my code I realised the following:

>>> from timeit import Timer as T
>>> T(lambda : 1234567890 / 4.0).repeat()
[0.22256922721862793, 0.20560789108276367, 0.20530295372009277]
>>> from __future__ import division
>>> T(lambda : 1234567890 / 4).repeat()
[0.14969301223754883, 0.14155197143554688, 0.14141488075256348]
>>> T(lambda : 1234567890 * 0.25).repeat()
[0.13619112968444824, 0.1281130313873291, 0.12830305099487305]

和也:

>>> from math import sqrt
>>> T(lambda : sqrt(1234567890)).repeat()
[0.2597470283508301, 0.2498021125793457, 0.24994492530822754]
>>> T(lambda : 1234567890 ** 0.5).repeat()
[0.15409398078918457, 0.14059877395629883, 0.14049601554870605]

我认为它与Python是用C语言实现的方式做,但我不知道是否有人会关心解释为什么会这样?

I assume it has to do with the way python is implemented in C, but I wonder if anybody would care to explain why is so?

推荐答案

(有点出乎意料),原因你的结果就是,Python似乎折叠涉及浮点乘法和乘方,但不是分裂不断前pressions。 的Math.sqrt()是一个不同的野兽完全因为没有字节code,此事涉及的函数调用。

The (somewhat unexpected) reason for your results is that Python seems to fold constant expressions involving floating-point multiplication and exponentiation, but not division. math.sqrt() is a different beast altogether since there's no bytecode for it and it involves a function call.

在Python的2.6.5,以下code:

On Python 2.6.5, the following code:

x1 = 1234567890.0 / 4.0
x2 = 1234567890.0 * 0.25
x3 = 1234567890.0 ** 0.5
x4 = math.sqrt(1234567890.0)

编译到后面的字节codeS:

compiles to the following bytecodes:

  # x1 = 1234567890.0 / 4.0
  4           0 LOAD_CONST               1 (1234567890.0)
              3 LOAD_CONST               2 (4.0)
              6 BINARY_DIVIDE       
              7 STORE_FAST               0 (x1)

  # x2 = 1234567890.0 * 0.25
  5          10 LOAD_CONST               5 (308641972.5)
             13 STORE_FAST               1 (x2)

  # x3 = 1234567890.0 ** 0.5
  6          16 LOAD_CONST               6 (35136.418286444619)
             19 STORE_FAST               2 (x3)

  # x4 = math.sqrt(1234567890.0)
  7          22 LOAD_GLOBAL              0 (math)
             25 LOAD_ATTR                1 (sqrt)
             28 LOAD_CONST               1 (1234567890.0)
             31 CALL_FUNCTION            1
             34 STORE_FAST               3 (x4)

正如你所看到的,乘法和乘方拿不出,因为在所有的时候code编译他们完成的时间。司需要更长的时间,因为它发生在运行时。平方根不仅是四大最昂贵的计算操作,这也招致各种开销,其他人不(属性查询,函数调用等)。

As you can see, multiplication and exponentiation take no time at all since they're done when the code is compiled. Division takes longer since it happens at runtime. Square root is not only the most computationally expensive operation of the four, it also incurs various overheads that the others do not (attribute lookup, function call etc).

如果您消除常量折叠的效果,几乎没有分开乘法和除法:

If you eliminate the effect of constant folding, there's little to separate multiplication and division:

In [16]: x = 1234567890.0

In [17]: %timeit x / 4.0
10000000 loops, best of 3: 87.8 ns per loop

In [18]: %timeit x * 0.25
10000000 loops, best of 3: 91.6 ns per loop

的Math.sqrt(x)实际上是一点点比更快点¯x** 0.5 ,presumably因为它是后者的一个特例,因此可以更有效地完成,尽管开销

math.sqrt(x) is actually a little bit faster than x ** 0.5, presumably because it's a special case of the latter and can therefore be done more efficiently, in spite of the overheads:

In [19]: %timeit x ** 0.5
1000000 loops, best of 3: 211 ns per loop

In [20]: %timeit math.sqrt(x)
10000000 loops, best of 3: 181 ns per loop

修改2011-11-16:恒前pression折叠Python的窥孔优化完成。该人士$ ​​C $ C( peephole.c )包含以下注释解释了为什么不断分裂没有被折叠:

edit 2011-11-16: Constant expression folding is done by Python's peephole optimizer. The source code (peephole.c) contains the following comment that explains why constant division isn't folded:

    case BINARY_DIVIDE:
        /* Cannot fold this operation statically since
           the result can depend on the run-time presence
           of the -Qnew flag */
        return 0;

-Qnew 标记启用的的 PEP 238

这篇关于Python的:为什么*和**的速度比/和SQRT()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆