[英]Cython crashed using memoryviews
刪除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
那是設置。 這個bug來自於#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中的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函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.