繁体   English   中英

为什么 std::bitset<8> 4 个字节大?

[英]Why is std::bitset<8> 4 bytes big?

似乎对于 std::bitset<1 到 32>,大小设置为 4 个字节。 对于 33 到 64 的大小,它直接跳转到 8 个字节。 不会有任何开销,因为 std::bitset<32> 是偶数 4 个字节。

在处理位时,我可以看到对齐字节长度,但是为什么位集需要对齐字长,尤其是对于最有可能在内存预算紧张的情况下使用的容器?

这是在 VS2010 下。

最可能的解释是bitset使用了整数个机器字来存储数组。

这样做可能是出于内存带宽的原因:读/写在字边界对齐的字通常相对便宜。 另一方面,在某些架构上读取(尤其是写入!)任意对齐的字节可能很昂贵。

由于我们谈论的是每个bitset几个字节的固定大小的惩罚,这对于通用库来说听起来是一个合理的权衡。

我假设对 bitset 的索引是通过获取 32 位值然后隔离相关位来完成的,因为这在处理器指令方面是最快的(在 x86 上使用较小的值较慢)。 为此所需的两个索引也可以非常快速地计算出来:

int wordIndex = (index & 0xfffffff8) >> 3;
int bitIndex = index & 0x7;

然后你可以这样做,这也非常快:

int word = m_pStorage[wordIndex];
bool bit = ((word & (1 << bitIndex)) >> bitIndex) == 1;

此外,恕我直言,每个位集最多浪费 3 个字节并不完全是内存问题。 考虑到位集已经是存储此类信息的最有效的数据结构,因此您必须将浪费评估为总结构大小的百分比。

对于 1025 位,此方法使用 132 字节而不是 129 字节,开销为 2.3%(并且随着位集站点的增加而减少)。 考虑到可能的性能优势,这听起来很合理。

除了一些提取所需位的遗留函数之外,现代机器上的内存系统不能从内存中获取除单词之外的任何其他内容。 因此,将位集与字对齐会使它们处理起来更快,因为在访问它时不需要屏蔽掉不需要的位。 如果你不屏蔽,做类似的事情

bitset<4> foo = 0;
if (foo) {
    // ...
}

很可能会失败。 除此之外,我记得前段时间读到有一种方法可以将几个 bitset 压缩在一起,但我记不清了。 我认为当您在一个结构中将多个位集放在一起时,它们可以占用“共享”内存,这不适用于位域的大多数用例。

我在 Aix 和 Linux 实现中具有相同的功能。 在 Aix 中,内部位集存储是基于字符的:

typedef unsigned char _Ty;
....
_Ty _A[_Nw + 1];

在 Linux 中,内部存储是长基的:

typedef unsigned long _WordT;
....
_WordT            _M_w[_Nw];

出于兼容性原因,我们使用基于字符的存储修改了 Linux 版本

检查您在 bitset.h 中使用的是哪种实现

因为 32 位 Intel 兼容处理器不能单独访问字节(或者更好,它可以通过隐式应用一些位掩码和移位)但一次只能访问 32 位字。

如果你声明

bitset<4> a,b,c;

即使库将其实现为 char, abc也将是 32 位对齐的,因此存在相同的浪费空间。 但是在让位集代码做自己的掩码之前,处理器将被迫预先掩码字节。

出于这个原因,MS 使用int[1+(N-1)/32]作为位的容器。

也许是因为它默认使用int ,如果溢出则切换到long long (只是猜测……)

如果你的 std::bitset<8> 是一个结构的成员,你可能有这个:

struct A
{
  std::bitset< 8 > mask;
  void * pointerToSomething;
}

如果 bitset<8> 存储在一个字节中(并且结构打包在 1 字节边界上),那么在结构中跟随它的指针将是未对齐的,这将是一件坏事。 将 bitset<8> 存储在一个字节中是安全和有用的唯一时间是,如果它处于打包结构中,然后是其他一些可以将其打包在一起的单字节字段。 我想这是一个过于狭窄的用例,不值得提供一个库实现。

基本上,在你的八叉树中,一个单字节位集只有在一个打包结构中跟随另一个一到三个单字节成员时才有用。 否则,无论如何都必须将其填充为四个字节(在 32 位机器上)以确保以下变量是字对齐的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM