gpt4 book ai didi

python - 分配在同一地址的数组 Cython + Numpy

转载 作者:太空宇宙 更新时间:2023-11-04 02:29:45 24 4
gpt4 key购买 nike

我在使用 numpy + cython 时遇到了一些有趣的内存行为,同时尝试从 numpy 数组中获取数据作为 C 数组,以在无 GIL 函数中使用。我已经查看了 cython 和 numpy 的数组 API,但没有找到任何解释。因此请考虑以下代码行:

cdef np.float32_t *a1 = <np.float32_t *>np.PyArray_DATA(np.empty(2, dtype="float32"))
print "{0:x}".format(<unsigned int>a1)
cdef np.float32_t *a2 = <np.float32_t *>np.PyArray_DATA(np.empty(2, dtype="float32"))
print "{0:x}".format(<unsigned int>a2)[]

我用 numpy 的空函数分配了两个 numpy 数组,并想为每个数组检索一个指向数据缓冲区的指针。您会期望这两个指针指向堆上的两个不同内存地址,可能间隔 2*4 字节。但是不,我得到指向相同内存地址的指针,例如

>>>96a7aec0
>>>96a7aec0

怎么会?我设法通过在 PyArray_DATA 调用之外声明我的 numpy 数组来解决这个问题,在这种情况下,我得到了我期望的结果。

我能想到的唯一解释是,我没有在 PyArray_DATA 函数的范围之外创建任何 Python 对象,并且调用此函数不会增加 Python 的引用计数。因此,GC 会立即回收此内存空间,并将下一个数组分配到现在空闲的前一个内存地址。有比我更懂 cython 的人可以证实这一点或给出其他解释吗?

最佳答案

您创建了两个临时 numpy 数组,它们恰好位于同一地址。由于没有为它们保留 python 引用,它们会立即被垃圾收集,a1a2 也成为悬空指针。

如果为他们保留引用,他们的地址不能相同,例如:

cdef int[:] a = np.arange(10)  # A memoryview will keep the numpy array from GC.
cdef int[:] b = np.arange(10)
cdef int* a_ptr = &a[0]
cdef int* b_ptr = &b[0]
print(<size_t>a_ptr)
print(<size_t>b_ptr)

在使用对象的基础数据时必须格外小心。如果使用不当,经常会遇到悬空指针。 例如:

void cfunc(const char*)
# Fortunately, this won't compile in cython.
# Error: Storing unsafe C derivative of temporary Python reference
cdef const char* = ("won't" + " compile").encode()
cfunc(char)

正确的方法:

# make sure keep_me is alive before cfunc have finished with it.
cdef bytes keep_me = ("right" + "way").encode()
cfunc(temp)
# Or for single use.
cfunc(("right" + "way").encode())

C++ std::string 的成员 c_str() 的另一个例子:

// The result of `+` will immediately destructed. cfunc got a  dangling pointer.
const char * s = (string("not") + string("good")).c_str();
cfunc(s);

正确的方法:

// keep `keep_me` for later use.
string keep_me = string("right") + string("way");
cfunc(keep_me.c_str());
// Or, for single use.
cfunc((string("right") + string("way")).c_str())

引用:std::string::c_str() and temporaries

关于python - 分配在同一地址的数组 Cython + Numpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49507801/

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