我有一个代码,我需要以随机的方式从大量的位(总共几兆字节)读取和写入单个数据位。类似于使用N维阵列玩战列舰的东西。
我怀疑一个紧凑的数组会更快,因为它会将一些数组保留在缓存中。另一方面,我知道对数组元素的访问时间,因为数组对象相当于通过编译时指针值访问,并且std :: vector的典型实现中的元素访问时间与元素访问相同通过运行时指针值(较慢)。我不知道bitset和bitfields是如何适应这一切的。
我不需要这个代码是可移植的,只是非常快(x86)。
答案 0 :(得分:1)
没有单一的答案,因为它取决于处理器架构(和编译器)。
那就是说,一个比特阵列非常快。您只需将其创建为int
的数组,然后通过选择正确的int
来访问这些位并提取正确的位。只要您的int
具有两位数(32,64等)的功率,它就会紧凑,快速 - 否则您可能必须在紧凑性和速度之间进行交易(例如在36位处理器上)你可以选择速度,每个int只使用32位。
紧凑案例中的代码变为(p[idx / BITS_PER_INT] >> (idx % BITS_PER_INT))
。对于BITS_PER_INT = 2 << SHIFT
这与(p[idx >> SHIFT] >> (idx & (BITS_PER_INT-1))) & 1
相同的快速情况。
如果您需要更多地控制数据存储,您可以自定义布局以符合您的要求(尽管如果可移植性没有问题,这也可能不是问题。)
同样,因为它也是特定于实现的最快我应该提到std::vector<bool>
虽然不能保证尽可能快或紧凑,但它很可能至少是其中之一并且可能是一个很好的权衡如果需要,他们之间。
答案 1 :(得分:0)
在研究了元素访问如何转换为汇编代码之后,我继续实现了自己的位寻址方法。 我用了
char array[n][n]...[n/8];
并创建了一个查找表
char lookup[8]={1,2,4,8,16,32,64,128};
并使用8个最低有效位将最后一个数组索引拆分为两个以访问查找表并使用二进制或|为了写位和读取我使用二进制和&amp;用我用来寻址查找表的相同索引来掩盖位和位移位。
阅读部分:
bool result=(bool)(array[x][y]...[z>>8]&lookup[(char)(z&255)])>>((char)(z&255))
写部分:
array[x][y]...[z>>8] |= lookup[(char)(z&255)] //writes 1
我对性能很满意,这应该编译成接近最小的汇编程序代码,但我没有任何可靠的证据。