为什么 std::bitset<8> 4 个字节大?
Why is std::bitset<8> 4 bytes big?
似乎对于std::bitset<1到32>,大小设置为4字节。对于33到64的大小,它直接跳到8字节。不可能有任何开销,因为std::bitset<32>是一个偶数4字节。
当处理位时,我可以看到对齐到字节长度,但是为什么bitset需要对齐到字长度,特别是对于最有可能在内存预算紧张的情况下使用的容器?
最可能的解释是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;
另外,每个bitset最大浪费3字节并不完全是内存问题。考虑到bitset已经是存储这类信息的最有效的数据结构,因此您必须以总结构大小的百分比来评估浪费。
对于1025位,这种方法使用132字节而不是129字节,为2.3%的开销(并且随着bitset站点的增加而降低)。考虑到可能带来的性能好处,这听起来很合理。
现代机器上的内存系统除了从内存中提取所需位的一些遗留函数外,不能从内存中提取任何其他内容。因此,将bitset与单词对齐可以使它们的处理速度快得多,因为在访问它时不需要屏蔽不需要的位。如果不使用掩码,请输入
bitset<4> foo = 0;
if (foo) {
// ...
}
很可能会失败。除此之外,我记得前一段时间读到有一种方法可以将几个bitset挤在一起,但我记不清了。我认为当你在一个结构中有几个位集在一起时,它们可以占用"共享"内存,这不适用于比特域的大多数用例。
我在Aix和Linux实现中有相同的特性。在Aix中,内部bitset存储是基于char的:
typedef unsigned char _Ty;
....
_Ty _A[_Nw + 1];
在Linux中,内部存储是基于long的:
typedef unsigned long _WordT;
....
_WordT _M_w[_Nw];
出于兼容性的考虑,我们修改了Linux版本,使用基于字符的存储
检查在bitset.h
因为32位的intel兼容处理器不能单独访问字节(或者更好的是,它可以通过隐式地应用一些位掩码和移位),而每次只能访问32位的字。
如果你声明
bitset<4> a,b,c;
即使库将实现为char, a
, b
和c
也将以32位对齐,因此存在相同的浪费空间。但是处理器将被迫在让bitset代码执行自己的掩码之前对字节进行预掩码。
因此MS使用int[1+(N-1)/32]
作为位的容器
也许是因为它默认使用int
,并切换到long long
,如果它溢出?(只是猜测…)
如果你的std::bitset<如果8>是结构体的成员,你可以这样写:如果8>
struct A
{
std::bitset< 8 > mask;
void * pointerToSomething;
}
如果bitset<8>存储在一个字节中(并且结构体封装在1字节边界上),那么结构体中跟随它的指针将是未对齐的,这将是一件坏事。将bitset<8>存储在一个字节中是安全且有用的唯一情况是,它在一个打包结构中,并且后面跟着一些可以打包在一起的其他单字节字段。我想这个用例太窄了,不值得提供一个库实现。
基本上,在你的八叉树中,一个单字节的bitset只有在一个打包结构中后跟另外一个到三个单字节的成员时才有用。否则,无论如何都必须将其填充为四个字节(在32位机器上),以确保下面的变量与单词对齐。
- 从不同线程使用int64的不同字节安全吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- EASTL矢量<向量<int>>连续的
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 字节到位运算符重载C++
- 在java中读取c++字节的位字段
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 字节真的是最小可寻址单元吗
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- asn1c 不会从 asn.1 模块中提取八位字节字符串的默认值
- 如何将原始字节附加到 std::vector?