从整数数组构造位集

Posted

技术标签:

【中文标题】从整数数组构造位集【英文标题】:Construct bitset from array of integers 【发布时间】:2015-07-06 06:49:58 【问题描述】:

uint64_t 构造bitset<64> 很容易:

uint64_t flags = ...;
std::bitset<64> bsflags;

但是有没有一种从uint64_t[N] 构造bitset&lt;64 * N&gt; 的好方法,这样flags[0] 将引用最低64 位?

uint64_t flags[3];
// ... some assignments
std::bitset<192> bsflags;  // this very unhelpfully compiles
                             // yet is totally invalid

还是我不得不循环调用set()

【问题讨论】:

您的意思是从每个uint64_t 中取出最低8 位吗?以及按什么顺序? @Wintermute 哎呀。我想要所有的位。 flags[0] 将是最低 64 位。 可能类似于constexpr std::size_t FLAGS_SIZE = 3; uint64_t flags[FLAGS_SIZE]; std::bitset&lt;64 * FLAGS_SIZE&gt;(); std::bitset 没有接受元素数组的转换(其中 elements 是底层 std::bitset 类型)。在我看来,这是一个失败,因为 std::vector 是。 为什么投反对票?想要能够做到这一点就这么不合理吗? 【参考方案1】:

std::bitset 没有范围构造函数,所以你必须循环,但是用std::bitset::set() 单独设置每个位是不够的。 std::bitset 支持二元运算符,所以至少可以批量设置 64 位:

  std::bitset<192> bs;

  for(int i = 2; i >= 0; --i) 
    bs <<= 64;
    bs |= flags[i];
  

更新:在 cmets 中,@icando 提出了对std::bitsets 的位移是 O(N) 操作的有效担忧。对于非常大的位集,这最终会吃掉批量处理的性能提升。在我的基准测试中,std::bitset&lt;N * 64&gt; 的盈亏平衡点与单独设置位且不改变输入数据的简单循环相比:

int pos = 0;
for(auto f : flags) 
  for(int b = 0; b < 64; ++b) 
    bs.set(pos++, f >> b & 1);
  

N == 200 附近(x86-64 上的 gcc 4.9,带有 libstdc++ 和-O2)。 Clang 的表现稍差,在N == 160 附近收支平衡。带有 -O3 的 Gcc 将其推高到 N == 250

取低端,这意味着如果您想使用 10000 位或更大的位集,这种方法可能不适合您。 在 32 位平台上(例如常见的 ARM) ,阈值可能会更低,因此在此类平台上使用 5000 位位集时请记住这一点。但是,我认为,在此之前的某个地方,您应该问自己 bitset 是否真的是容器的正确选择。

【讨论】:

如果 bs 是 bitset,那么 shift 是 O(N) 操作,所以整个循环是 O(N^2) 操作。没有人注意到这一点? @Barry,您所说的“还是我不得不在循环中调用 set()?”,实际上是比这更好的解决方案。你接受了一个 O(N^2) 的解决方案,因为你自己有一个 O(N) 的解决方案,这很奇怪。 这对于大型位集来说是个好点。我怀疑 192 位位集是否会达到收支平衡点,其中移位涉及(在 PC 上)两个机器字,但在某些时候它会。让我来做个基准测试。 @icando 基准测试结果在;超过 10 kbits 的收支平衡。我注意到您的担忧以及何时与答案相关;如果有人来考虑以这种方式滥用std::bitset,那就太好了。但是,对于合理的用例,我不相信会达到阈值。 @Wintermute 酷。我正在处理非常小的Ns,主要对代码清晰度而不是性能感兴趣,所以双赢!另外, 【参考方案2】:

如果从范围初始化很重要,您可以考虑使用 std::vector

它确实有来自一对迭代器的构造函数

【讨论】:

以上是关于从整数数组构造位集的主要内容,如果未能解决你的问题,请参考以下文章

Cuda:XOR 单个位集与位集数组

可变大小的位集[重复]

有没有办法使用numpy从python中的2D数组构造3D数组?

将数组从另一个类的构造函数传递给类函数

数据初始化

526. 优美的排列