Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the efficient way to check two memoryviews in loop?

I want to speed up my code by using memoryviews. here are two classes I use:

cdef class child:
    cdef public int[:] move
    def __init__(self, move):
        self.move = move

cdef class parent:
    cdef public:
        list children
        int[:, :] moves
    def __init__(self):
        self.children = []
    def add_children(self, moves):
        cdef int i = 0
        cdef int N = len(moves)
        for i in range(N):
            self.children.append(child(moves[i]))

And this is the code I want to check whether the classes work or not:

temp = []
for i in range(100):
    temp.append([i, i+1])

cdef int[:, :] moves = np.asarray(temp, dtype=np.int32)
a = parent()
a.add_children(moves)
for move in moves:
    for ch in a.children:
        if move == ch.move:
            print('ok')

I expect for 100 to print ok but I get nothing. I know if I use the list(move) == list(ch.move) I can get the expected output but I don't want the conversion overhead in loops.

Can anyone help me with an efficient way? If anyone has any other suggestion which improves the code speed, It would be appreciated.

like image 528
Masoud Masoumi Moghadam Avatar asked Aug 05 '17 08:08

Masoud Masoumi Moghadam


Video Answer


2 Answers

I'd probably use numpy.array_equal. (It accepts memoryviews as well as numpy arrays.)

if numpy.array_equal(move, ch.move):
  print("OK")

The main advantage over memcmp (that the other answer suggests) is that memcmp will not work on non-contiguous array (which the other answer admits). It's easy to get a non-contiguous memoryview just by taking a column of a 2D memoryview.

like image 52
DavidW Avatar answered Oct 13 '22 20:10

DavidW


You could utilize memcmp (function that compares memory) from the c library:

from libc.string cimport memcmp

cdef int[:, :] moves = np.asarray(temp, dtype=np.int32)
cdef int[:] move
cdef child ch
a = parent()
a.add_children(moves)
for move in moves:
    for ch in a.children:
        if memcmp(&move[0], &ch.move[0], move.nbytes) == 0:
            print('ok')

However that could (probably) lead to problems if the memoryviews have different dtypes, endianness or strides - because memcmp just compares the plain memory.

like image 34
MSeifert Avatar answered Oct 13 '22 19:10

MSeifert