Вы можете векторизовать это следующим образом:
temp = np.subtract(a, xyz) # so we only have to compute this once
dist = np.linalg.norm(np.subtract(temp, np.multiply(np.dot(temp, n)[:, None], n)),
axis=-1)
# 220 ms ± 6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
По сравнению с синхронизацией для вашего первого примера кода выше:
# 30 s ± 1.89 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
Это дает мне тот же результат, что и ваш первый пример кода(проверено с помощью np.array_equal()
), и это на пару порядков быстрее.
Пояснение
Хитрость заключается в том, чтобы заставить вызов np.multiply()
работать правильно, добавивдополнительная ось к результату np.dot()
, который я делаю со срезом [:, None]
после np.dot()
.В основном None
, используемый в кусочках срезки, является ярлыком для добавления оси, поэтому результат np.dot()
для вас должен иметь форму (2521909,)
, а после скобок с None
он будет иметь форму (2521909, 1)
.Результат np.multiply()
(и temp
) будет иметь форму (2521909, 3)
, и мы возьмем норму вдоль последней оси, чтобы получить трехмерное расстояние от линии до каждой из ваших 2521909 точек.