我对Numpy阵列内存管理有疑问。假设我使用以下内容从缓冲区创建一个numpy数组:
>>> s = "abcd"
>>> arr = numpy.frombuffer(buffer(s), dtype = numpy.uint8)
>>> arr.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : False
ALIGNED : True
UPDATEIFCOPY : False
>>> del s # What happens to arr?
在上面的情况中,'arr'是否持有's'的引用?如果我删除's',这会释放为's'分配的内存,从而使'arr'可能引用未分配的内存吗?
我有其他一些问题:
答案 0 :(得分:6)
以下内容应该澄清一点:
>>> s = 'abcd'
>>> arr = np.frombuffer(buffer(s), dtype='uint8')
>>> arr.base
<read-only buffer for 0x03D1BA60, size -1, offset 0 at 0x03D1BA00>
>>> del s
>>> arr.base
<read-only buffer for 0x03D1BA60, size -1, offset 0 at 0x03D1BA00>
在第一种情况下del s
没有效果,因为数组指向的是从它创建的buffer
,在其他地方没有引用。
>>> t = buffer('abcd')
>>> arr = np.frombuffer(t, dtype='uint8')
>>> arr.base
<read-only buffer for 0x03D1BA60, size -1, offset 0 at 0x03C8D920>
>>> arr.base is t
True
>>> del t
>>> arr.base
<read-only buffer for 0x03D1BA60, size -1, offset 0 at 0x03C8D920>
在第二种情况下,当你del t
时,你摆脱了指向t
对象的变量buffer
,但因为数组仍然引用了同一个buffer
del arr
1}},它不会被删除。虽然我不确定如何检查它,但如果您现在buffer
,则{{1}}对象应该丢失其最后一个引用并自动进行垃圾回收。
答案 1 :(得分:0)
为了补充@seberg 的评论:
import ctypes
import sys
import numpy as np
b = bytearray([1, 2, 3])
b_addr = id(b)
print(sys.getrefcount(b) - 1, ctypes.c_long.from_address(b_addr).value) # => 1 1
a1 = np.frombuffer(b, dtype=np.int8)
assert b[0] == a1[0]
b[0] = b[0] + 1
assert b[0] == a1[0]
print(sys.getrefcount(b) - 1, ctypes.c_long.from_address(b_addr).value) # => 2 2
a2 = np.frombuffer(b, dtype=np.int8)
print(sys.getrefcount(b) - 1, ctypes.c_long.from_address(b_addr).value) # => 3 3
del a2
print(sys.getrefcount(b) - 1, ctypes.c_long.from_address(b_addr).value) # => 2 2
del b
print(ctypes.c_long.from_address(b_addr).value) # => 1
del a1
print(ctypes.c_long.from_address(b_addr).value) # => 0
sys.getrefcount(b)
返回更高的值“因为它包含(临时)引用作为 getrefcount() 的参数”