1

I'm trying to create an array inside a function using @vectorize, I don't know why I keep receiving this error:

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

Code:

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

The code works fine without the function decoration.

  • What have you tried? What kind of works and what doesn’t? See [ask] in the [help] for more information. – Eb946207 Dec 20 '18 at 21:33
  • Thanks Ethan for the hint. I think my question is clear and the code is available, you can find answers if you just tried to run the code. – Marwan Abdelatti Dec 20 '18 at 21:48
  • I do not have a python interpreter that I can use at the moment. But I know that error means that `Module.array` does not exist. Do you call `variable.array` somewhere in your code? – Eb946207 Dec 20 '18 at 21:50
  • I jave modified the code to include the import lines I used. I used np.array after I imported numpy as np – Marwan Abdelatti Dec 20 '18 at 21:52
  • 1
    `np.Array`, not `np.array` – Eb946207 Dec 20 '18 at 21:54
  • 1
    Possible duplicate of [Using numpy 'module' object has no attribute 'array'](https://stackoverflow.com/questions/36530726/using-numpy-module-object-has-no-attribute-array) – mx0 Dec 20 '18 at 22:42
  • The auto completion shows array with lower case a. I used np.Array and got: module 'numpy' has no attribute 'Array' – Marwan Abdelatti Dec 20 '18 at 22:43
  • `np.array` is a standard Numpy function for initializing an array from a sequence (such as a list). You're using it correctly (@EthanK the type is `np.ndarray`. `np.Array` doesn't exist). – tel Dec 20 '18 at 23:49
  • @tel Oh. I don't use numpy – Eb946207 Dec 21 '18 at 00:36

1 Answers1

2

The problem

numpy.array is not supported by Numba. Numba only supports a subset of the Numpy top-level functions (ie any function you call like numpy.foo). Here's an identical issue from the Numba bug tracker.

The "solution"

Here's the list of Numpy functions that Numba actually supports. numpy.zeros is supported, so in an ideal world you could just change the lines in your code that use np.array to:

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

and it would work. However, when targeting cuda all Numpy functions that allocate memory (including np.zeros) are disabled. So you'll have to come up with a solution that doesn't involve any array allocation.

Issues with use of vectorize

Also, it looks like vectorize is not the wrapper function you should be using. Instead, a function like the one you've written requires the use of guvectorize. Here's the closest thing to your original code that I was able to get to work:

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)

The third argument in the signature is actually the return value, so you call the function like:

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)

Output:

95.67131

Better error message in latest Numba

You should probably upgrade your version of Numba. In the current version, your original code raises a somewhat more specific error message:

TypingError: Failed in nopython mode pipeline (step: nopython frontend). Use of unsupported NumPy function 'numpy.array' or unsupported use of the function.
tel
  • 13,005
  • 2
  • 44
  • 62
  • Wow! this is really beyond my expectations. Very neat, very detailed with example. Thank you very much. * Can you please explain to me the meaning of: '(m,n),(p)->()' in the decoration line? * There is no 'target' argument for guvector ? I think I will give up Anaconda since it does not upgrade numba over 0.39 – Marwan Abdelatti Dec 21 '18 at 04:26
  • 1
    Translated to plain english, `'(m,n),(p)->()'` as the second arg of `guvectorize` means: "This is a function that takes one array of shape `(m,n)` and one array of shape `(p)` and returns a scalar". `guvectorize` requires this second argument since the function being wrapped cannot have an explicit return value. – tel Dec 21 '18 at 04:50
  • Thanks again @tel. One more question please, * There is no 'target='cuda'' argument for guvector ? – Marwan Abdelatti Dec 21 '18 at 04:54
  • 1
    There is, but as I said in the answer when you have that flag set, all of the array creation functions will be disabled. You'll have to change the algorithm of your `fitness` function to deal with that. Either pass in pre-made versions of `depot` and `firstnode`, or make them plain lists. – tel Dec 21 '18 at 04:58