int8 与 bool dtype 的 NumPy 数组大小和性能差异

问题描述 投票:0回答:1

我正在尝试使用

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
类型。

python numpy memory types numpy-ndarray
1个回答
3
投票

我是否正确解释了

nbytes
的输出?如果是这样,我们应该如何理解
bool
类型每个元素不使用一位这一事实?

是的,这是正确的。

bool
使用与
int8
相同的空间。

这样做的原因是 NumPy 要求数组的所有元素都是可寻址的。在大多数当前的 CPU 上,您最多可以在字节级别寻址。

如果您想要更高效的内存解决方案,您有以下几种选择:

  • NumPy 可以使用 packbits 和 unpackbits 将布尔数组转换为 8 位整数数组,其中每个整数代表 8 个布尔值。
  • 另一个库,bitarray,支持每个字节 8 个布尔值,但它的功能比 NumPy 少。 (例如不支持多维数组。)

考虑到这一点,是否有理由在

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 中发现更少的惊喜。

© www.soinside.com 2019 - 2024. All rights reserved.