首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在python中处理cpu缓存(或者调用一次函数的最快方法)

如何在python中处理cpu缓存(或者调用一次函数的最快方法)
EN

Stack Overflow用户
提问于 2015-08-23 13:44:36
回答 1查看 1.5K关注 0票数 1

我发现python的VM似乎对CPU-Cache非常不友好。

例如:

代码语言:javascript
复制
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

时间:

代码语言:javascript
复制
> 100us

另一种情况:

代码语言:javascript
复制
import time
a = range(500)

for i in range(100000):
    st = time.time()
    sum(a)
    print (time.time() - st)*1e6

时间:

代码语言:javascript
复制
~ 20us

我们可以看到,当频繁运行时,代码会变得更快。

有解决方案吗?

我们可以参考这个问题:(应该是同一个问题) python function(or a code block) runs much slower with a time interval in a loop

我觉得这个问题很难。必须对python虚拟机、c和cpu-cache的机制有深入的了解。

你有什么建议在哪里张贴这个问题,以获得可能的答案?

EN

回答 1

Stack Overflow用户

发布于 2015-08-23 18:08:25

你的假设“我们可以在频繁运行时看到,代码变得更快”是不完全正确的。

这个循环

代码语言:javascript
复制
#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(),这在时间上都没有什么不同。

代码语言:javascript
复制
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)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32163585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档