Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to check if NumPy arrays share the same data?

Tags:

python

numpy

My impression is that in NumPy, two arrays can share the same memory. Take the following example:

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 

So clearly b didn't make a copy of a; it just created some new meta-data and attached it to the same memory buffer that a is using. Is there a way to check if two arrays reference the same memory buffer?

My first impression was to use a.data is b.data, but that returns false. I can do a.data == b.data which returns True, but I don't think that checks to make sure a and b share the same memory buffer, only that the block of memory referenced by a and the one referenced by b have the same bytes.

like image 928
mgilson Avatar asked Jul 02 '12 01:07

mgilson


People also ask

How do you check if two NumPy arrays have the same value?

To check if two NumPy arrays A and B are equal: Use a comparison operator (==) to form a comparison array. Check if all the elements in the comparison array are True.

How do you check that NumPy array owns the data or not?

To check whether array own it's data in view and copy we can use the fact that every NumPy array has the attribute base that returns None if the array owns the data. Else, the base attribute refers to the original object.

How do I check if two arrays are similar in python?

Compare Two Arrays in Python Using the numpy. array_equiv() Method. The numpy. array_equiv(a1, a2) method takes array a1 and a2 as input and returns True if both arrays' shape and elements are the same; otherwise, returns False .

How do you find the common values between two arrays in NumPy?

In NumPy, we can find common values between two arrays with the help intersect1d(). It will take parameter two arrays and it will return an array in which all the common elements will appear.


2 Answers

You can use the base attribute to check if an array shares the memory with another array:

>>> import numpy as np >>> a = np.arange(27) >>> b = a.reshape((3,3,3)) >>> b.base is a True >>> a.base is b False 

Not sure if that solves your problem. The base attribute will be None if the array owns its own memory. Note that an array's base will be another array, even if it is a subset:

>>> c = a[2:] >>> c.base is a True 
like image 77
jterrace Avatar answered Oct 07 '22 11:10

jterrace


I think jterrace's answer is probably the best way to go, but here is another possibility.

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 

Example:

>>> 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 

Here is a plot showing the time for each share_memory(a,a[::2]) call as a function of the number of elements in a on my computer.

share_memory function

like image 25
user545424 Avatar answered Oct 07 '22 10:10

user545424