2012-08-03 12 views
10

Ich versuche zu verwenden und zu beschleunigen Phantasie Indexierung zu "Join" zwei Arrays und Summe über eine der Achsen der Ergebnisse.Fast (er) numpy fancy Indexing und Reduktion?

Etwas wie folgt aus:

$ ipython 
In [1]: import numpy as np 
In [2]: ne, ds = 12, 6 
In [3]: i = np.random.randn(ne, ds).astype('float32') 
In [4]: t = np.random.randint(0, ds, size=(1e5, ne)).astype('uint8') 

In [5]: %timeit i[np.arange(ne), t].sum(-1) 
10 loops, best of 3: 44 ms per loop 

Gibt es eine einfache Möglichkeit, die Aussage in In [5] zu beschleunigen? Sollte ich mit OpenMP gehen und so etwas wie scipy.weave oder Cythonprange?

+0

Eine weitere verwandte Frage ist, wie würde ich 'Pandas' verwenden, um das Gleiche zu tun? – npinto

+0

Numpy macht das bei C-Geschwindigkeit, also wirst du es wahrscheinlich nicht viel schneller mit Weben beschleunigen können. – reptilicus

Antwort

8

numpy.take ist aus irgendeinem Grund viel schneller als Phantasieindexierung. Der einzige Trick ist, dass das Array als flach behandelt wird.

In [1]: a = np.random.randn(12,6).astype(np.float32) 

In [2]: c = np.random.randint(0,6,size=(1e5,12)).astype(np.uint8) 

In [3]: r = np.arange(12) 

In [4]: %timeit a[r,c].sum(-1) 
10 loops, best of 3: 46.7 ms per loop 

In [5]: rr, cc = np.broadcast_arrays(r,c) 

In [6]: flat_index = rr*a.shape[1] + cc 

In [7]: %timeit a.take(flat_index).sum(-1) 
100 loops, best of 3: 5.5 ms per loop 

In [8]: (a.take(flat_index).sum(-1) == a[r,c].sum(-1)).all() 
Out[8]: True 

Ich denke, die einzige andere Weg Sie viel von einer Verbesserung der Geschwindigkeit sehen werden darüber hinaus mit so etwas wie PyCUDA einen angepassten Kernel für eine GPU zu schreiben wäre.

+1

Das Array wird standardmäßig nur als flach behandelt. Sie können weiterhin das Schlüsselwort 'axis' verwenden. Dh, np.take (np.arange (10) .reshape ((- 1,2)), [0], axis = 0) 'wählt die erste Zeile aus. – jorgeca

+0

@jorgeca: richtig, aber ich denke nicht, dass Sie einzelne Elemente durch Angabe von sowohl Zeile als auch Spalte ziehen können, wie Sie mit ausgefallenen Indizierung können, wenn Sie das flache Array indizieren. – user545424