Python Numpy:每个操作上的内存分配?

Python Numpy:每个操作上的内存分配?,python,numpy,Python,Numpy,numpy是否为对矩阵执行的每个操作分配新矩阵 例如: A = np.random.rand(10, 20) A = 2 * A # Operation 1: Is a copy of A made, and a reference assigned to A? B = 2 * A # Operation 2: Does B get a completely different copy of A? C = A # Operation 3: Does C get a referen

numpy是否为对矩阵执行的每个操作分配新矩阵

例如:

A = np.random.rand(10, 20)
A = 2 * A  # Operation 1: Is a copy of A made, and a reference assigned to A?
B = 2 * A  # Operation 2: Does B get a completely different copy of A?
C = A      # Operation 3: Does C get a reference to A?
和切片操作:

A[0, :] = 3
连锁经营怎么样

D = A * B * C  # Elementwise multiplication, if A * B allocates memory, does 
               # (A * B) * C allocate another patch of memory?

Numpy是一个很棒的图书馆,但我只想知道在引擎盖下会发生什么。我的直觉是切片操作会修改内存视图,但我不知道赋值。

是的,它会创建新的数组。除了C.C和指向同一内存的点


你可以自己测试所有这些。尝试使用
id(A)
命令查看A在内存中的位置。另外,只需创建一个较小的结构并修改部分结构,然后查看a、B和/或C是否也被更新。

请记住,numpy数组是Python对象。Python不断地创建和删除对象。数组的属性显示在
.FLAGS
数组界面字典中,例如
形状
数据类型
。占用(可能)大量内存的属性是数据缓冲区。它可能有几个字节长,也可能是MB

在可能的情况下,numpy操作尽量避免复制数据缓冲区。编制索引时,如果可能,它将返回一个
视图
。我认为文档对视图和副本进行了比较

但是视图与Python引用不同。共享引用意味着两个变量(或列表或字典中的指针)指向同一个Python对象。
视图
是一个不同的数组对象,但它与另一个数组共享数据缓冲区。副本有自己的数据缓冲区

在您的示例中:

A = np.random.rand(10, 20)
A
是指向数组对象的变量。该对象有一个具有200个浮点(200*8字节)的数据缓冲区

2*A
使用新数据缓冲区创建新对象。它的任何数据值都不能与原始
A
共享
A=…
重新分配
A
变量。旧的
对象“丢失”,最终内存被垃圾回收

B = 2 * A  # Operation 2: Does B get a completely different copy of A?
2*A
在新的
A
阵列上运行。对象被分配到
B
<代码>A
保持不变

C = A      # Operation 3: Does C get a reference to A?
是的,这只是普通的Python赋值
C
指的是与
A
相同的对象<代码>id(C)=id(A)

B
是对新数组对象的引用。但该对象与
A
共享数据缓冲区。这是因为只要从不同的点开始,使用不同的
形状
,就可以在缓冲区中找到所需的值

A[0, :] = 3
此LHS切片将更改
a
值的子集。它类似于:

B = A[0, :]
B = 3
但LHS和RHS切片之间存在细微差异。在LHS上,当您获得一个副本而不是一个视图时,您必须更加注意。我特别在
A[idx1,:][:,idx2]=3
这样的表达式中看到了这一点

D = A * B * C 
在这样的计算中,有多少个中间副本的详细信息隐藏在numpy C代码中。最安全的假设是,它会执行以下操作:

temp1 = A*B
temp2 = temp1*C
D = temp2
(temp1 goes to garbage)

对于普通的计算来说,不值得担心这些细节。如果你真的在追求速度,你可以在备选方案上做一个
timeit
。偶尔我们会遇到一些关于操作导致
内存错误的问题。进行搜索以获取有关这些的更多详细信息。

回答得好,谢谢。我添加了一个关于链式操作的回复。你知道numpy是如何计算这些值的吗?我不知道确切的情况,但是,一般来说,python将
D=A*B*C
解释为
D=A.。\uuuuuuMul\uuuuu(B)。\uuuuuuMul\uuuuuuu(C)
因此,我假设有一个中间结果是为A*B计算的,然后是为最终分配给D的结果*C计算的。如果你关心这个问题,你可以查看numpy的源代码。你关心的是速度,还是非常大的阵列内存不足?@hpaulj:我关心的是速度,主要是。但记忆是另一件我很在意的事情。
D = A * B * C 
temp1 = A*B
temp2 = temp1*C
D = temp2
(temp1 goes to garbage)