Кусковая кусковая функция медленная в скудном квадрате - PullRequest
0 голосов
/ 01 мая 2018

Я пытался измерить время, затрачиваемое на оценку математической функции, как тупым, так и простым питоническим способом. Сначала я измерил, сколько времени требуется, чтобы оценить функцию.

import numpy as np
import scipy as sp
import scipy.integrate as si



def func1(x):
    return np.piecewise(x, [x<=2, x>2],
                    [lambda x: 2*x + pow(2, x),
              lambda x: -(pow(x, 2) + 2)]
                       )
def func2(x):
    if (x<=2): return 2*x + pow(2,x)
    else: return -(pow(x, 2) + 2)

data = np.linspace(-10, 10, 1000)
%timeit data1 = func1(data)
data2 = []
%timeit for i in range(0, np.size(data)): data2.append(func2(data[i]))

На самом деле, приведенный выше результат был, как я и ожидал, тупой путь был намного быстрее, чем основной способ.

35.2 µs ± 110 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
771 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Однако в scipy.integrate.quad происходит странная вещь. Скорость интеграции была намного быстрее в основном питоническим способом. Почему дело?

%timeit si.quad(func1, -10, 10)
%timeit si.quad(func2, -10, 10)

5.59 ms ± 25.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
187 µs ± 39.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

1 Ответ

0 голосов
/ 01 мая 2018

np.piecewise быстро только при использовании векторизации. Когда входные данные являются скалярными, они намного медленнее, чем эквивалент Python, предположительно из-за накладных расходов:

from timeit import timeit
kwds = dict(globals=globals(), number=1000)

print(timeit("data1 = func1(data)", **kwds))
data2 = []
print(timeit("for i in range(0, np.size(data)): data2.append(func2(data[i]))", **kwds))
data3 = []
print(timeit("for i in range(0, np.size(data)): data3.append(func1(data[i]))", **kwds))

0.06953751016408205
0.957529284991324
15.591511018108577

Теперь, тот факт, что он работает с func2, документами и тем, как работают популярные схемы адаптивной интеграции, позволяет предположить, что quad вызывает его подынтегральное выражение со скалярными аргументами один за другим, что объясняет ваше наблюдение.

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