In numba, what's the difference between array(float64, 1d, C) and array(float64, 1d, A)?

Viewed 1335

I have two simple and similar functions. One can compile with numba while the other can't. I can't understand the difference between them.The following are these two functions:

The first one:

@nb.njit(float64[:](float64[:], float64[:]))
def arrAdd(a,b):
    assert a.shape == b.shape
    return a + b

It succeed in compiling. When I call it,

arrAdd(np.array([1,2.0,21]),np.array([2,3.0,1]))

It will return:

array([ 3.,  5., 22.])

The second one:

c = np.array([1,2.0,21])
@nb.njit
def arrAdd1(arr):
    return arrAdd(arr,c)

However, when I call this function:

arrAdd1([2,3.0,1])

it will show:

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Invalid use of type(CPUDispatcher(<function arrAdd at 0x00000212A9FDC670>)) with parameters (array(float64, 1d, C), readonly array(float64, 1d, C))
Known signatures:
 * (array(float64, 1d, A), array(float64, 1d, A)) -> array(float64, 1d, A)
During: resolving callee type: type(CPUDispatcher(<function arrAdd at 0x00000212A9FDC670>))
During: typing of call at <ipython-input-57-c77e552c5560> (4)


File "<ipython-input-57-c77e552c5560>", line 4:
def arrAdd1(arr):
    return arrAdd(arr, c)
    ^

So what's the difference between array(float64, 1d, C)) and array(float64, 1d, A)?

1 Answers

A (any), C (C-contiguous) and F (Fortran-contiguous) are the three types of array layout. But that's not the problem in your example.

Problem 1

In this line

arrAdd1([2,3.0,1])

you are passing a list instead of an array.

The following simplified version works:

@nb.njit                            # No types
def arrAdd(a, b):
    assert a.shape == b.shape
    return a + b

a = arrAdd(np.array([1, 2.0, 21]), np.array([2, 3.0, 1]))
print(a)

c = np.array([1, 2.0, 21])
@nb.njit                            # No types
def arrAdd1(arr):
    return arrAdd(arr, c)

a = arrAdd1(np.array([2,3.0,1]))    # Pass an array
print(a)

and produces

[ 3.  5. 22.]
[ 3.  5. 22.]

Problem 2

In your example arrAdd1() is defined as a closure, so c becomes a constant in the function.

If you really want to use explicit parameter types, you need to specify that addArr() will receive a constant array at least in the second parameter.

Al long as the functions don't modify their inputs, you can declare all input parameters readonly, as in this example, that produces the same result:

vector = nb.types.Array(dtype=f8, ndim=1, layout="A")
readonly_vector = nb.types.Array(dtype=f8, ndim=1, layout="A", readonly=True)

@nb.njit(vector(readonly_vector, readonly_vector))
def arrAdd(a, b):
    assert a.shape == b.shape
    return a + b

a = arrAdd(np.array([1, 2.0, 21]), np.array([2, 3.0, 1]))
print(a)

c = np.array([1, 2.0, 21])
@nb.njit(vector(readonly_vector))
def arrAdd1(arr):
    return arrAdd(arr, c)

a = arrAdd1(np.array([2,3.0,1]))
print(a)

You can change the layout (A, C, F) to the one that suits you best.

Related