我正在尝试使用
numpy
的 nbytes
属性来检查具有不同 dtype
的数组的内存使用情况。我注意到以下几点:
>>> np.zeros(1024, dtype='int64').nbytes / 1024 # in kB
8.0
>>> np.zeros(1024, dtype='int8').nbytes / 1024
1.0
>>> np.zeros(1024, dtype='bool').nbytes / 1024
1.0 # ?
前两行的结果对我来说很有意义,因为报告的内存使用量(分别为 8 kB 和 1 kB)只是每个元素的内存使用量(分别为 8 和 1 字节)乘以的总和元素数量(两种情况下均为 1024)。然而,在最后一种情况下,我假设
bool
类型的数组每个元素只需要一位内存,但是似乎每个元素需要 8 位,与 int8
相同。
我的问题:
nbytes
的输出?如果是这样,我们应该如何理解 bool
类型每个元素不使用一位的事实?bool
上使用 int8
类型数组?这个问题是在我处理二进制(0和1)值的数组时出现的,并试图找到空间有效的解决方案(就内存而言,因为我假设计算时间没有差异?),我认为会使用
bool
类型。
我是否正确解释了
的输出?如果是这样,我们应该如何理解nbytes
类型每个元素不使用一位这一事实?bool
是的,这是正确的。
bool
使用与 int8
相同的空间。
这样做的原因是 NumPy 要求数组的所有元素都是可寻址的。在大多数当前的 CPU 上,您最多可以在字节级别寻址。
如果您想要更高效的内存解决方案,您有以下几种选择:
考虑到这一点,是否有理由在
上使用bool
类型数组?int8
两者在很多方面表现不同。如果您使用
int8
作为布尔类型,那么您可能会看到一些令人惊讶的结果。
例如,假设您想要对数组进行 NOT 运算。对于
bool
,这正如您所期望的那样。但是对于int8
...
>>> import numpy as np
>>> bools = np.array([True, False, True])
>>> ints = bools.astype('int8')
>>> ~bools
array([False, True, False])
>>> ~ints
array([-2, -1, -2], dtype=int8)
...它采用值的按位 NOT,这会导致所有 0 或 1 值变为 -1 或 -2,如果转换回
bool
,这两个值都将被解释为 True。
或者,假设您想从某个条件为 True 的数组中获取值。如果您使用
bool
,这将被解释为过滤操作。如果您使用 int8
,它会被解释为 索引操作,并且您会得到不同的结果。
>>> a = np.arange(3)
>>> a[bools]
array([0, 2])
>>> a[ints]
array([1, 0, 1])
一般来说,您应该以能够解释您的意图的方式使用数据类型。如果您想要布尔值,则应该使用
bool
。这样你就会在 NumPy 中发现更少的惊喜。