Numba 3x langsamer als numpy

Wir haben eine vektorielle napy get_pos_neg_bitwise Funktion, die eine Maske = [132 20 192] und eine df.shape von (500e3, 4) verwenden, die wir mit numba beschleunigen wollen.

from numba import jit import numpy as np from time import time def get_pos_neg_bitwise(df, mask): """ In [1]: print mask [132 20 192] In [1]: print df [[ 1 162 97 41] [ 0 136 135 171] ..., [ 0 245 30 73]] """ check = (np.bitwise_and(mask, df[:, 1:]) == mask).all(axis=1) pos = (df[:, 0] == 1) & check neg = (df[:, 0] == 0) & check pos = np.nonzero(pos)[0] neg = np.nonzero(neg)[0] return (pos, neg) 

Mit Tipps von @morningsun haben wir diese numba Version gemacht:

 @jit(nopython=True) def numba_get_pos_neg_bitwise(df, mask): posneg = np.zeros((df.shape[0], 2)) for idx in range(df.shape[0]): vandmask = np.bitwise_and(df[idx, 1:], mask) # numba fail with # if np.all(vandmask == mask): vandm_equal_m = 1 for i, val in enumerate(vandmask): if val != mask[i]: vandm_equal_m = 0 break if vandm_equal_m == 1: if df[idx, 0] == 1: posneg[idx, 0] = 1 else: posneg[idx, 1] = 1 pos = list(np.nonzero(posneg[:, 0])[0]) neg = list(np.nonzero(posneg[:, 1])[0]) return (pos, neg) 

Aber es ist noch 3 mal langsamer als die numpy (~ 0.06s Vs ~ 0,02s).

 if __name__ == '__main__': df = np.array(np.random.randint(256, size=(int(500e3), 4))) df[:, 0] = np.random.randint(2, size=(1, df.shape[0])) # set target to 0 or 1 mask = np.array([132, 20, 192]) start = time() pos, neg = get_pos_neg_bitwise(df, mask) msg = '==> pos, neg made; p={}, n={} in [{:.4} s] numpy' print msg.format(len(pos), len(neg), time() - start) start = time() msg = '==> pos, neg made; p={}, n={} in [{:.4} s] numba' pos, neg = numba_get_pos_neg_bitwise(df, mask) print msg.format(len(pos), len(neg), time() - start) start = time() pos, neg = numba_get_pos_neg_bitwise(df, mask) print msg.format(len(pos), len(neg), time() - start) 

Bin ich etwas fehlt?

 In [1]: %run numba_test2.py ==> pos, neg made; p=3852, n=3957 in [0.02306 s] numpy ==> pos, neg made; p=3852, n=3957 in [0.3492 s] numba ==> pos, neg made; p=3852, n=3957 in [0.06425 s] numba In [1]: 

One Solution collect form web for “Numba 3x langsamer als numpy”

Versuchen Sie, den Anruf zu np.bitwise_and außerhalb der Schleife zu bewegen, da numba nichts tun kann, um es zu beschleunigen:

 @jit(nopython=True) def numba_get_pos_neg_bitwise(df, mask): posneg = np.zeros((df.shape[0], 2)) vandmask = np.bitwise_and(df[:, 1:], mask) for idx in range(df.shape[0]): # numba fail with # if np.all(vandmask == mask): vandm_equal_m = 1 for i, val in enumerate(vandmask[idx]): if val != mask[i]: vandm_equal_m = 0 break if vandm_equal_m == 1: if df[idx, 0] == 1: posneg[idx, 0] = 1 else: posneg[idx, 1] = 1 pos = np.nonzero(posneg[:, 0])[0] neg = np.nonzero(posneg[:, 1])[0] return (pos, neg) 

Dann bekomme ich Timings von:

 ==> pos, neg made; p=3920, n=4023 in [0.02352 s] numpy ==> pos, neg made; p=3920, n=4023 in [0.2896 s] numba ==> pos, neg made; p=3920, n=4023 in [0.01539 s] numba 

Also jetzt ist Numba ein bisschen schneller als numpy.

Auch hat es keinen großen Unterschied gemacht, aber in deiner ursprünglichen Funktion kehrst du numpy Arrays zurück, während du in der Numba-Version pos und neg in Listen umgewandelt hast.

Im Allgemeinen aber würde ich vermuten, dass die Funktionsaufrufe von numpy Funktionen dominiert werden, die numba nicht beschleunigen kann, und die numpy Version des Codes verwendet bereits schnelle Vektorisierungsroutinen.

Aktualisieren:

Sie können es schneller machen, indem Sie den enumerate entfernen und direkt in das Array eintragen, anstatt ein Slice zu packen. Auch das Aufteilen von pos und neg in separate Arrays hilft, das Aufschneiden einer nicht zusammenhängenden Achse im Gedächtnis zu vermeiden:

 @jit(nopython=True) def numba_get_pos_neg_bitwise(df, mask): pos = np.zeros(df.shape[0]) neg = np.zeros(df.shape[0]) vandmask = np.bitwise_and(df[:, 1:], mask) for idx in range(df.shape[0]): # numba fail with # if np.all(vandmask == mask): vandm_equal_m = 1 for i in xrange(vandmask.shape[1]): if vandmask[idx,i] != mask[i]: vandm_equal_m = 0 break if vandm_equal_m == 1: if df[idx, 0] == 1: pos[idx] = 1 else: neg[idx] = 1 pos = np.nonzero(pos)[0] neg = np.nonzero(neg)[0] return pos, neg 

Und Timings in einem ipython Notebook:

  %timeit pos1, neg1 = get_pos_neg_bitwise(df, mask) %timeit pos2, neg2 = numba_get_pos_neg_bitwise(df, mask)​ 100 loops, best of 3: 18.2 ms per loop 100 loops, best of 3: 7.89 ms per loop 
  • Werte ändern auf matplotlib imshow () grafische Achse
  • Anwenden der Funktion auf Sätze von Spalten in Pandas, 'Looping' über den gesamten Datenrahmen spaltenweise
  • Histogramm Matplotlib
  • Python: Liste der Matrizen zu numpy Array?
  • Calling Python von PHP scheitert, wenn Import numpy
  • (4,1,2) Numpy Array im Uhrzeigersinn
  • Making wissenschaftliche Notation lesbar aus einer numpy Array
  • Wie vergabe ich Eingangs-Arrays mit f2py?
  • ImportError: Kein Modul namens numpy
  • Dot Produkt mit Diagonalmatrix, ohne es zu schaffen
  • Wie konvertiert man eine Spalten- oder Zeilenmatrix zu einer Diagonalmatrix in Python?
  • Python ist die beste Programmiersprache der Welt.