gpt4 book ai didi

python - cython prange 获取 pyeval_savethread : null tstate 错误

转载 作者:行者123 更新时间:2023-12-01 08:31:57 28 4
gpt4 key购买 nike

总是出现“pyeval_savethread: null tstate”错误

我尝试使用 cython 通过 prange 进行一些并行计算。但是我发现当我使用返回指针的函数时,我会得到上面的错误。我真的不知道如何处理这个问题。

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef double *jonswap(double *w, double Hs, double Tp, int n, double gamma = 3.7) nogil:
'''
Function to obtain Jonswap spectra
w: wave frequency range [rad/s]
'''
cdef:
double *sigma = <double*>malloc(n * sizeof(double))
double *a = <double*>malloc(n * sizeof(double))
double fhs = Hs * Hs
double ftp = Tp * Tp * Tp * Tp
double wp = 2 * M_PI / Tp
Py_ssize_t i

cdef double *sj = <double*>malloc(n * sizeof(double))

with nogil:
for i in range(n):
sigma[i] = 0.07 if w[i] < wp else 0.09
a[i] = exp(-0.5 * pow((w[i] - wp) / (sigma[i] * w[i]), 2.0))
sj[i] = 320 * fhs * pow(w[i], -5.0) / ftp * exp(-1950 * pow(w[i], -4) / ftp) * pow(gamma, a[i])



free(sigma)
free(a)

return sj

def test():
cdef:
double dw = 0.05
int n = 43
int i = 0
double *w = <double*>malloc(n * sizeof(double))
double Hs = 3.0
double Tp = 8.0

for i in range(n):
w[i] = 0.35 + i * dw

# initialize Jonswap spectra and wave elevation
cdef:
double *S_wave
int j
double suma = 0.0
# double[:] z = np.zeros((n), dtype=DTYPE_float)

with nogil, parallel():
S_wave = jonswap(w, Hs, Tp, n)
for i in prange(100, schedule='guided'):
suma += sumw(S_wave,n)
free(S_wave)

return suma

cdef double sumw(double *s, int n) nogil:
cdef:
int i
double suma = 0
for i in range(n):
suma += s[i]

return suma

这只是一个测试。编译时不会出现错误。但是当我运行测试函数时,它收到错误。我想知道是否有人知道如何解决这个问题。我真的很感激。

最佳答案

由于您的示例不完整,我创建了一个更简单的示例,它证实了我最初的想法,即问题与 nogil 函数内的 nogil block 有关:

cdef int f(int x) nogil:
cdef int y
with nogil:
y = x+1 # do some work without the GIL
return x

def test():
cdef int out
with nogil:
out = f(1)

给予:

Fatal Python error: PyEval_SaveThread: NULL tstate

问题在于,f 内的 with nogil block 会在您不持有 GIL 时尝试释放它,或者在最后尝试重新获得它当它不应该做的时候,阻止它。解决方案是删除不必要的 with nogil: block (在本例中位于 f 内,在您的情况下位于 jonswap 内)

理想情况下,Cython 应该将其标记为错误。

<小时/>

编辑:一个简化的测试,显示您可以在并行 block 中返回指针而不会出现错误。它没有做任何有用的事情。

from libc.stdlib cimport malloc, free

from cython.parallel import prange, parallel


def test():
cdef:
double *S_wave
int i
double suma = 0
int n = 50

with nogil, parallel():
S_wave = allocate(n)
for i in prange(100):
suma += sumw(S_wave,n)
free(S_wave)

print(suma)

cdef double sumw(double *s, int n) nogil:
cdef:
int i
double suma = 0
for i in range(n):
suma += s[i]

return suma

cdef double* allocate(int n) nogil:
cdef double* out = <double*>malloc(sizeof(double)*n)
cdef int i
for i in range(n):
out[i] = i*0.5
return out

关于python - cython prange 获取 pyeval_savethread : null tstate 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53876148/

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