Я ищу в том, чтобы вычислить как можно более эффективные в Python3 продукте точки внутри двойной суммы формы:Эффективный способ вычисления скалярного произведения в двойной сумме в Python3
import cmath
for j in range(0,N):
for k in range(0,N):
sum_p += cmath.exp(-1j * sum(a*b for a,b in zip(x, [l - m for l, m in zip(r_p[j], r_p[k])])))
где r_np является массив из нескольких тысяч троек, а xa - постоянный тройной. Сроки для длины N=1000
троек составляет около 2.4s
. То же самое с помощью NumPy:
import numpy as np
for j in range(0,N):
for k in range(0,N):
sum_np = np.add(sum_np, np.exp(-1j * np.inner(x_np,(r_np[j] - r_np[k]))))
на самом деле медленнее с выполнения около 4.0s
. Я предполагаю, что это связано с отсутствием большого преимущества векторизации, только короткая 3 точка 3 является np.dot, которая съедается путем запуска N^2 из циклов. Однако скромное убыстрение по первому примеру, я мог бы получить с помощью простого python3 с картой и мулом:
from operator import mul
for j in range(0,N):
for k in range(0,N):
sum_p += cmath.exp(-1j * sum(map(mul,x, [l - m for l, m in zip(r_p[j], r_p[k])])))
с выполнением около 2.0s
Попытки использовать либо если условие не рассчитал случай j=k
, где
r_np[j] - r_np[k] = 0
и, таким образом, скалярное произведение также становится равным 0, или разделив сумму в два, чтобы достигнуть того же самого
for j in range(0,N):
for k in range(j+1,N):
...
for k in range(0,N):
for j in range(k+1,N):
...
оба сделали это еще медленнее. Итак, все это масштабируется с помощью O (N^2), и мне интересно, можно ли с помощью некоторых методов сортировки или других вещей избавиться от циклов и сделать их масштабируемыми с помощью O (N logN). Проблема в том, что мне нужно однократное второе время автономной работы для набора из N~6000
троек, поскольку у меня есть тысячи этих сумм для вычисления. В противном случае мне нужно попробовать плетение scipy, numba, pyrex или python или полностью спуститься по пути C ...
Заранее благодарим за любую помощь!
Edit:
это как образец данных будет выглядеть следующим образом:
# numpy arrays
x_np = np.array([0,0,1], dtype=np.float64)
N=1000
xy = np.multiply(np.subtract(np.random.rand(N,2),0.5),8)
z = np.linspace(0,40,N).reshape(N,1)
r_np = np.hstack((xy,z))
# in python format
x = (0,0,1)
r_p = r_np.tolist()
Не могли бы вы отказаться от тестовых данных в кодовом блоке, чтобы мы могли использовать его для тестирования? – IVlad
Будет ли 'x' всегда равняться' (0, 0, 1) '? –
за данную сумму, да. Но вот почему я должен вычислить многие из этих сумм для разных 'x' – joanwa