对于函数局部变量的缓冲区类型意外抛出 Cython 错误

Cython error thrown unexpectedly for buffer types which ARE function local variables

刚学Cython,运行报了一个我不明白的错误,好吧我不明白为什么会在下面的函数中抛出。纯 Python 版本按预期工作。

import numpy as np
cimport numpy as np

ctypedef np.int8_t DTYPE_int8
ctypedef np.int64_t DTYPE_int64

cdef int fitness(np.ndarray[DTYPE_int8, ndim=1] c):
    
    cdef np.ndarray[DTYPE_int8, ndim=1] a
    cdef np.ndarray[DTYPE_int8, ndim=1] d1_cnts
    cdef np.ndarray[DTYPE_int8, ndim=1] d2_cnts
    
    a = np.arange(N, dtype=np.int8)
    d1_cnts = np.unique(c - a, return_counts=True)[1]
    d2_cnts = np.unique(c + a, return_counts=True)[1]
    d1_cnts = sum(sum(range(n)) for n in d1_cnts)
    d2_cnts = sum(sum(range(n)) for n in d2_cnts)
    return d1_cnts + d2_cnts

pop = np.arange(N, dtype=np.int8)
print(fitness(pop))

我收到 d1_cnts 和 d2_cnts 的错误“缓冲区类型只允许作为函数局部变量”。这两个变量都是函数局部变量(对吧?),那么为什么会出现这个错误?

它们被捕获在生成器表达式中:

(sum(range(n)) for n in d1_cnts)

在这种情况下,生成器表达式立即被 sum 使用,但 Cython 担心您可能 return 生成器表达式(带有捕获的变量)的一般情况。

您的两个选择是:

  1. 使用限制较少的类型化内存视图
  2. 切换到不捕获变量的列表理解求和。

我认为 Cython 最终应该相当有效地优化生成器表达式,但错误消息出现在更早的阶段,在它意识到这是一个选项之前。


另外 sum(range(n)) 应该可以用三角数公式替换((n-1)*n/2 我认为),但这是一个单独的优化