Search code examples
pythonpython-3.xloopscythontyped-memory-views

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.


Solution

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