Python 2.7 复杂度过大导致内存错误

1 投票
3 回答
1360 浏览
提问于 2025-04-17 11:09

我刚接触Python,正在运行以下代码,但在使用Python 2.7时出现了内存错误。因为我在用OpenCV,所以我选择了Python 2.7。我看过之前的帖子,但对它们的内容不是很理解。

s={}
ns={}
ts={}
for i in range(0,256): #for red component
    for j in range(0,256): #for green component
        for k in range(0,256): # for blue component
            s[(i,j,k)]=0
            ns[(i,j,k)]=0
            ts[(i,j,k)]=i*j*k

请帮帮我。这个代码是想记录红色、绿色和蓝色成分的频率。为此,我把这些值初始化为零。

3 个回答

0

即使你所有的变量都只用一个字节,这个程序也需要405MB的内存。

你应该使用压缩技术来在有限的空间里存储更多的数据。

补充:如果你想在Python中制作直方图,可以参考这个很不错的例子,使用的是Python图像库(PIL):点击这里查看。实际上,主要的工作只需要这三行代码:

import Image
img = Image.open(imagepath)
hist = img.histogram()
1

实际上,你的程序至少需要 300*300*300*4*3 字节的内存,仅仅是为了字典中的值数据。此外,你的键元组还占用 300*300*300*3*3*4 字节。

总共加起来是 1296000000 字节,或者说 1.2 GiB 的数据。

这个计算还没有包括维护字典数据时的额外开销。

所以,程序是否会出错,取决于你电脑的内存有多少。

你可以先尝试这样做:

s = {}
ns = {}
ts = {}
for i in range(0, 300):
    for j in range(0, 300):
        for k in range(0, 300):
            index=(i, j, k)
            s[index]=j
            ns[index]=k
            ts[index]=i*j*k

理论上,这样做只会占用一半的内存,因为数据部分的内存减少了,而索引元组是可以重复使用的。


根据你描述的情况(你只是想计数),其实不需要预先初始化所有可能的组合。所以你可以省略你问题中提到的初始化,而是建立一个只存储实际有数据的值的存储,这些值通常会比所有可能的组合要少得多。

你可以使用一个 defaultdict(),或者手动模仿它的行为,因为我觉得你颜色“调色板”中的大多数组合并不会被用到。

from collections import defaultdict
make0 = lambda: 0
s = defaultdict(make0)
ns = defaultdict(make0)
# what is ts? do you need it?

现在你有三个类似 dict 的对象,可以根据需要写入数据。然后,对于你实际拥有的每一种颜色组合,你可以执行 s[index] += 1 或者 ns[index] += 1

至于你的 ts,我不太清楚,也许你可以计算出来,或者需要找到其他解决方案。

5

第一点:用 itertools 替代每次循环都构建的 range 列表。xrange 会返回一个迭代器对象,和 range 类似,而 product 会返回一个迭代器,从给定的可迭代对象中选择元组元素。

第二点:对于大数据,使用 numpy。它是专门为这种情况设计的矩阵实现。

>>> import numpy as np
>>> from itertools import product
>>> x=np.zeros((256,256,256))
>>> for i, j, k in product(xrange(256), repeat=3):
...     x[i,j,k]= i*j*k
... 

对我来说,大约需要五秒钟,内存使用量也在预期范围内。

$ cat /proc/27240/status 
Name:   python
State:  S (sleeping)
...
VmPeak:   420808 kB
VmSize:   289732 kB

注意,如果你尝试分配三个 256*256*256 的数组,可能会遇到系统内存限制,因为每个数组大约有1700万条数据。幸运的是,numpy 允许你将数组保存到磁盘上。

你听说过 PIL(Python图像库) 吗?你可能会觉得它很有用。

撰写回答