如何在C ++中构建N位变量?

时间:2017-10-31 19:55:52

标签: c++ algorithm optimization bitset bitarray

我正在处理C ++中非常大的布尔列表,每个约有2 ^ N个N布尔值。因为在这种情况下内存是关键的,即指数增长,我想构建一个N位长变量来存储每个元素。

对于小N,例如24,我只是使用unsigned long int。需要64MB((2 ^ 24)* 32/8/1024/1024)。但我需要达到36.内置变量的唯一选择是unsigned long long int,但需要512GB((2 ^ 36)* 64/8/1024/1024/1024),这有点太多了。 使用36位变量,它对我有用,因为它的大小下降到288GB((2 ^ 36)* 36/8/1024/1024/1024),这适合我的超级计算机的节点。

我尝试了std::bitset,但std::bitset< N >创建了至少为8B的元素。 因此,std::bitset< 1 >列表远远大于unsigned long int列表。 这是因为std::bitset只是改变了表示,而不是容器。

我也尝试过来自Boost的boost::dynamic_bitset<>,但结果甚至最差(至少32B!),出于同样的原因。

我知道一个选项是将所有元素写为一个布尔链,2473901162496(2 ^ 36 * 36),然后存储在38654705664(2473901162496/64)unsigned long long int中,得到288GB(38654705664 * 64/8/1024/1024/1024)。然后访问元素只是找到存储36位的元素的游戏(可以是一个或两个)。但是现有代码(3000行)的重写很多,因为映射变得不可能,并且因为在某些功能执行期间添加和删除项目肯定会复杂,混乱,具有挑战性,结果很可能效率不高。

如何在C ++中构建N位变量?

3 个答案:

答案 0 :(得分:5)

具有5个字符的结构如何(可能需要根据需要进行一些奇妙的运算符重载以使其与现有代码兼容)?由于填充/对齐,带有long和char的结构可能不起作用...

基本上你自己的迷你BitSet针对尺寸进行了优化:

struct Bitset40 {
   unsigned char data[5];
   bool getBit(int index) {
     return (data[index / 8] & (1 << (index % 8))) != 0;
   }
   bool setBit(int index, bool newVal) {
     if (newVal) {
        data[index / 8] |= (1 << (index % 8));
     } else {
        data[index / 8] &= ~(1 << (index % 8));
     }
   }
};

编辑:正如geza在他评论中指出的那样,这里的“技巧”是尽可能接近所需的最小字节数(不会因触发对齐损失而浪费内存,填充或指针间接,请参阅http://www.catb.org/esr/structure-packing/)。

编辑2 :如果您有冒险精神,也可以尝试一下该字段(请告诉我们实际消耗的空间):

struct Bitset36 {
  unsigned long long data:36;
}

答案 1 :(得分:3)

我不是专家,但我会“尝试”。找到编译器支持的最小类型的字节(应该是char)。您可以检查sizeof,你应该得到1.这意味着1个字节,所以8位。

所以如果你想要一个24位类型......你需要3个字符。对于36你需要5个char数组,你最后会有4位浪费的填充。这很容易解释。

即。

char typeSize[3] = {0}; // should hold 24 bits

现在制作一个位掩码来访问typeSize的每个位置。

const unsigned char one = 0b0000'0001;
const unsigned char two = 0b0000'0010;
const unsigned char three = 0b0000'0100;
const unsigned char four = 0b0000'1000;
const unsigned char five = 0b0001'0000;
const unsigned char six = 0b0010'0000;
const unsigned char seven = 0b0100'0000;
const unsigned char eight = 0b1000'0000;

现在您可以按位使用或在需要时将值设置为1.

typeSize[1] |= four; 
*typeSize[0] |= (four | five); 

要关闭位,请使用&amp;操作者..

typeSize[0] &= ~four; 
typeSize[2] &= ~(four| five); 

你可以用&amp;读取每个位的位置。操作

typeSize[0] & four

请记住,我没有编译器方便尝试这个,所以希望这是一个有用的方法来解决你的问题。

祝你好运; - )

答案 2 :(得分:1)

您可以使用<div class="container"> <div class="sidebar"> <ul> <li>blah blah</li> <li>blah blah</li> <li>blah blah</li> </ul> </div> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur egestas ante id sem pulvinar, et facilisis justo convallis. Integer tempor elit a ullamcorper scelerisque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla eu sagittis urna. Mauris at suscipit ex, ac rutrum turpis. Ut ut ligula non magna pharetra tempor. Suspendisse aliquet turpis vel nibh rutrum placerat. Fusce interdum leo ut tristique euismod. Donec venenatis elit ornare ex pharetra tristique ut ac odio. Duis non finibus odio, sed congue est. Nullam accumsan tellus in porttitor maximus. Fusce pharetra tincidunt magna a bibendum. Aenean bibendum turpis sed risus faucibus placerat. Sed vel nisl massa. Vestibulum maximus pretium semper. Integer tempus orci eget orci aliquam commodo. Donec enim massa, vehicula sit amet turpis posuere, rhoncus convallis elit. Donec interdum tellus justo, eu semper ligula mattis nec. Quisque eu molestie neque. Nulla mollis mollis tortor ac convallis. Praesent malesuada erat in lectus imperdiet, volutpat iaculis risus euismod. Aenean non iaculis nunc. Pellentesque vel libero semper mi pulvinar gravida in et orci. Mauris bibendum ligula ex, sed feugiat massa varius et. Praesent diam elit, bibendum quis nisl quis, aliquam venenatis lorem. In sagittis varius tortor eu facilisis. Donec orci nunc, bibendum sit amet neque feugiat, luctus luctus dui. Nam vestibulum lacinia leo in vulputate. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut dignissim est sit amet bibendum tempus. Etiam non tincidunt justo. Suspendisse at maximus dolor. Fusce dictum in orci ut mattis. Pellentesque elementum ante turpis, eu dapibus diam euismod in. </div>数组,并使用按位运算存储和检索所需的位链。这种方法排除了空间开销。

无符号字节数组B []和12位变量V(表示为ushort)的简化示例:

unsigned long int