这段代码有什么问题?模块类型的未知属性 'array'(<module 'numpy' from filename __init__.py'>

What's wrong in this code? Unknown attribute 'array' of type Module(<module 'numpy' from filename __init__.py'>

我正在尝试使用@vectorize 在函数内创建一个数组,我不知道为什么我一直收到此错误:

Unknown attribute 'array' of type Module( < module 'numpy' from 'filename.... /lib/python3.6/site-packages/numpy/ __ init __ .py'>)

代码:

from numba import vectorize, float32
import numpy as np

@vectorize([float32(float32[:,:], float32[:])], target='cuda')
def fitness(vrp_data, individual):
    # The first distance is from depot to the first node of the first route
    depot = np.array([0.0, 0.0, 30.0, 40.0], dtype=np.float32)
    firstnode = np.array([0.0, 0.0, 0.0, 0.0], dtype=np.float32)
    firstnode = vrp_data[vrp_data[:,0] == individual[0]][0] if 
individual[0] !=0 else depot

    x1 = depot[2]
    x2 = firstnode[2]
    y1 = depot[3]
    y2 = firstnode[3]

    dx = x1 - x2
    dy = y1 - y2
    totaldist = math.sqrt(dx * dx + dy * dy)

    return totaldist

代码在没有函数修饰的情况下工作正常。

问题

Numba 不支持

numpy.array。 Numba 仅支持 Numpy 顶级函数的一个子集(即您调用的任何函数,如 numpy.foo)。这是一个 identical issue from the Numba bug tracker.

"solution"

这是 list of Numpy functions that Numba actually supports。支持 numpy.zeros,因此在理想情况下,您只需将代码中使用 np.array 的行更改为:

depot = np.zeros(4, dtype=np.float32)
depot[2:] = [30, 40]
firstnode = np.zeros(4, dtype=np.float32)

它会起作用的。但是,当定位 cuda all Numpy functions that allocate memory (including np.zeros) are disabled 时。所以你必须想出一个不涉及任何数组分配的解决方案。

使用 vectorize

的问题

此外,vectorize 似乎不是您应该使用的包装函数。相反,一个类似于您编写的函数 requires the use of guvectorize。这是我能够开始工作的与您的原始代码最接近的东西:

import math
from numba import guvectorize, float32
import numpy as np

@guvectorize([(float32[:,:], float32[:], float32[:])], '(m,n),(p)->()')
def fitness(vrp_data, individual, totaldist):
    # The first distance is from depot to the first node of the first route
    depot = np.zeros(4, dtype=np.float32)
    depot[2:] = [30, 40]
    firstnode = np.zeros(4, dtype=np.float32)
    firstnode = vrp_data[vrp_data[:,0] == individual[0]][0] if individual[0] !=0 else depot

    x1 = depot[2]
    x2 = firstnode[2]
    y1 = depot[3]
    y2 = firstnode[3]

    dx = x1 - x2
    dy = y1 - y2
    totaldist[0] = math.sqrt(dx * dx + dy * dy)

签名中的第三个参数实际上是 return 值,因此您可以这样调用该函数:

vrp_data = np.arange(100, 100 + 4*4, dtype=np.float32).reshape(4,4)
individual = np.arange(100, 104, dtype=np.float32)

fitness(vrp_data, individual)

输出:

95.67131

最新 Numba 中更好的错误消息

您可能应该升级您的 Numba 版本。在当前版本中,您的原始代码会引发更具体的错误消息:

TypingError: Failed in nopython mode pipeline (step: nopython frontend). Use of unsupported NumPy function 'numpy.array' or unsupported use of the function.