我不太明白如何在大型/更长的 nogil 部分中使用 memoryviews 完成引用计数。让我们假设基本上我所有的代码都是 nogil,除了在深处创建一个 numpy-array-to-memoryview 。内存视图被返回并向上使用。
一个相当简单的例子是
import numpy as np
cdef:
double[::1] mv
cdef double[::1] someFun(int nn) nogil:
cdef:
double[::1] mvb
with gil:
mvb = np.arange(nn, dtype=np.double)
return mvb
with nogil:
mv = someFun(30)
# Here could be MUCH more "nogil" code
# How is memory management/reference counting done here?
我假设当 someFun() 返回 memoryview 时,numpy 数组的引用计数仍应为 1。Cython 之后如何处理引用计数?我的意思是即使内存视图/数组被取消引用,也不允许更改引用计数,对吗?如果上面有几个带有 nogil 代码的层,它怎么知道取消对 memoryview 的引用,并且可能与 someFun() 不同,memoryview 没有向上返回?
编辑:所以我想出了一个相当粗略的方法来做更多的测试。我的代码现在看起来像这样。
import numpy as np
cdef extern from "stdio.h":
int getchar() nogil
int printf(const char* formatt, ...) nogil
cdef:
double[::1] mv, mv2 = np.ones(3)
int ii, leng = 140000000
cdef double[::1] someFun(int nn) nogil:
cdef:
double[::1] mvb
with gil:
mvb = np.ones(nn, dtype=np.double)
return mvb
with nogil:
mv = someFun(leng)
printf("1st stop")
getchar()
mv = mv2
printf("2nd stop")
getchar()
对我来说有趣的部分是在第一站mv
仍然分配了数组/内存视图,但是当我取消引用它直到第二站才被释放。我只检查了内存使用情况htop
(这就是为什么选择如此大的数组),可能有更好的方法。显然,我想要发生的自由/引用计数行为,但是当它没有 GIL 时它会这样做很奇怪。也许内存视图不完全是nogil?
有人可以解释这是否是可靠的行为吗?