研究list和array的内存增长模式

list_array.py

本习题的程序文件

在Python中,列表是一个动态的指针数组,而array模块所提供的array对象则是保存相同类型的数值的动态数组。由于array直接保存值,因此它所使用的内存比列表少。列表和array都是动态数组,因此往其中添加新元素,而没有空间保存新的元素时,它们会自动重新分配内存块,并将原来的内存中的值复制到新的内存块中。为了减少重新分配内存的次数,通常每次重新分配时,大小都为原来的k倍。k值越大,则重新分配内存的次数越少,但浪费的空间越多。本习题通过一系列的实验观察列表和array的内存分配模式。

通过getsizeof()计算列表的增长模式

sys.getsizeof()可以获得列表所占用的内存大小。请编写程序计算一个长度为10000的列表,它的每个下标都保存列表增长到此下标时的大小:

import sys
【你的程序】计算size列表,它的每个小标都保存增长到此下标时size列表的大小
import pylab as pl
pl.plot(size, lw=2)

程序的输出如【图:列表的内存增长模式】所示,图中每个阶梯跳变的位置都表示一次内存分配,而每个阶梯的长度表示内存分配多出来的大小。

/tech/static/books/scipyex/_images//list_array_01.png

列表的内存增长模式

请编写程序计算表示每次分配内存时列表的内存大小的resize_pos数组:

import numpy as np
【你的程序】计算resize_pos,它的每个元素是size中每次分配内存的位置
pl.figure()
pl.plot(resize_pos, lw=2)
print "list increase rate:"
tmp = resize_pos[25:].astype(np.float) #
print np.average(tmp[1:]/tmp[:-1]) #
可以使用NumPy的diff()、where()、nonzero()快速完成此计算。

程序的输出如【图:列表进行内存分配时的长度】所示,由图可知曲线呈指数增长,第45次分配内存时,列表的大小已经接近10000。

/tech/static/books/scipyex/_images//list_array_02.png

列表进行内存分配时的长度

❷为了计算增长率,只需要计算resize_pos数组前后两个值的商的平均值即可。❶为了提高精度,我们只计算后半部分的平均值,注意需要用astype()方法将整数数组转换为浮点数数组。程序的输出如下:

list increase rate:
1.12828128382

我们可以用scipy.optimize.curve_fit()对resize_pos数组进行拟合,拟合函数为指数函数:

a 10^{b x + c} + d

请编写程序用上面的公式对resize_pos数组进行拟合:

from scipy.optimize import curve_fit
【你的程序】用指数函数对resize_pos数组进行拟合
print "list increase rate by curve_fit:"
print 10**b

程序的输出为:

list increase rate by curve_fit:
1.1250154766

通过运算时间估算

遗憾的是,无论array对象的长度是多少,sys.getsizeof()的结果都不变。因此无法用上节的方法计算array对象的增长因子。

由于内存分配时会耗费比较长的时间,因此可以通过测量每次增加元素的时间,找到内存分配时的长度。请编写测量增加元素的时间的程序:

from array import array
import time
【你的程序】计算往array中添加元素的时间times
pl.figure()
pl.plot(times)
为了更准确地测量内存分配的耗时,可以测量多个array对象的append()方法的执行时间。

程序的输出如【图:array对象添加每个元素所需的时间】所示,我们可以看到array对象在某些长度时,添加元素的耗时明显增加,这就是array对象运行内存分配的时刻。

/tech/static/books/scipyex/_images//list_array_03.png

array对象添加每个元素所需的时间

请编写程序从【图:array对象添加每个元素所需的时间】计算出array对象运行内存分配时的长度:

【你的程序】通过times计算array对象内存分配时的长度resize_pos2

pl.figure()
pl.plot(resize_pos2, lw=2)

程序的输出如【图:array对象进行内存分配时的长度】所示。

/tech/static/books/scipyex/_images//list_array_04.png

array对象进行内存分配时的长度

內容目录

上一个主题

Python科学计算习题集

下一个主题

用argmin(a)的返回值作下标存取数组

本页

loading...