我试图测试在python中使用JIT的速度提升。这是我使用的代码。
from numba import jit
import timeit
@jit # Commented out when testing pure python
def sumof():
x = 0
for i in xrange(1000000000):
x += 1
return x
def timer():
sumof() # Run once to initialize the JIT compiler
l = []
t = timeit.default_timer()
for x in range(10):
l.append(sumof())
return timeit.default_timer()-t, l # Returns the time elapsed and the list of results, to verify accuracy
print timer()
这给出了与此类似的结果
(5.643910299113486e-06, [1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000])
现在我知道原始CPU性能比纯python快几个数量级,但是在5微秒内有100亿次操作?我测试了相同的代码,但使用了有符号64位整数的最大值而不是仅仅十亿。这是结果。
(5.643909389618784e-06, [9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L])
~92千万亿次操作......在5微秒内完成。根据我的数学计算,这是一次大约16次septillion操作。有些事情显然是错误的,但却给出了正确的结果。我怀疑编译器在某种程度上摆脱了for循环,但为什么呢?我该如何预防?
答案 0 :(得分:1)
优化器似乎很可能已经用一个常量计算替换了循环。有关经典循环优化的列表,请参阅this issue。在这种情况下,完全展开循环,然后组合所有常量,得到return n
(x + = 1)或return n * b
(x + = b)。使用x += i
会产生return n * (n + 1) / 2
。 (在每种情况下n
都是适当的上部循环界限:在i
中求range(n)
时,它实际上只是n-1
。)
因为这是一个JIT编译器,它甚至可以为变量n
执行此操作,尽管在您的示例中每个n
都是常量,因此即使非JIT编译器也可以执行此操作。