您可以使用np.tensordot
这样一个量化的解决方案代替循环,如下 -
# Get the starting indices for each iteration
idx = (np.arange(M)*B)[:,None] + np.arange(N)
# Get the range of indices across all iterations as a 2D array and index
# time_series with it to give us "time_series[k*B : (N) + k*B]" equivalent
time_idx = time_series[idx]
# Use broadcasting to perform summation accumulation
C = np.tensordot(time_idx,time_idx,axes=([0],[0]))
的tensordot
可以由被替换 -
C = np.zeros((N,N))
for k in range(int(M)):
C += np.outer(time_series[k*B : (N) + k*B], time_series[k*B : (N) + k*B])
可以被替代简单的点积:
C = time_idx.T.dot(time_idx)
个
运行测试
功能:
def original_app(time_series,B,N,M):
C = np.zeros((N,N))
for k in range(int(M)):
C += np.outer(time_series[k*B : (N) + k*B], time_series[k*B : (N) + k*B])
return C
def vectorized_app(time_series,B,N,M):
idx = (np.arange(M)*B)[:,None] + np.arange(N)
time_idx = time_series[idx]
return np.tensordot(time_idx,time_idx,axes=([0],[0]))
输入:
In [115]: # Inputs
...: mu = 1.2
...: sigma = 0.5
...: N = 1000
...: M = 100
...: B = 10
...: time_series = np.random.normal(mu,sigma, (N + B*(M-1)) )
...:
时序:
In [116]: out1 = original_app(time_series,B,N,M)
In [117]: out2 = vectorized_app(time_series,B,N,M)
In [118]: np.allclose(out1,out2)
Out[118]: True
In [119]: %timeit original_app(time_series,B,N,M)
1 loops, best of 3: 1.56 s per loop
In [120]: %timeit vectorized_app(time_series,B,N,M)
10 loops, best of 3: 26.2 ms per loop
因此,我们看到一个60x
加速问题中列出的输入!
这真的让我的一天,非常感谢。修改后的代码现在正在运行,加速很明显。 – Luluca