import numpy as np
如果您因为已经知道这一点而感到厌倦,请跳过前言。
我最近在调试时遇到了问题。我写了'A = B = C = np.zeros([3,3]),我认为我刚刚定义了三个新的矩阵。我所做的事实上是不同的。我定义了一个新的矩阵(用零填充)和三个标签,每个标签都指向同一个矩阵。让我用以下例子来说明:
>>> 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])
一切正常吗?这是对的,但我同样可以写:
A, B, C = np.zeros([3,3,3])
我认为第二个选项以更有效的方式使用内存,因为它定义了一个3x3x3张量,然后为每个层的3个标签A,B和C而不是三个单独的矩阵,它们之间可能有内存位。 / p>
你认为哪一个更好?
答案 0 :(得分:3)
最重要的是,它闻起来像是过早优化。如果我们谈论的是少数几个矩阵,那么无论如何都无关紧要。如果我们正在谈论大量的矩阵,你就不太可能使用解包。
话虽如此,第二个选项涉及创建更大的底层存储,而第一个选项创建三个独立的存储。如果所有三个矩阵共享相同的生命周期,前者会更有效。后者更具可读性,并允许释放单个矩阵的内存。如果这种优化对你很重要,请测量。
答案 1 :(得分:3)
我做了一个简单的测试,看看这两种情况发生了什么(代码和结果如下)。由于怀疑后一种方法线性分配存储器,而前者将其分散到系统所允许的位置(我原本希望它比它更紧密)。 因此后者在内存位置方面更有效。但就分配时间而言(下面的脚本定时)它们是等价的(解包似乎偷了一些时间,我们谈论的是几乎非常小的数字)。因此,考虑这一点很可能是过早优化。
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]
输出
>差异在位置b-a -125520
>差异在位置c-a -173376
>差异在位置B-A 72
>差异在位置C-A 144