Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numba - does nopython mode support list of tuples?

I would like to clarify that this is my first experience with Numba, so I am very far from being an expert. I am trying to manually implement an easy KNN, here's the code:

@jit(nopython=True)
def knn(training_set, test_set):
for q in range(len(test_set)):
    indexes = [-1]
    values = [np.inf]
    thres = values[-1]

    for u in range(len(training_set)):
        dist = 0
        flag = False
        dist = knn_dist(training_set[u], test_set[q], thres)
        if dist == 0:
            flag = True
        if not flag:

            '''
            Binary search to obtain the index
            '''    

            # Various code

return

Now, I would like to use the nopython mode of numba to optimize the code, here's part of the error:

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
 in _call_incref_decref(self, builder, root_type, typ, value, funcname, getters)
    185             try:
--> 186                 meminfo = data_model.get_nrt_meminfo(builder, value)
    187             except NotImplementedError as e:

 in get_nrt_meminfo(self, builder, value)
    328                 raise NotImplementedError(
--> 329                     "unsupported nested memory-managed object")
    330         return value

NotImplementedError: unsupported nested memory-managed object

Both the training and the test set are lists of lists of tuples, I wonder if this data structure is supported by nopython, and if not (as it seems), which data structure could I use to make it possible? Am I forced to change numba mode?

P.s. to better clarify, an example of training/test is the following:

[[(0, 1), (1, 1), (2, 1), (3, 2), (4, 5)], [(0, 2), (1, 4), (2, 3), (3, 4), (4, 2)], [(0, 5), (1, 4), (2, 3), (3, 4), (4, 2)], [(0, 6), (1, 5), (2, 4), (3, 3), (4, 2)], [(0, 0), (1, 9), (2, 8), (3, 9), (4, 8)], [(0, 5), (1, 4), (2, 3), (3, 4), (4, 2)]]
like image 805
Laeneven Avatar asked Aug 15 '18 10:08

Laeneven


People also ask

Does Numba support tuples?

Numba supports function calls using positional and named arguments, as well as arguments with default values and *args (note the argument for *args can only be a tuple, not a list). Explicit **kwargs are not supported.

What is Nopython in Numba?

nopython. Numba has two compilation modes: nopython mode and object mode. The former produces much faster code, but has limitations that can force Numba to fall back to the latter. To prevent Numba from falling back, and instead raise an error, pass nopython=True .

Does Numba work with list comprehension?

Numba supports list comprehension, but not the creation of nested list.

Is Numba better than Cython?

The Takeaway. So numba is 1000 times faster than a pure python implementation, and only marginally slower than nearly identical cython code. There are some caveats here: first of all, I have years of experience with cython, and only an hour's experience with numba.


1 Answers

does nopython mode support list of tuples?

Yes, it does. But, as your error message implies, not a nested list.

Am I forced to change numba mode?

No, you are not.


You can trivially convert your list of tuples L to a regular NumPy array:

L_arr = np.array(L)

Here's a demonstration and how you can test for yourself:

from numba import jit

L = [[(0, 1), (1, 1), (2, 1), (3, 2), (4, 5)], [(0, 2), (1, 4), (2, 3), (3, 4), (4, 2)],
     [(0, 5), (1, 4), (2, 3), (3, 4), (4, 2)], [(0, 6), (1, 5), (2, 4), (3, 3), (4, 2)],
     [(0, 0), (1, 9), (2, 8), (3, 9), (4, 8)], [(0, 5), (1, 4), (2, 3), (3, 4), (4, 2)]]

L_arr = np.array(L)

@jit(nopython=True)
def foo(x):
    return x

With L this gives an error:

print(foo(L))

LoweringError: Failed at nopython (nopython mode backend)
reflected list(reflected list((int64 x 2))): unsupported nested memory-managed object

With L_arr, you have a 3-dimensional NumPy array of shape (6, 5, 2):

print(foo(L_arr))

array([[[0, 1],
        [1, 1],
        [2, 1],
        [3, 2],
        [4, 5]],
        ...
       [[0, 5],
        [1, 4],
        [2, 3],
        [3, 4],
        [4, 2]]])

You may then wish to refactor your logic to work more efficiently with the NumPy array instead of a nested list of tuples.

like image 158
jpp Avatar answered Nov 03 '22 02:11

jpp