Search code examples
pythoncython

The value in cython array is changed randomly


Here is my cython code.

self.point_index_array attribute is array whose values increase by 1 from 0.

[0, 1, 2, 3, 4, 5, .....]

The values are normal when first declared, but when the array is accessed from another function, the values of the first four elements are automatically changed.

python and cython version

  • Python 3.9.13
  • Cython 0.29.34

Here is my sudo code

cdef class KdTree:
    cdef uint32_t* point_index_array

    def __cinit__(KdTree self):
        self.point_index_array = NULL

    def __init__(KdTree self, 
                 np.ndarray points not None, 
                 int num_of_leaf=16):
        cdef np.ndarray[uint32_t, ndim=1] point_index_list
        point_index = np.arange(0, self.num_of_points, dtype=np.uint32)
        point_index_list = np.ascontiguousarray(point_index.ravel(), dtype=np.uint32)
        self.point_index_array = <uint32_t*>point_index_list.data
    
        # kdtree...

        # its normal
        self.print_index_array()

    def print_index_array(self):
        for index in range(10):
          print(f"index {index} => {self.point_index_array[index]}")


    def neighbor_search(self, float distance):
        # values in self.point_index_array are changed 
        self.print_index_array()

normal output is (__init__)

index 0 => 390
index 1 => 469
index 2 => 493
index 3 => 492
index 4 => 396
index 5 => 490
index 6 => 397
index 7 => 117
index 8 => 484
index 9 => 9

abnormal output is (neighbor_search)

index 0 => 1171518192
index 1 => 504
index 2 => 1174758304
index 3 => 504
index 4 => 396
index 5 => 490
index 6 => 397
index 7 => 117
index 8 => 484
index 9 => 9

I don't understand why this happens at all.

Could you let me know what I'm missing?


Solution

  • @slothrop thanks for your appreciate!

    "point_index_list" variable is python object in previous code, so it was removed by GC.

    so, i save this object to class attribute.

    cdef class KdTree:
      cdef uint32_t* point_index_array
      cdef readonly np.ndarray point_index_list
    
      def __init__(KdTree self, 
                    np.ndarray points not None, 
                    int num_of_leaf=16):
    
        point_index = np.arange(0, self.num_of_points, dtype=np.uint32)
    
        # this code will prevent CG of point_index_list
        self.point_index_list = np.ascontiguousarray(point_index.ravel(), dtype=np.uint32)
        self.point_index_array = <uint32_t*>self.point_index_list.data