Python:在numpy中定义矩阵的内存优化方法 前言:

Python:在numpy中定义矩阵的内存优化方法 前言:,python,memory,memory-management,numpy,matrix,Python,Memory,Memory Management,Numpy,Matrix,如果你对阅读感到厌烦,就跳过前言,因为你已经知道这一点了 我最近在调试时遇到了一个问题。我写了'A=B=C=np.zero([3,3]),我想我刚刚定义了三个新矩阵。事实上,我所做的是不同的。我定义了一个新矩阵(用零填充)和三个标签,每个标签都指向同一个矩阵。让我用下面的例子来说明: import numpy as np 问题是: 嗯。现在我知道没问题了,对吧?我当然可以写: >>> a = b = [0,0] >>> a [0,0] >>>

如果你对阅读感到厌烦,就跳过前言,因为你已经知道这一点了

我最近在调试时遇到了一个问题。我写了'A=B=C=np.zero([3,3]),我想我刚刚定义了三个新矩阵。事实上,我所做的是不同的。我定义了一个新矩阵(用零填充)和三个标签,每个标签都指向同一个矩阵。让我用下面的例子来说明:

import numpy as np
问题是: 嗯。现在我知道没问题了,对吧?我当然可以写:

>>> a = b = [0,0]
>>> a
[0,0]
>>> b
[0,0]
>>> # All good so far.
>>> a[0] = 1
>>> a
[1,0]
>>> # Nothing short of what one would expect...
>>> b
[1,0]
>>> # ... but since 'b' is assigned tot he same tuple, it changes as well.
一切正常吗?没错,但我同样可以写:

A = np.zeros([3,3])
B = np.zeros([3,3])
C = np.zeros([3,3])
我认为第二种方法使用内存的效率更高,因为它定义了一个3x3x3张量,然后为每个层定义了3个标签a、B和C,而不是三个单独的矩阵,它们之间可能有内存位


你认为哪一个更好?

最重要的是,它闻起来像是过早优化。如果我们讨论的是一小部分矩阵,这两种方式都无关紧要。如果我们谈论的是大量的矩阵,你不太可能利用解包


话虽如此,第二个选项涉及创建更大的底层存储,而第一个选项创建三个独立的存储。如果三个矩阵的寿命相同,则前者的效率更高。后者更具可读性,并允许释放单个矩阵的内存。如果这种优化对您有任何影响,请进行测量。

我做了一个简单的测试,看看这两种情况下(下面的代码和结果)发生了什么。正如所怀疑的那样,后一种方法是线性分配内存,而前一种方法是将内存分散到系统允许的任何地方(我本以为会比以前更紧密)。 因此,后者在内存位置方面更有效。但就分配时间而言(下面的脚本计时),它们是等价的(解包似乎占用了一些时间,我们谈论的几乎是非常小的数字)。因此,考虑这一点很可能是过早的优化

A, B, C = np.zeros([3,3,3])
输出

>位置b-a中的差异-125520

>位置c-a中的差异-173376

>位置B-A中的差异72

>位置C-A中的差异144


不幸的是,这可能会被关闭,因为它不是正确的格式,所以。。但只要运行timeit并查看您的procmon,就可以看到这两者的内存和时间足迹。。。人们认为完全不相关的东西,你可以很容易地自己检查度量。通常,如果你希望使用3D数组进行某些操作(例如,计算所有3个矩阵的元素平均值),你只需要做解包工作,当然,这需要给它一个标签:
big_array=np.zeros((3,3,3));a、 b,c=大数组
。这主要是个人喜好的问题,尽管如果你的阵列很大,可能会更容易找到三个三分之一大小的插槽,而不是一个完整大小的插槽。我不确定你是否非常了解numpy如何处理内存和视图。。。你说的“垃圾”是什么意思?像解包这样的标准特性如何影响可读性?你怎么认为前一种方法会更节省内存?@Jaime你说得对,我说得太早了,指的是“垃圾”。我现在更新了答案,以更准确地反映所涉及的权衡。
import sys
import numpy as np
nr = 1000
rounds =1000
if len(sys.argv)==2:
    if sys.argv[1]=='seq':
        print "testing sequential allocation"
        for i in xrange(rounds):
            a=np.zeros([nr,nr])
            b=np.zeros([nr,nr])
            c=np.zeros([nr,nr])
    elif sys.argv[1]=='all':
        print "testing allocating all at once"
        for i in xrange(rounds):
            A,B,C=np.zeros([3,nr,nr])
        
        
a=np.zeros([3,3])
b=np.zeros([3,3])
c=np.zeros([3,3])
A,B,C=np.zeros([3,3,3])

print "diff in location b-a", b.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location c-a", c.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location B-A", B.__array_interface__['data'][0]-A.__array_interface__['data'][0]
print "diff in location C-A", C.__array_interface__['data'][0]-A.__array_interface__['data'][0]