Reputation: 180
When removing the gil and using a memory view, this error appears:
Fatal Python error: PyThreadState_Get: no current thread
The same object has worked fine as a memory view before. See code below for more details.
# @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
That was the setup. The bug comes from the lines with the commented out # with gil. If i use the gil, the program slows down alot. Also, using the same object as a memory view in another function works perfectly fine. I do not get this.
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
Then the rest of the function.
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
Upvotes: 4
Views: 363
Reputation: 30887
loads
and durations
are typed as ndarray
rather than as memoryviews. When you pass them to the function this will require reference counting and so won't work. Unfortunately Cython doesn't diagnose it at compile-time so it just crashes. Change them to memoryviews in c_calculated_mutation
to fix the problem. Here's a brief example to demonstrate:
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
This gives the output:
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)
If that doesn't fix it there may also be something inside fitness
since we can't see its contents. It either needs to be a nogil
cdef
function (i.e. cdef int fitness(...) nogil:
) or it needs to be a C function.
Upvotes: 3