numba nopython mode "Undefined variable '$313.3'"

1.5k views Asked by At

This is my code to construct minimum trees from an image (f is an image provided by scipy)

It is the foundation of a seam carving program that I am writing.

This snippet works as intended in normal python. When I use @numba.jit without nopython=True, it also works (with a ~200% performance improvement!), but that is in object mode.

When I try to use nopython=True mode it does not compile and I get the error:

Failed at nopython (nopython frontend)
Undefined variable '$313.3'

I don't understand why this will not compile, because I do not see anything that could be undefined.

from numba import jit
from scipy import misc
import numba

f = misc.face()
@jit(nopython=True)
def explorethisx(inar, x):
    places = []
    places.append((x,0))
    x1,y1 = x,0
    s = numba.int64(0)
    co = 0
    #for _ in range( 799):

    while co != numba.int16(799):
        co += 1
        a1,a2,a3 = 999,999,999
        a1 = inar[y1 + 1][x1-1][1]
        a2 = inar[y1 + 1][x1][1]
        a3 = inar[y1 + 1][x1 + 1][1]
        m = a1
        ch = -1
        if m > a2:
            m = a2
            ch = 0
        if m > a3:
            m = a3
            ch = 1
        x1 = x1 + ch
        y1 = y1 + 1
        s += inar[y1][x1][1]
        places.append((x1,y1))
    return([s, places])
explorethisx(f,3)
explorethisx.inspect_types()

Numba is a really cool project, and I am impressed by performance improvements even in python object mode.

1

There are 1 answers

6
MSeifert On BEST ANSWER

The exception message is misleading. It's just that only supports homogeneous lists, so when you try to return [s, places] you return a list containing one "integer" and one "list of tuples of integers" which isn't homogeneous anymore.

Note that this minimal example already demonstrates that exception:

from numba import jit

@jit(nopython=True)
def test():
    places = []
    places.append((1, 2))
    places.append((2, 3))
    return [10, places]

>>> test()
...
TypingError: Failed at nopython (nopython frontend)
Undefined variable '$0.12'

You could simply return a tuple:

return (s, places)

instead of the old

return([s, places])

Even though this compiles - the function contains an out-of-bounds memory access (I had a segfault) when calling the functions so you definetly need to check your memory access as well.