Хотя Исаакиевская ответ представляется перспективным, так как она удаляет те две вложенные для петель, вы вынуждены создать промежуточный массив M
, который n
раз превышает размер исходного V
массива. Python для петель не дешев, но доступ к памяти не является бесплатным либо:
n = 10
p = 20000
V = np.random.rand(n, p)
F = np.random.rand(n, n)
def op_code(V, F):
n, p = V.shape
A = np.zeros(p)
for i in xrange(n):
for j in xrange(i+1):
A += F[i,j] * V[i,:] * V[j,:]
return A
def isaac_code(V, F):
n, p = V.shape
F = F.copy()
F[np.triu_indices(n, 1)] = 0
M = (V.reshape(n, 1, p) * V.reshape(1, n, p)) * F.reshape(n, n, 1)
return M.sum((0, 1))
Если теперь принять как для испытательной поездки:
In [20]: np.allclose(isaac_code(V, F), op_code(V, F))
Out[20]: True
In [21]: %timeit op_code(V, F)
100 loops, best of 3: 3.18 ms per loop
In [22]: %timeit isaac_code(V, F)
10 loops, best of 3: 24.3 ms per loop
Так Извлечение для петель обходятся вам ое замедление. Не очень хорошая вещь ... На данный момент вы можете даже подумать, нужна ли функция, занимающая около 3 мс для оценки, дальнейшая оптимизация. В случае, если вы делаете, есть небольшое улучшение, которое можно было с помощью np.einsum
:
def einsum_code(V, F):
n, p = V.shape
F = F.copy()
F[np.triu_indices(n, 1)] = 0
return np.einsum('ij,ik,jk->k', F, V, V)
А теперь:
In [23]: np.allclose(einsum_code(V, F), op_code(V, F))
Out[23]: True
In [24]: %timeit einsum_code(V, F)
100 loops, best of 3: 2.53 ms per loop
Так что примерно на 20% ускорить, который вводит код, который может очень хорошо не быть таким же читаемым, как ваши петли. Я бы сказал, не стоит ...
Какая форма 'F'? Это '(n, n)' или '(n, n, p)'? – wflynny
Считаете ли вы, что вы пишете эти петли в C (поскольку они просты), и используя scipy.weave.blitz? – usethedeathstar
Bill, F is (n, n) – user1984528