我可以强制python数组元素具有特定的大小吗?

时间:2016-04-25 05:11:45

标签: python arrays numpy

我使用数组模块来存储大量数字(许多千兆字节)的无符号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吗?

3 个答案:

答案 0 :(得分:5)

如果您想坚持使用arrayset the typecodeIunsigned int)而不是Lunsigned 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.arrayarray.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循环。