[英]Make a FOR LOOP with numpy arrays multiplication and "appending" faster
这是我当前的代码。
当第二个“for 循环”中的元素数量很少(大约 10k)并且只需要几秒钟时它工作正常,但是当第二个“for 循环”中的元素数量很高(大约 40k)时大约需要 60 秒或更长时间:为什么?
例如:有时当第二个 for 循环有 28k 个元素时,执行它所花费的时间比它有 7k 个元素时要少。 我不明白为什么时间与操作次数不是线性相关的。
此外,作为一般规则,代码运行的时间越长,循环时间就越长。
回顾一下,执行时间通常遵循以下规则:
.
from random import random
import numpy as np
import time
import gc
from collections import deque
import random
center_freq = 20000000
smpl_time = 0.03749995312*pow(10,-6)
mat_contents = []
for i in range(10):
mat_contents.append(np.ones((3600, random.randint(3000,30000))))
tempo = np.empty([0,0])
for i in range(3600):
tempo = np.append(tempo, center_freq*smpl_time*i)
ILO = np.cos(tempo)
check = 0
for element in mat_contents:
start_time = time.time()
Icolumn = np.empty([0,0])
Imatrix = deque([])
gc.disable()
for colonna in element.T:
Imatrix.append(np.multiply(ILO, colonna))
gc.enable()
varI = np.var(Imatrix)
tempImean = np.mean(Imatrix)
print('\nSize: ', len(element.T))
print("--- %s seconds ---" % (time.time() - start_time))
print("--- ", check, ' ---')
check += 1
你的代码杀死了我的 session,大概是因为数组维度对于 memory 来说太大了。再次尝试使用较小的数字:
In [1]: from collections import deque
...: import random
...:
...: center_freq = 20000000
...: smpl_time = 0.03749995312*pow(10,-6)
...:
...: mat_contents = []
...:
...: for i in range(10):
...: mat_contents.append(np.ones((36, random.randint(30,300))))
...:
...: tempo = np.empty([0,0])
...:
...: for i in range(3600):
...: tempo = np.append(tempo, center_freq*smpl_time*i)
...:
...: ILO = np.cos(tempo)
...:
...: check = 0
In [2]:
In [2]: tempo.shape
Out[2]: (3600,)
In [3]: ILO
Out[3]:
array([ 1. , 0.73168951, 0.07073907, ..., -0.63602366,
-0.99137119, -0.81472814])
In [4]: len(mat_contents)
Out[4]: 10
快速说明 - 虽然mat_contents
循环中的列表 append 相对较快,但下一个循环中的np.append
糟糕。 不要那样使用它。
我不知道我现在是否有时间看下一个循环,但是,你为什么在那里使用deque
? 为什么不是列表? 我没有太多地使用deque
,但我认为它与右侧append
的列表相比没有任何优势。
修正ILO
以减少形状
In [16]: tempo = np.empty([0,0])
...: ...:
...: ...: for i in range(36):
...: ...: tempo = np.append(tempo, center_freq*smpl_time*i)
...:
In [17]: tempo.shape
Out[17]: (36,)
In [18]: ILO = np.cos(tempo)
我怀疑循环可以用一个numpy
表达式代替,但我不会深入研究它。
In [19]: %%timeit
...: for element in mat_contents:
...: Icolumn = np.empty([0,0])
...: Imatrix = deque([])
...: for colonna in element.T:
...: Imatrix.append(np.multiply(ILO, colonna))
...: varI = np.var(Imatrix)
...: tempImean = np.mean(Imatrix)
...:
5.82 ms ± 6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Imatrix = []
的时间是一样的,所以使用deque
没有坏处。
mat_contents
包含 arrays 具有不同的形状(第二维):
In [22]: [x.shape for x in mat_contents]
Out[22]:
[(36, 203),
(36, 82),
(36, 194),
(36, 174),
(36, 119),
(36, 190),
(36, 272),
(36, 68),
(36, 293),
(36, 248)]
现在让我们检查一下您担心的慢循环:
In [23]: ILO.shape
Out[23]: (36,)
In [24]: element=mat_contents[0]
In [25]: element.T.shape
Out[25]: (203, 36)
In [26]: Imatrix =[]
...: for colonna in element.T:
...: Imatrix.append(np.multiply(ILO, colonna))
...: arr = np.array(Imatrix)
In [27]: arr.shape
Out[27]: (203, 36)
要将 (36,) 数组和 (203,36) 相乘,我们不需要循环。
In [28]: np.allclose(ILO*element.T, arr)
Out[28]: True
In [29]: %%timeit
...: Imatrix =[]
...: for colonna in element.T:
...: Imatrix.append(np.multiply(ILO, colonna))
...: arr = np.array(Imatrix)
...:
...:
405 µs ± 2.72 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
整个数组操作要快得多:
In [30]: timeit ILO*element.T
19.4 µs ± 14.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
在您最初的问题中,您加载了一个.mat
文件。 您是否正在尝试翻译 MATLAB 代码? numpy
就像旧时代的 MATLAB,其中全矩阵运算要快得多。 numpy
不做循环的jit
编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.