Can't call numba functions from inside njit'ed functions

Viewed 7477

Working with numba, I stumbled upon very unexpected behavior. I created an nb.njit function inside of which I was trying to create a nb.typed.List of int8 numpy arrays, so I tried to create a corresponding numba type.

nb.int8[:]  # type of the list elements

So, I set this type to an nb.typed.List via lsttype keyword.

l = nb.typed.List(lsttype=nb.int8[:])  # list of int8 numpy ndarrays

What I got is:

numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function getitem>) found for signature:
 
 >>> getitem(class(int8), slice<a:b>)
 
There are 16 candidate implementations:
   - Of which 16 did not match due to:
   Overload in function 'getitem': File: <built-in>: Line <N/A>.
     With argument(s): '(class(int8), slice<a:b>)':
    No match.

Which, I suppose, means that numba is trying to slice the nb.int8 type object, as if it doesn't understand the notation.

So, I tried it the other way, creating an empty array of np.int8 type, and using the nb.typeof function.

nb.typeof(np.array([], dtype=np.int8))

And it returned:

numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Unknown attribute 'typeof' of type Module(<module 'numba' from '/Users/.../venv37/lib/python3.7/site-packages/numba/__init__.py'>)

This I do not understand! How can numba not see itself?

The minimum example is very simple:

import numba as nb
import numpy as np

@nb.njit
def v():
    print(nb.typeof(np.array([], dtype=np.int8)))

v()

So I tried using the same function, but without the @nb.njit.

AND IT PRINTS!

array(int8, 1d, C)

Also, I tried importing numba inside the function, since it doesn't see the module, but it produced:

numba.core.errors.UnsupportedError: Failed in nopython mode pipeline (step: analyzing                    bytecode)
Use of unsupported opcode (IMPORT_NAME) found

I tried reinstalling and updating both numba and numpy, also.

What kind of trickery is that?

2 Answers

I found a nasty workaround.

@nb.njit
def f(types=(nb.int8[::1], nb.float64[::1])):
    a = nb.typed.List.empty_list(types[0])
    b = nb.typed.List.empty_list(types[1])
    # and so on...

[::1] means a 1-dimensional numpy.ndarray of C-type.

What about letting numba figure the type out by itself?

@nb.njit
def v():
    l=nb.typed.List()
    l.append(np.array([1,2,3], dtype=np.int8))
    return l
v()

Returns ListType[array(int8, 1d, C)]([[1 2 3]]) for me

Related