我使用数组模块来存储大量数字(许多千兆字节)的无符号32位整数。 python使用8个字节,而不是为每个元素使用4个字节,如array.itemsize所示,并由pympler验证。
例如:
>>> array("L", range(10)).itemsize
8
我有很多元素,所以我可以将它们存储在4个字节内。
Numpy会让我将这些值存储为无符号32位整数:
>>> np.array(range(10), dtype = np.uint32).itemsize
4
但问题是任何使用numpy的索引运算符的操作速度都是慢两倍,因此numpy支持的矢量运算操作速度很慢。 例如:
python3 -m timeit -s "from array import array; a = array('L', range(1000))" "for i in range(len(a)): a[i]"
10000 loops, best of 3: 51.4 usec per loop
VS
python3 -m timeit -s "import numpy as np; a = np.array(range(1000), dtype = np.uint32)" "for i in range(len(a)): a[i]"
10000 loops, best of 3: 90.4 usec per loop
所以我被迫使用两倍于我想要的内存,或者程序的运行速度是我想要的两倍。有没有解决的办法?我可以强制python数组使用指定的itemsize吗?
答案 0 :(得分:5)
如果您想坚持使用array
,set the typecode至I
(unsigned int
)而不是L
(unsigned long
):< / p>
>>> array.array("I", range(10)).itemsize
4
那就是说,如果没有办法加速你的计算方式超过你使用numpy输掉的2倍,我会非常惊讶。如果不确切知道你对这些价值观做了什么,很难说清楚。
答案 1 :(得分:1)
2件事:使用numpy.arange()(内部方法)
并避免使用Numpy的语句(出于计算机速度的原因)。尝试尽可能使用广播技术。
获取所有项目的一种更简单的方法是使用.ravel(),如果numpy数组的形状妨碍了。
python3 -m timeit -s "import numpy as np; a = np.arange(1000),
....... dtype = np.uint32)" "for i in range(len(a)): a[i]"
10000次循环,最佳3:106每循环usec
python3 -m timeit -s "import numpy as np; a = np.arange(1000),
....... dtype = np.uint32)" "a.ravel()"
1000000个循环,最好是3:每循环0.218次使用
答案 2 :(得分:1)
在查看here时,array.array
是一个老工具,据我所知并不特别感兴趣。
如果您遇到效率问题,numpy.array
是array.array
的最佳选择,它会提供大量优化的矢量化工具。在这种情况下,32位操作通常比64位操作更快,即使在64位系统上也是如此:
import numpy as np
In [528]: %timeit np.sum(a32)
1000 loops, best of 3: 1.86 ms per loop
In [529]: %timeit np.sum(a64)
100 loops, best of 3: 2.22 ms per loop
In [530]: %timeit sum(a32)
1 loop, best of 3: 572 ms per loop
In [531]: %timeit sum(a64)
1 loop, best of 3: 604 ms per loop
如你所见,你必须避免使用较慢的纯python循环。