我发现python的VM似乎对CPU-Cache非常不友好。
例如:
import time
a = range(500)
sum(a)
for i in range(1000000): #just to create a time interval, seems this disturb cpu cache?
pass
st = time.time()
sum(a)
print (time.time() - st)*1e6时间:
> 100us另一种情况:
import time
a = range(500)
for i in range(100000):
st = time.time()
sum(a)
print (time.time() - st)*1e6时间:
~ 20us我们可以看到,当频繁运行时,代码会变得更快。
有解决方案吗?
我们可以参考这个问题:(应该是同一个问题) python function(or a code block) runs much slower with a time interval in a loop
我觉得这个问题很难。必须对python虚拟机、c和cpu-cache的机制有深入的了解。
你有什么建议在哪里张贴这个问题,以获得可能的答案?
发布于 2015-08-23 18:08:25
你的假设“我们可以在频繁运行时看到,代码变得更快”是不完全正确的。
这个循环
#just to create a time interval, seems this disturb cpu cache?
for i in range(1000000):
pass不仅仅是一个简单的时间延迟。在Python2中,它创建一个包含1,000,000个整数对象的列表,循环遍历它,然后销毁它。在Python3中,range()是一个生成器,因此它对内存的浪费要小得多;Python2的等价物是xrange()。
在标准的CPython实现中,列表是指向其包含的对象的指针数组。在32位系统中,一个整数对象占用12个字节,一个空列表对象占用32个字节,当然一个指针占用4个字节。因此,range(1000000)总共消耗32 + 1000000 * (4 + 12) = 16000032字节。
一旦循环结束,range()列表上的引用计数就会降为零,因此它及其内容都有资格进行垃圾收集。垃圾收集一百万个整数需要一点时间,所以在循环结束后注意到时间延迟也就不足为奇了。此外,创建和释放所有这些对象的过程通常会导致一些内存碎片,这将影响后续代码的效率。
在我的2GHzPentium4Linux系统上,你的第一个代码块打印的值范围是38 - 41µs,但是如果我改变循环使用xrange(),那么时间就会下降到31 - 34µs。
如果修改代码以防止在计算sum(a)之前对range()进行垃圾回收,那么无论我们使用range()还是xrange(),这在时间上都没有什么不同。
import time
a = range(500)
sum(a)
bigrange = xrange(1000000)
for i in bigrange:
pass
st = time.time()
sum(a)
print (time.time() - st) * 1e6
#Maintain a reference to bigrange to prevent it
#being garbage collected earlier
print sum(bigrange)https://stackoverflow.com/questions/32163585
复制相似问题