Ответ 1
numpy.take
по какой-то причине намного быстрее, чем причудливая индексация. Единственный трюк в том, что он рассматривает массив как плоский.
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
Я думаю, что только другой способ, которым вы будете видеть большую часть улучшения скорости, помимо этого, - это написать собственное ядро для графического процессора, используя что-то вроде PyCUDA.