删除GIL并使用内存视图时,出现此错误:
Fatal Python error: PyThreadState_Get: no current thread
同一对象以前作为内存视图都很好地工作。有关更多详细信息,请参见下面的代码。
# @boundscheck(False)
# @wraparound(False)
# @nonecheck(False)
cpdef c_calculated_mutation(
np.ndarray[int, ndim=3] population,
long mutations,
long[:] depotmap,
double[:,:] mapping,
np.ndarray[long, ndim=1] loads,
dict max_loads,
np.ndarray[long, ndim=1] durations,
dict max_durations
):
cdef:
int[:,:,:] pop = population
int xLen = len(population[0][0])
int yLen = len(population[0])
int zLen = len(population)
list export_changes = []
int x, y, z, xx, yy, i, max_depot, prev, value, mutation
float new_fitness, best
int[:,:] view
int* load_limits = <int*>malloc(len(max_loads) * sizeof(int))
int* duration_limits = <int*>malloc(len(max_durations) * sizeof(int))
int* fxes = <int*>calloc(mutations, sizeof(int))
int* fyes = <int*>calloc(mutations, sizeof(int))
int* txes = <int*>calloc(mutations, sizeof(int))
int* tyes = <int*>calloc(mutations, sizeof(int))
int* zes = <int*>calloc(mutations, sizeof(int))
int* xxx = <int*>calloc(mutations, sizeof(int))
int* yyy = <int*>calloc(mutations, sizeof(int))
int* zzz = <int*>calloc(mutations, sizeof(int))
i=0
for value in max_loads:
load_limits[i] = int(max_loads[value])
duration_limits[i] = int(max_durations[value])
max_depot = value
i += 1
for mutation in prange(mutations, nogil=True):
z = rand() % zLen
y = rand() % yLen
x = rand() % xLen
value = population[z, y, x]
while value >= 0:
x = rand() % xLen
value = population[z, y, x]
xxx[mutation] = x
yyy[mutation] = y
zzz[mutation] = z
那是设置。该错误来自与GIL评论的#。如果我使用GIL,则程序会减慢很多。另外,在另一个功能中使用相同的对象作为内存视图非常好。我不明白。
for mutation in prange(mutations, nogil=True, num_threads=8):
x = xxx[mutation]
y = yyy[mutation]
z = zzz[mutation]
value = population[z, y, x]
xx = x
# with gil:
best = fitness(pop[z,:,:], xLen, yLen, depotmap, max_depot, mapping, loads, load_limits, durations, duration_limits)
for yy in range(yLen):
prev = population[z, yy, xx]
population[z, yy, xx] = value
population[z, y, x ] = prev
# with gil:
new_fitness = fitness(pop[z, :, :], xLen, yLen, depotmap, max_depot, mapping, loads, load_limits, durations, duration_limits)
if best > new_fitness:
best = new_fitness
fxes[mutation] = x
fyes[mutation] = y
txes[mutation] = xx
tyes[mutation] = yy
zes[mutation] = z
population[z, y, x ] = value
population[z, yy, xx] = prev
然后函数的其余部分。
for mutation in range(mutations):
x = fxes[mutation]
y = fyes[mutation]
xx = txes[mutation]
yy = tyes[mutation]
z = zes[mutation]
export_changes += [z]
prev = population[z, yy, xx]
population[z, yy, xx] = population[z, y, x]
population[z, y, x ] = prev
free(load_limits)
free(duration_limits)
free(fxes)
free(fyes)
free(txes)
free(tyes)
free(zes)
free(xxx)
free(yyy)
free(zzz)
return population, export_changes
loads
和 durations
键入为 ndarray
,而不是记忆视图。当您将它们传递到功能时,这将需要参考计数,因此无法正常工作。不幸的是,Cython在编译时没有诊断出它,因此它崩溃了。将它们更改为c_calculated_mutation
中的内存视图以解决问题。这是一个简短的例子:
cimport numpy as np
# won't allow me to add "nogil" at Cython compile stage
cdef int f(np.ndarray[np.int32_t,ndim=1] x):
return 1
cdef int g(np.int32_t[:] x) nogil:
return 2
def call_funcs(np.ndarray[np.int32_t,ndim=1] a, np.int32_t[:] b):
# can't do "with nogil:" - needs gil to call
f(a)
with nogil:
g(b) # fine
print("g(b) done")
with nogil:
g(a) # crashes
这给出了输出:
g(b) done
Fatal Python error: PyThreadState_Get: no current thread
Current thread 0x00007f3233184540 (most recent call first):
File "<stdin>", line 1 in <module>
Aborted (core dumped)
如果在那里无法修复它,则在fitness
中也有一些东西,因为我们看不到其内容。它要么需要是nogil
cdef
函数(即cdef int fitness(...) nogil:
(,要么需要是C函数。