Ich bin vor kurzem über numba gestolpert und dachte darüber nach, einige hausgemachte C-Erweiterungen mit eleganteren Autojitted Python-Code zu ersetzen. Leider war ich nicht glücklich, als ich einen ersten, schnellen Benchmark ausprobierte. Es scheint, wie numba ist nicht viel besser als normaler Python hier tun, obwohl ich fast C-ähnliche Leistung erwartet hätte:Optimieren des Zugriffs auf numpy Arrays für numba
from numba import jit, autojit, uint, double
import numpy as np
import imp
import logging
logging.getLogger('numba.codegen.debug').setLevel(logging.INFO)
def sum_accum(accmap, a):
res = np.zeros(np.max(accmap) + 1, dtype=a.dtype)
for i in xrange(len(accmap)):
res[accmap[i]] += a[i]
return res
autonumba_sum_accum = autojit(sum_accum)
numba_sum_accum = jit(double[:](int_[:], double[:]),
locals=dict(i=uint))(sum_accum)
accmap = np.repeat(np.arange(1000), 2)
np.random.shuffle(accmap)
accmap = np.repeat(accmap, 10)
a = np.random.randn(accmap.size)
ref = sum_accum(accmap, a)
assert np.all(ref == numba_sum_accum(accmap, a))
assert np.all(ref == autonumba_sum_accum(accmap, a))
%timeit sum_accum(accmap, a)
%timeit autonumba_sum_accum(accmap, a)
%timeit numba_sum_accum(accmap, a)
accumarray = imp.load_source('accumarray', '/path/to/accumarray.py')
assert np.all(ref == accumarray.accum(accmap, a))
%timeit accumarray.accum(accmap, a)
Das auf meinem Rechner gibt:
10 loops, best of 3: 52 ms per loop
10 loops, best of 3: 42.2 ms per loop
10 loops, best of 3: 43.5 ms per loop
1000 loops, best of 3: 321 us per loop
Ich bin mit dem letzte numba-Version von pypi, 0.11.0. Irgendwelche Vorschläge, wie man den Code repariert, damit er mit Numba ziemlich schnell läuft?
numba ist am effektivsten für reinen Python Code und numpy Arrays. Alle speziellen Funktionen können nicht optimal beschleunigt werden. Wenn Sie Ihre eigene Max-Funktion in reinem Python geschrieben haben und diese automatisch gesetzt haben, wäre sie wahrscheinlich schneller. – M4rtini
Ich habe mir den Code von numba angeschaut. Für viele numpige Funktionen bestimmt sie den Ausgabedatentyp korrekt, indem sie auf die Eingabe schaut und weiß, wie sich die Funktion verhält. Es heißt Typinferenz. Dies funktioniert z.B. mit 'np.sum' und' np.prod', aber min und max sind nicht im Code aufgeführt. Ich habe dafür einen Fehlerbericht eingereicht. – Michael