gpt4 book ai didi

python - 在不复制的情况下将 C 数组绑定(bind)到 Numpy 数组

转载 作者:太空狗 更新时间:2023-10-29 18:09:23 25 4
gpt4 key购买 nike

我正在编写一个 Python 类,它将包装一个包含 C 结构的 C 模块。我使用的是 Cython 语言(Python 和 C 的超集语言)。 C 结构在构造函数中被 malloc,并包含一个我想在 Python 中使用的数组。该数组将在 Python 中表示为 NumPy 数组,但我不想将值复制到它。我想将 NumPy 数组直接链接到 malloc 的内存。对于此任务,我使用 NumPy Array API特别是这个功能:

PyObject* PyArray_SimpleNewFromData (int nd, npy_intp* dims, int typenum, void* data)

我设法在 Cython 中使用此代码将 NumPy 数组绑定(bind)到 C 结构的数组,只要 NumPy 数组和 MultimediaParams 就可以正常工作。对象具有相同的生命周期:

cdef class MultimediaParams:
def __init__(self, **kwargs):
self._mm_np = < mm_np *> malloc(sizeof(mm_np))
#some code...

def as_ndarray(self): #TODO: what if self deallocated but numpy array still exists(segfault?)
cdef numpy.npy_intp shape[1]
cdef int arr_size = sizeof(self._mm_np[0].n2) / sizeof(self._mm_np[0].n2[0])
shape[0] = < numpy.npy_intp > arr_size
cdef numpy.ndarray ndarray
ndarray = numpy.PyArray_SimpleNewFromData(1, shape, numpy.NPY_DOUBLE, self._mm_np[0].n2)

return ndarray

def __dealloc__(self):
free(self._mm_np)

如您所见,该类有其 __dealloc__方法将处理在 C 中分配的内存并在没有对 MultimediaParams 的引用时释放它实例。

在这种绑定(bind)中,NumPy 不拥有数组的内存。

问题:当MultimediaParams对象被释放并且数组的内存被释放,NumPy 对象仍然指向刚刚被释放的内存。当 NumPy 对象尝试访问/修改已释放的内存时,这将导致段错误。

我怎样才能确保 MultimediaParams只要有一个 NumPy 对象在使用它的内存,对象就不会被释放?

据我所知,我需要做的就是让 NumPy 对象引用 MultimediaParams它从中获得要指向的内存的实例。我尝试使用 ndarray.base = <PyObject*>self所以 NumPy 会知道它的基础对象,这应该添加另一个对 MultimediaParams 的引用实例,只要 NumPy 数组还存在,就会导致它不会被释放。这一行导致我的测试失败,因为 NumPy 数组的内容变成了垃圾。

澄清:NumPy 数组不拥有 C 数组内存,我不希望它拥有。我想要 MultimediaParams负责释放 C 结构(包含数组数据),但只要 NumPy 对象还活着就不会这样做。

有什么建议吗?

最佳答案

正如@J.F.Sebastian 的评论所指出的,问题很可能是当您正确地将指向您的 MultitimediaParams 实例的指针分配给 NumPy 数组的 base 引用时,你实际上并没有增加它的引用计数,因为赋值是在 C 中而不是在 Python 中进行的。这可能会导致 MultitimediaParams 对象的过早垃圾回收,其内存被重用并导致您在 ndarray 中体验到垃圾数据。

使用宏 Py_INCREF 手动增加 MultitimediaParams 对象的引用计数应该会产生所需的行为。

关于python - 在不复制的情况下将 C 数组绑定(bind)到 Numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33478046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com