Python占用太多内存
Python taking too much of memory
我正在从 .npz 文件导入稀疏矩阵。下面是代码的脚本。稀疏矩阵 (Dx, Dy, ..., M) 的大小为 373248x373248,存储了 746496 个元素。
if runmode == 2:
data = np.load('Operators2.npz', allow_pickle=True)
Dx = data['Dx']
Dy = data['Dy']
Dz = data['Dz']
Dxx = data['Dxx']
Dyy = data['Dyy']
Dzz = data['Dzz']
Dxp = data['Dxp']
Dyp = data['Dyp']
Dzp = data['Dzp']
M = data['M']
del data
如果我打印变量之一,例如 Dx,我得到以下输出:
array(<373248x373248 sparse matrix of type '<class 'numpy.float64'>'
with 746496 stored elements in Compressed Sparse Column format>,
dtype=object)
但是我的系统内存增加了,程序崩溃了。当我执行下面的代码行时,程序崩溃了。我没有收到任何错误,但程序崩溃了。
DIV = Dx*u+Dy*v+Dz*w
即使我执行以下代码行,内存消耗也会增加,程序会崩溃
DIV = data['Dx']*u+data['Dy']*v+data['Dz']*w
这里 u,v,w 的形状是 373248x1。 DIV 的形状是 373248x1。由于Dx、Dy、Dz是稀疏矩阵,所以Dx*u做矩阵向量乘法,给出一个向量。
如果在同一个代码中,我实际计算Dx,Dy,...,M内存是没有问题的。如果我正在计算 Dx,那么输出如下:
<373248x373248 sparse matrix of type '<class 'numpy.float64'>'
with 746496 stored elements in Compressed Sparse Column format>
所以我认为在导入时创建对象存在问题。有没有办法避免这种情况?或者,我在导入稀疏矩阵时做错了什么?
谢谢你。
我使用 scipy.io.savemat() and scipy.io.loadmat() 解决了这个问题。我之前使用 np.savz() 和 np.load() 并且占用了太多内存。
制作一个稀疏矩阵:
In [38]: M = sparse.random(1000,1000,.2,'csr')
3 种不同的保存方式:
In [39]: from scipy import io
In [40]: np.savez('Msparse.npz', M=M)
In [41]: sparse.save_npz('M1sparse',M)
In [43]: io.savemat('Msparse.mat', {'M':M})
文件大小:
In [47]: ll M1spa* Mspar*
-rw-rw-r-- 1 paul 1773523 Feb 1 12:40 M1sparse.npz
-rw-rw-r-- 1 paul 2404208 Feb 1 12:41 Msparse.mat
-rw-rw-r-- 1 paul 2404801 Feb 1 12:39 Msparse.npz
加载 3 个矩阵:
In [48]: M1=sparse.load_npz('M1sparse.npz')
In [49]: M2=np.load('Msparse.npz',allow_pickle=True)['M']
In [50]: M3=io.loadmat('Msparse.mat')['M']
In [51]: M1
Out[51]:
<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>
In [52]: M2
Out[52]:
array(<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>,
dtype=object)
In [53]: M3
Out[53]:
<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Column format>
M1
和 M3
是相同的 - csr
就像 M
对于 save_npz
,csc
(MATLAB 格式)对于 .mat
.
M2
有一个对象 dtype 包装器。
In [54]: (M1*np.ones((1000,1))).shape
Out[54]: (1000, 1)
In [55]: (M3*np.ones((1000,1))).shape
Out[55]: (1000, 1)
这花了很多时间;结果差点不敢看
In [56]: (M2*np.ones((1000,1))).shape
Out[56]: (1000, 1)
如果我从对象数组中提取矩阵,乘法很快
In [57]: (M2.item()*np.ones((1000,1))).shape
Out[57]: (1000, 1)
In [58]: (M2.item()*np.ones((1000,1))).dtype
Out[58]: dtype('float64')
In [59]: (M3*np.ones((1000,1))).dtype
Out[59]: dtype('float64')
仔细观察 M2
乘法:
In [60]: (M2*np.ones((1000,1))).dtype
Out[60]: dtype('O')
In [61]: (M2*np.ones((1000,1)))[:2,:]
Out[61]:
array([[<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>],
[<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>]],
dtype=object)
它对 ones
的每个元素执行 M*1
乘法 - 生成 1000 个稀疏矩阵。那就是你的内存消耗的去向。
总之,当使用 savez
时,它将每个稀疏矩阵包装在一个对象 dtype 数组中,并进行 pickle。所以你不应该直接使用`data['Dx']
Dx = data['Dx'] # wrong
Dx = data['Dx'].item() # right
该计算非常适合就地操作:
np.multiply(data['Dx'], u, out=data['Dx']
np.multiply(data['Dy'], v, out=data['Dy']
np.multiply(data['Dz'], w, out=data['Dz']
numpy.add(data['Dx'], data['Dy'], out=data['Dx'])
numpy.add(data['Dx'], data['Dz'], out=data['Dx'])
这不会创建额外的临时数组。如果您还避免加载此特定计算不需要的其他变量,您将节省额外的内存。在函数内部完成工作是确保工作完成后清理/释放内存的好方法。在您的情况下,最好支付阅读罚款并只读入每次此类计算所需的特定数据。尽管就像 hpaulj 所说的那样,您找不到更多的魔法;这是一个大数据集,需要大量内存。有什么方法可以减小问题的大小/分辨率,或者在更小的块中解决它?
我正在从 .npz 文件导入稀疏矩阵。下面是代码的脚本。稀疏矩阵 (Dx, Dy, ..., M) 的大小为 373248x373248,存储了 746496 个元素。
if runmode == 2:
data = np.load('Operators2.npz', allow_pickle=True)
Dx = data['Dx']
Dy = data['Dy']
Dz = data['Dz']
Dxx = data['Dxx']
Dyy = data['Dyy']
Dzz = data['Dzz']
Dxp = data['Dxp']
Dyp = data['Dyp']
Dzp = data['Dzp']
M = data['M']
del data
如果我打印变量之一,例如 Dx,我得到以下输出:
array(<373248x373248 sparse matrix of type '<class 'numpy.float64'>'
with 746496 stored elements in Compressed Sparse Column format>,
dtype=object)
但是我的系统内存增加了,程序崩溃了。当我执行下面的代码行时,程序崩溃了。我没有收到任何错误,但程序崩溃了。
DIV = Dx*u+Dy*v+Dz*w
即使我执行以下代码行,内存消耗也会增加,程序会崩溃
DIV = data['Dx']*u+data['Dy']*v+data['Dz']*w
这里 u,v,w 的形状是 373248x1。 DIV 的形状是 373248x1。由于Dx、Dy、Dz是稀疏矩阵,所以Dx*u做矩阵向量乘法,给出一个向量。
如果在同一个代码中,我实际计算Dx,Dy,...,M内存是没有问题的。如果我正在计算 Dx,那么输出如下:
<373248x373248 sparse matrix of type '<class 'numpy.float64'>'
with 746496 stored elements in Compressed Sparse Column format>
所以我认为在导入时创建对象存在问题。有没有办法避免这种情况?或者,我在导入稀疏矩阵时做错了什么? 谢谢你。
我使用 scipy.io.savemat() and scipy.io.loadmat() 解决了这个问题。我之前使用 np.savz() 和 np.load() 并且占用了太多内存。
制作一个稀疏矩阵:
In [38]: M = sparse.random(1000,1000,.2,'csr')
3 种不同的保存方式:
In [39]: from scipy import io
In [40]: np.savez('Msparse.npz', M=M)
In [41]: sparse.save_npz('M1sparse',M)
In [43]: io.savemat('Msparse.mat', {'M':M})
文件大小:
In [47]: ll M1spa* Mspar*
-rw-rw-r-- 1 paul 1773523 Feb 1 12:40 M1sparse.npz
-rw-rw-r-- 1 paul 2404208 Feb 1 12:41 Msparse.mat
-rw-rw-r-- 1 paul 2404801 Feb 1 12:39 Msparse.npz
加载 3 个矩阵:
In [48]: M1=sparse.load_npz('M1sparse.npz')
In [49]: M2=np.load('Msparse.npz',allow_pickle=True)['M']
In [50]: M3=io.loadmat('Msparse.mat')['M']
In [51]: M1
Out[51]:
<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>
In [52]: M2
Out[52]:
array(<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>,
dtype=object)
In [53]: M3
Out[53]:
<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Column format>
M1
和 M3
是相同的 - csr
就像 M
对于 save_npz
,csc
(MATLAB 格式)对于 .mat
.
M2
有一个对象 dtype 包装器。
In [54]: (M1*np.ones((1000,1))).shape
Out[54]: (1000, 1)
In [55]: (M3*np.ones((1000,1))).shape
Out[55]: (1000, 1)
这花了很多时间;结果差点不敢看
In [56]: (M2*np.ones((1000,1))).shape
Out[56]: (1000, 1)
如果我从对象数组中提取矩阵,乘法很快
In [57]: (M2.item()*np.ones((1000,1))).shape
Out[57]: (1000, 1)
In [58]: (M2.item()*np.ones((1000,1))).dtype
Out[58]: dtype('float64')
In [59]: (M3*np.ones((1000,1))).dtype
Out[59]: dtype('float64')
仔细观察 M2
乘法:
In [60]: (M2*np.ones((1000,1))).dtype
Out[60]: dtype('O')
In [61]: (M2*np.ones((1000,1)))[:2,:]
Out[61]:
array([[<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>],
[<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
with 200000 stored elements in Compressed Sparse Row format>]],
dtype=object)
它对 ones
的每个元素执行 M*1
乘法 - 生成 1000 个稀疏矩阵。那就是你的内存消耗的去向。
总之,当使用 savez
时,它将每个稀疏矩阵包装在一个对象 dtype 数组中,并进行 pickle。所以你不应该直接使用`data['Dx']
Dx = data['Dx'] # wrong
Dx = data['Dx'].item() # right
该计算非常适合就地操作:
np.multiply(data['Dx'], u, out=data['Dx']
np.multiply(data['Dy'], v, out=data['Dy']
np.multiply(data['Dz'], w, out=data['Dz']
numpy.add(data['Dx'], data['Dy'], out=data['Dx'])
numpy.add(data['Dx'], data['Dz'], out=data['Dx'])
这不会创建额外的临时数组。如果您还避免加载此特定计算不需要的其他变量,您将节省额外的内存。在函数内部完成工作是确保工作完成后清理/释放内存的好方法。在您的情况下,最好支付阅读罚款并只读入每次此类计算所需的特定数据。尽管就像 hpaulj 所说的那样,您找不到更多的魔法;这是一个大数据集,需要大量内存。有什么方法可以减小问题的大小/分辨率,或者在更小的块中解决它?