Pertanyaan Apakah ada cara untuk memeriksa apakah NumPy array berbagi data yang sama?


Kesan saya adalah bahwa di NumPy, dua larik dapat berbagi memori yang sama. Ambil contoh berikut:

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

Sangat jelas b tidak membuat salinan a; itu hanya menciptakan beberapa meta-data baru dan melekatkannya ke buffer memori yang sama itu a menggunakan. Apakah ada cara untuk memeriksa apakah dua array mereferensi buffer memori yang sama?

Kesan pertamaku adalah menggunakannya a.data is b.data, tapi itu mengembalikan salah. dapat saya lakukan a.data == b.data Yang mengembalikan Benar, tapi saya tidak berpikir bahwa cek untuk memastikan a dan b berbagi buffer memori yang sama, hanya itu blok memori yang direferensikan oleh a dan yang direferensikan oleh b memiliki byte yang sama.


32
2017-07-02 01:09


asal


Jawaban:


Saya pikir jawaban jterrace mungkin adalah cara terbaik untuk pergi, tetapi di sini ada kemungkinan lain.

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

Contoh:

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

Di sini adalah plot yang menunjukkan waktu untuk masing-masing share_memory(a,a[::2]) panggilan sebagai fungsi dari sejumlah elemen dalam a di komputer saya.

share_memory function


8
2017-07-02 03:16



Anda dapat menggunakan mendasarkan atribut untuk memeriksa apakah array berbagi memori dengan array lain:

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

Tidak yakin apakah itu memecahkan masalah Anda. Atribut dasar akan menjadi None jika larik memiliki memori sendiri. Perhatikan bahwa basis array akan menjadi array lain, bahkan jika itu adalah subset:

>>> c = a[2:]
>>> c.base is a
True

26
2017-07-02 01:30



Kerjakan saja:

a = np.arange(27)
a.__array_interface__['data']

Baris kedua akan mengembalikan tuple di mana entri pertama adalah alamat memori dan yang kedua adalah apakah array hanya dibaca. Dikombinasikan dengan bentuk dan tipe data, Anda dapat mengetahui rentang alamat memori yang tepat yang mencakup larik, sehingga Anda juga dapat bekerja dari ini ketika satu array adalah bagian dari yang lain.


4
2018-03-10 14:58