[Python] Numpy.array e tempi di accesso

Pietro Battiston ml a pietrobattiston.it
Mar 3 Nov 2015 17:19:21 CET


Salve a tutti di nuovo,

se definisco un semplice Fibonacci con una cache (volutamente un po'
stupida):

def _fib(n, cache):
    cached = cache[n]
    if cached != -1:
        return cached
    res = _fib(n-1, cache) + _fib(n-2, cache)
    cache[n] = res
    return res

def dfib(n):
    cache = {i:-1 for i in range(n+1)}
    cache[0] = cache[1] = 1
    return _fib(n, cache)

... %timeit dfib(91) mi dà "29.6 µs per loop". Se la cache invece che
un dict è un numpy.array, come in 

def afib(n):
    cache = -ones(shape=n+1, dtype=int64)
    cache[0] = cache[1] = 1
    return _fib(n, cache)

... %timeit afib(91) mi dà invece "53.2 µs per loop". E va bene che il
dizionario Python è una struttura efficiente, ma... è sempre una hash
table più un indexing, come fa a battere un semplice indexing?! Riesco
ad abbassare a "46.7 µs per loop" se sostituisco

    if cached != -1:

con

    if cached != EMPTY:

dove ho precedentemente definito

EMPTY = np.int64(-1)

... ma resta il fatto (verificato con %lprun) che "cached = cache[n]" è più veloce quando cache è un dizionario (~0.3 µs) che quando è un array (~0.4 µs).

Ciò umilia quel briciolo di comprensione delle strutture di dati che credevo di avere. Qualcuno sa illuminarmi?

(per la cronaca: la cosa l'ho notata in un algoritmo in cui la cache era molto più grande, e con indici non interi ma tuple di interi)

Pietro


Maggiori informazioni sulla lista Python