执行命令
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。
答案 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