Вы можете сделать эту операцию немного быстрее. Как вы уже предполагали, основной проблемой здесь является (ненужный) оператор питания.
В дополнение к этому у Numpy нет специальной реализации для power (float64, int64), где показатель степени представляет собой небольшое положительное целое число. Вместо этого Numpy всегда вычисляет мощность (float64, float64), что является гораздо более сложной задачей.
В Numba и Numexpr есть специальная реализация для простого случая (float64, int64), поэтому давайте попробуем это на первом шаге.
Первый подход
import numpy as np
import numba as nb
horizon = 91
phi = 0.2
trend = -0.004
@nb.njit()
def pow_cumsum(horizon,phi,trend):
out=np.empty(horizon)
csum=0.
for i in range(horizon):
csum+=phi**i+1
out[i]=csum*trend
return out
Как уже говорилось, перед непосредственным вычислением мощности нет необходимости, алгоритм может быть переписан, чтобы избежать этого полностью.
Второй подход
@nb.njit()
def pow_cumsum_2(horizon,phi,trend):
out=np.empty(horizon)
out[0]=2.*trend
TMP=2.
val=phi
for i in range(horizon-1):
TMP=(val+1+TMP)
out[i+1]=TMP*trend
val*=phi
return out
Задержка
%timeit np.cumsum(phi ** np.arange(horizon) + 1) * trend
7.44 µs ± 89.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit pow_cumsum(horizon,phi,trend)
882 ns ± 4.91 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit pow_cumsum_2(horizon,phi,trend)
559 ns ± 3.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)