Как ускорить "на l oop" в Python3 - PullRequest
2 голосов
/ 17 февраля 2020

Ниже код работает так медленно. Я попытался использовать numpy.argwhere вместо «оператора if» для ускорения кода, и я получил довольно эффективный результат, но он все еще очень медленный. Я также пробовал numpy.frompyfunc и numpy.vectorize, но потерпел неудачу. Что бы вы посоветовали для ускорения кода ниже?

import numpy as np
import time

time1 = time.time()

n = 1000000
k = 10000

velos = np.linspace(-1000, 1000, n)
line_centers = np.linspace(-1000, 1000, k)
weights = np.random.random_sample(k)
rvs = np.arange(-60, 60, 2)

m = len(rvs)
w = np.arange(10)
M = np.zeros((n, m))
for l, lc in enumerate(line_centers):
    vi = velos - lc

    for j in range(m - 1):
        w = np.argwhere((vi < rvs[j + 1]) & (vi > rvs[j])).T[0]

        M[w, j] = weights[l] * (rvs[j + 1] - vi[w]) / (rvs[j + 1] - rvs[j])
        M[w, j + 1] = weights[l] * (vi[w] - rvs[j]) / (rvs[j + 1] - rvs[j])

time2 = time.time()

print(time2 - time1)

РЕДАКТИРОВАТЬ: Размер массива M был неправильным. Я починил это.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2020

Конечно, это медленно, у вас есть два вложенных цикла! Вам необходимо переосмыслить свой алгоритм, используя векторные операции, как, например, без итерации по индексам, но реализовать в терминах индексных или логических массивов и сдвигов индексов.

Вы не предоставили никакой фоновой информации, так что это невероятно Трудно кому-то предложить что-то осмысленное (с учетом супа показателей в примере). Несколько быстрых предложений, основанных на быстром подборе вашего примера.

  • Выражение, подобное этому (rvs[j + 1] - rvs[j]), легко заменить на numpy.ediff1d.
  • Вы, кажется, перебирать n в блоках m, может быть, numpy.nditer будет полезен.
  • У меня есть догадка, что ваш внутренний l oop имеет ошибку, Вы уверены, что действительно хотите перебрать range(m - 1)? Это означает, что вы выполняете итерацию с 0 до m-2 (включительно), я сомневаюсь, что вы это имели в виду.

Мы можем помочь с более конкретными ответами, если вы предоставите дополнительную справочную информацию.

0 голосов
/ 17 февраля 2020

Это похоже на ситуацию, когда интерфейс с ++ может пригодиться. С Pybind11 вы можете создавать функции c ++, которые принимают numpy массивы в качестве аргумента, манипулируют ими и возвращают их обратно в python. Это ускорит ваши петли. Взгляните на это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...