Cython使用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

那是设置。该错误来自与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

loadsdurations键入为 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函数。

相关内容

  • 没有找到相关文章

最新更新