我的印象是,在NumPy中,两个阵列可以共享相同的内存.请看以下示例:
import numpy as np
a=np.arange(27)
b=a.reshape((3,3,3))
a[0]=5000
print (b[0,0,0]) #5000
#Some tests:
a.data is b.data #False
a.data == b.data #True
c=np.arange(27)
c[0]=5000
a.data == c.data #True ( Same data, not same memory storage ), False positive
Run Code Online (Sandbox Code Playgroud)
所以显然b
没有复制a
; 它只是创建了一些新的元数据并将其附加到a
正在使用的相同内存缓冲区中.有没有办法检查两个数组是否引用相同的内存缓冲区?
我的第一印象是使用a.data is b.data
,但返回false.我能做的a.data == b.data
,返回真,但我不认为检查,以确保a
和b
共享相同的内存缓冲区,只有内存块被引用a
和引用的一个b
具有相同的字节.
jte*_*ace 27
您可以使用base属性检查数组是否与另一个数组共享内存:
>>> import numpy as np
>>> a = np.arange(27)
>>> b = a.reshape((3,3,3))
>>> b.base is a
True
>>> a.base is b
False
Run Code Online (Sandbox Code Playgroud)
不确定是否能解决您的问题.None
如果数组拥有自己的内存,则base属性为.请注意,数组的基数将是另一个数组,即使它是一个子集:
>>> c = a[2:]
>>> c.base is a
True
Run Code Online (Sandbox Code Playgroud)
我认为jterrace的答案可能是最好的方法,但这是另一种可能性.
def byte_offset(a):
"""Returns a 1-d array of the byte offset of every element in `a`.
Note that these will not in general be in order."""
stride_offset = np.ix_(*map(range,a.shape))
element_offset = sum(i*s for i, s in zip(stride_offset,a.strides))
element_offset = np.asarray(element_offset).ravel()
return np.concatenate([element_offset + x for x in range(a.itemsize)])
def share_memory(a, b):
"""Returns the number of shared bytes between arrays `a` and `b`."""
a_low, a_high = np.byte_bounds(a)
b_low, b_high = np.byte_bounds(b)
beg, end = max(a_low,b_low), min(a_high,b_high)
if end - beg > 0:
# memory overlaps
amem = a_low + byte_offset(a)
bmem = b_low + byte_offset(b)
return np.intersect1d(amem,bmem).size
else:
return 0
Run Code Online (Sandbox Code Playgroud)
例:
>>> a = np.arange(10)
>>> b = a.reshape((5,2))
>>> c = a[::2]
>>> d = a[1::2]
>>> e = a[0:1]
>>> f = a[0:1]
>>> f = f.reshape(())
>>> share_memory(a,b)
80
>>> share_memory(a,c)
40
>>> share_memory(a,d)
40
>>> share_memory(c,d)
0
>>> share_memory(a,e)
8
>>> share_memory(a,f)
8
Run Code Online (Sandbox Code Playgroud)
下面的曲线图显示了每次share_memory(a,a[::2])
调用的时间与a
计算机中元素数量的关系.
小智 8
要准确解决问题,您可以使用
import numpy as np
a=np.arange(27)
b=a.reshape((3,3,3))
# Checks exactly by default
np.shares_memory(a, b)
# Checks bounds only
np.may_share_memory(a, b)
Run Code Online (Sandbox Code Playgroud)
这两个np.may_share_memory
和np.shares_memory
一个可选的max_work
参数,可以让你决定多少努力,投入,以确保没有误报。这个问题是 NP 完全的,所以总是找到正确的答案在计算上是相当昂贵的。
做就是了:
a = np.arange(27)
a.__array_interface__['data']
Run Code Online (Sandbox Code Playgroud)
第二行将返回一个元组,其中第一项是内存地址,第二项是该数组是否为只读。结合形状和数据类型,您可以算出数组覆盖的内存地址的确切范围,因此当一个数组是另一个数组的子集时,也可以从中算出。
归档时间: |
|
查看次数: |
7440 次 |
最近记录: |