使用 NumPy 优化非数字矩阵的创建
Optimizing the creation of a non-numeric matrix with NumPy
当我试图找到一种方法来优化巨大的二维矩阵的创建和打印时,我决定试用 NumPy。但是,对我来说不幸的是,相反地使用这个库会使情况变得更糟。
我的目标是创建一个矩阵,该矩阵将用其索引填充字符串。像这样(其中 n
是矩阵的大小):
python_matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]
当我这样使用 NumPy 库的 array()
函数时:
numpy_matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])
创建矩阵的时间只会增加。例如,对于 n = 1000
:python_matrix
的创建时间为 0.032 秒,而 numpy_matrix
的创建时间为 0.419,即比 python 长 13 倍
此外,numpy_matrix
打印速度比 python_matrix
使用 for
循环
打印速度慢(如果您输出完整版本,而不是缩短版本)
n = 1000
def numpy_matrix(n):
matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])
with numpy.printoptions(threshold=numpy.inf):
print(coordArr)
def python_matrix(n):
matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]
def print_matrix():
for arr in matrix:
print(arr)
print_matrix()
# time of numpy_matrix > time of python_matrix
- 是使用标准 Python 功能更好,还是 NumPy 实际上更高效,只是我没有正确使用它?
- 此外,如果我确实使用 NumPy,如何加速完整版矩阵的输出的问题仍然存在
运行 ipython
会话并使用其 timeit
,我没有发现如此大的差异:
制作清单:
In [13]: timeit [[f"{y}, {x}" for y in range(N)] for x in range(N)]
492 ms ± 3.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
制作数组(同时制作列表):
In [14]: timeit np.array([[f"{y}, {x}" for y in range(N)] for x in range(N)])
779 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
从以下时间删除列表创建步骤:
In [15]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist)
...:
...:
313 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
因此,从现有列表创建数组的时间不会太长。
指定数据类型也有一点帮助:
In [18]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist, dtype='U8')
...:
...:
224 ms ± 2.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
虽然我们可以只对字符串格式化计时,但计时打印比较尴尬,str(x)
。我不会显示时间,但是是的,数组格式化要慢得多。本质上 numpy
必须通过 Python 自己的字符串处理代码;它几乎没有自己的东西。
数字list/array
对于数值数组,相对差异较大:
In [29]: alist = [[(x,y) for y in range(N)] for x in range(N)]
In [30]: arr = np.array(alist)
In [31]: arr.shape
Out[31]: (1000, 1000, 2)
In [32]: timeit alist = [[(x,y) for y in range(N)] for x in range(N)]
171 ms ± 8.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [33]: timeit arr = np.array(alist)
832 ms ± 36.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
但是,如果使用数组方法创建相同的数组 - 即不通过列表的列表,时间会好得多:
In [40]: timeit np.stack(np.broadcast_arrays(np.arange(N)[:,None], np.arange(N)),axis=2)
8.51 ms ± 89.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
numpy
并不是在所有方面都优于列表。最适合现有数组的数学运算。从列表创建数组非常耗时。而且它并没有增加很多字符串处理。
当我试图找到一种方法来优化巨大的二维矩阵的创建和打印时,我决定试用 NumPy。但是,对我来说不幸的是,相反地使用这个库会使情况变得更糟。
我的目标是创建一个矩阵,该矩阵将用其索引填充字符串。像这样(其中 n
是矩阵的大小):
python_matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]
当我这样使用 NumPy 库的 array()
函数时:
numpy_matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])
创建矩阵的时间只会增加。例如,对于 n = 1000
:python_matrix
的创建时间为 0.032 秒,而 numpy_matrix
的创建时间为 0.419,即比 python 长 13 倍
此外,numpy_matrix
打印速度比 python_matrix
使用 for
循环
n = 1000
def numpy_matrix(n):
matrix = numpy.array([[f"{y}, {x}" for x in range(n)] for y in range(n)])
with numpy.printoptions(threshold=numpy.inf):
print(coordArr)
def python_matrix(n):
matrix = [[f"{y}, {x}" for x in range(n)] for y in range(n)]
def print_matrix():
for arr in matrix:
print(arr)
print_matrix()
# time of numpy_matrix > time of python_matrix
- 是使用标准 Python 功能更好,还是 NumPy 实际上更高效,只是我没有正确使用它?
- 此外,如果我确实使用 NumPy,如何加速完整版矩阵的输出的问题仍然存在
运行 ipython
会话并使用其 timeit
,我没有发现如此大的差异:
制作清单:
In [13]: timeit [[f"{y}, {x}" for y in range(N)] for x in range(N)]
492 ms ± 3.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
制作数组(同时制作列表):
In [14]: timeit np.array([[f"{y}, {x}" for y in range(N)] for x in range(N)])
779 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
从以下时间删除列表创建步骤:
In [15]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist)
...:
...:
313 ms ± 12.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
因此,从现有列表创建数组的时间不会太长。
指定数据类型也有一点帮助:
In [18]: %%timeit alist = [[f"{y}, {x}" for y in range(N)] for x in range(N)]
...: np.array(alist, dtype='U8')
...:
...:
224 ms ± 2.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
虽然我们可以只对字符串格式化计时,但计时打印比较尴尬,str(x)
。我不会显示时间,但是是的,数组格式化要慢得多。本质上 numpy
必须通过 Python 自己的字符串处理代码;它几乎没有自己的东西。
数字list/array
对于数值数组,相对差异较大:
In [29]: alist = [[(x,y) for y in range(N)] for x in range(N)]
In [30]: arr = np.array(alist)
In [31]: arr.shape
Out[31]: (1000, 1000, 2)
In [32]: timeit alist = [[(x,y) for y in range(N)] for x in range(N)]
171 ms ± 8.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [33]: timeit arr = np.array(alist)
832 ms ± 36.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
但是,如果使用数组方法创建相同的数组 - 即不通过列表的列表,时间会好得多:
In [40]: timeit np.stack(np.broadcast_arrays(np.arange(N)[:,None], np.arange(N)),axis=2)
8.51 ms ± 89.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
numpy
并不是在所有方面都优于列表。最适合现有数组的数学运算。从列表创建数组非常耗时。而且它并没有增加很多字符串处理。