numba.guvectorize 数组之间的映射值

Mapping values between arrays with numba.guvectorize

我是 numba 的新手。我有一个 n 大小的“索引”数组 (configuration),其中包含 [0,m) 中的整数和一个大小为 m 的“映射”数组 (phase_values)。我想要的是使用 numba.guvectorize.

configuration 数组的每个元素映射到 phase_values 中的相应值

在 numpy 中,函数如下所示:

def configuration_to_phase_shifts_numpy(configuration, phase_values):
    map_states_to_phase_shifts = np.vectorize(lambda s: phase_values[s])
    return map_states_to_phase_shifts(configuration)

根据 numba 的文档,我理解我需要的等效矢量化代码是:

@numba.guvectorize([(numba.int64[:], numba.complex128[:], numba.complex128[:])], '(n),(m)->(n)',nopython=True)
def configuration_to_phase_shifts(configuration, phase_values, phase):
    for i in range(configuration.shape[0]):
        phase[i] = phase_values[configuration[i]]

但是,在第一次调用函数期间进行编译时:

phase = configuration_to_phase_shifts(configuration, phase_values)

numba 抛出以下错误:

Untyped global name 'configuration_to_phase_shifts': cannot determine Numba type of <class 'numpy.ufunc'>

所以,(除了如何让它工作这个明显的问题),我不明白为什么我的函数是“无类型的”——当我使用 guvectorize 装饰器时,声明了一个输出参数并且是否定义了符号输出布局?



根据@aerobiomat 的回答进行编辑

当我在 @numba.njit 修饰函数中调用向量化函数时出现上述错误,例如:

@numba.njit
def foo():
    phase_values  = np.array([1,2,3], dtype=complex)
    configuration = np.array([0,0,1,1,2,2])
    phase         = configuration_to_phase_shifts(configuration_to_phase_shifts)
    do_stuff(phase)

>>>foo()

Untyped global name 'configuration_to_phase_shifts': cannot determine Numba type of <class 'numpy.ufunc'>
File "<ipython-input>", line 5:
def foo():
    <source elided>
    configuration = np.array([0,0,1,1,2,2])
    phase         = configuration_to_phase_shifts(configuration_to_phase_shifts)
    ^

答案中的 numpy 索引方法解决了问题

在这个例子中使用 Numba 0.53 和 Python 3.8,您的代码似乎没有任何更改就可以正常工作:

>>> configuration = np.array([1,2,0], dtype=int)
>>> phase_values = np.array([4,6,8,1], dtype=complex)
>>> configuration_to_phase_shifts(configuration, phase_values)
array([6.+0.j, 8.+0.j, 4.+0.j])

然而,使用纯 numpy 可以获得相同的结果,不需要任何进一步的优化:

>>> phase_values[configuration]
array([6.+0.j, 8.+0.j, 4.+0.j])

这应该是评论而不是答案,但评论中的格式更难。