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 
  • Matrixinversion ohne Numpy
  • Eine Funktion auf einem zweidimensionalen numpy Array zu senden
  • Numpy get index wo der Wert wahr ist
  • Digitieren eines analogen Signals
  • Wie kann ich eine Liste von Tupeln faktorisieren?
  • Wie berechne ich eine Fourier-Serie in Numpy?
  • Berechnen Sie Pixel für Pixel-Mittel der Raster mit numpy
  • Sortierung eines Python-Arrays / Recarray nach Spalte
  • Python ist die beste Programmiersprache der Welt.