编译时间在ipython3中

时间:2014-12-15 17:21:22

标签: python-3.x ipython jit timeit

执行命令

timeit a = (3**(10**7))%24;

在ipython3上获得输出,

100000000 loops, best of 3: 13.5 ns per loop
Compiler time: 3.39 s

编译时间是指JIT编译器在ipython3中花费的时间吗?

在Ubuntu 14.04上使用ipython3 v1.2.1。

1 个答案:

答案 0 :(得分:1)

IPython没有实现任何类型的JIT编译器。 '编译时间'表示Python将文本代码编译为Python字节码的时间。

我对你的时间感到惊讶 - 这是一个非常简单的表达方式,几乎没有时间编译。如果编译时间不到0.1秒,IPython就不会报告编译时间,而且我以前从未见过它。所以我自己去尝试了,果然......

In [2]: timeit a = (3**(10**7))%24;
10000000 loops, best of 3: 20.7 ns per loop
Compiler time: 5.54 s

那是怎么回事?

答案是CPython的窥视孔优化器,特别是函数fold_binops_on_constants(),找到了here (C code)10**7是两个常量的二元运算,保证总是具有相同的值。所以Python有助于预先计算该值,并用常量10**7替换程序中的10000000。但是现在3**10000000是对两个常量的二元运算,所以它也计算它。最后它对操作的最后部分做了同样的事情,所以字节码看起来像这样:

In [11]: dis.dis("a = (3**(10**7))%24")
  1           0 LOAD_CONST               7 (9)
              3 STORE_NAME               0 (a)
              6 LOAD_CONST               4 (None)
              9 RETURN_VALUE

当代码运行时,它实际上正在执行的是将常量9存储在名称a中!

这在实际代码中很有用 - 该表达式在创建.pyc文件时预先计算,因此每次运行程序时都会保存几秒钟。它对时序没那么有用,因为你的实际计算只由编译器运行一次。为了强制它进行计时,我们可以简单地从表达式的最里面部分创建一个变量,因此Python不会对它进行优化(窥孔优化器非常基本,不像现代C编译器或JIT编译器):

In [5]: b = 7

In [6]: timeit a = (3**(10**b))%24;
1 loops, best of 3: 5.5 s per loop