Tengo dos funciones simples y similares. Uno puede compilar con numba mientras que el otro no. No puedo entender la diferencia entre ellos. Las siguientes son estas dos funciones:

El primero:

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

Logra compilar. Cuando lo llamo

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

Regresará:

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

El segundo:

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

Sin embargo, cuando llamo a esta función:

arrAdd1([2,3.0,1])

Mostrará:

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)
    ^

Entonces, ¿cuál es la diferencia entre array (float64, 1d, C)) y array (float64, 1d, A)?

1
DennisDai 25 feb. 2021 a las 08:56

1 respuesta

La mejor respuesta

A (cualquiera), C (C-contiguo) y F (Fortran-contiguo) son los tres tipos de diseño de matriz. Pero ese no es el problema en tu ejemplo.

Problema 1

En esta linea

arrAdd1([2,3.0,1])

Está pasando una lista en lugar de una matriz.

La siguiente versión simplificada funciona:

@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)

Y produce

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

Problema 2

En su ejemplo, arrAdd1() se define como un cierre, por lo que c se convierte en una constante en la función.

Si realmente desea utilizar tipos de parámetros explícitos, debe especificar que addArr() recibirá una matriz constante al menos en el segundo parámetro.

Siempre que las funciones no modifiquen sus entradas, puede declarar todos los parámetros de entrada de solo lectura, como en este ejemplo, que produce el mismo resultado:

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)

Puede cambiar el diseño (A, C, F) al que más le convenga.

1
aerobiomat 26 feb. 2021 a las 15:22