Я пытаюсь получить быстрый векторизованную версию следующего цикла:Vectorize добавление в массив индексируется другой массив
for i in xrange(N1):
A[y[i]] -= B[i,:]
Здесь A.shape = (N2,N3)
, y.shape = (N1)
с y
значениями в [0,N2[
, B.shape = (N1,N3)
. Вы можете представить, что записи y
являются индексами в строках A
. Здесь N1
большой, N2
довольно маленький и N3
- маленький.
Я думал, что просто делает
A[y] -= B
будет работать, но проблема в том, что там повторяются записи в y
и это не делает правильно (то есть, если y=[1,1]
то A[1]
добавляется только один раз, не дважды). Кроме того, это, похоже, не быстрее, чем цикл без использования.
Есть ли лучший способ сделать это?
EDIT: YXD связанный this answer в комментариях, которые поначалу, похоже, соответствуют счету. Казалось бы, вы можете делать то, что я хочу с
np.subtract.at(A, y, B)
и он работает, но когда я пытаюсь запустить его это значительно медленнее, чем unvectorized версии. Итак, остается вопрос: есть ли более эффективный способ сделать это?
EDIT2: пример, чтобы сделать вещи бетон:
n1,n2,n3 = 10000, 10, 500
A = np.random.rand(n2,n3)
y = np.random.randint(n2, size=n1)
B = np.random.rand(n1,n3)
для цикла, при запуске с помощью %timeit
в IPython дает на моей машине:
10 loops, best of 3: 19.4 ms per loop
версия subtract.at
производит такое же значение для A
в конце, но намного медленнее:
1 loops, best of 3: 444 ms per loop
возможно дубликат [numpy.array. \ _ \ _ Iadd \ _ \ _ и повторные индексы] (http://stackoverflow.com/questions/24099404/numpy-array-iadd-and-repeated-indices) и http://stackoverflow.com/q/15973827/553404 – YXD
@YXD, спасибо за предложение, выглядело довольно хорошо, но, похоже, на самом деле дела обстоят медленнее. Я отредактировал вопрос, чтобы решить эту проблему. – toth
Является ли 'A' инициализированным нулями, то есть' A = np.zeros ((N2, N3)) 'перед тем, как перейти в цикл? – Divakar