访问和更改长布尔数组的最快实现是什么?

What is the fastest implementation for accessing and changing a long array of boolean?

本文关键字:实现 是什么 数组 布尔 访问      更新时间:2023-10-16

我想实现一个很长的布尔数组(作为二进制基因组),并访问一些间隔来检查该间隔是否全部为真,此外,我想改变一些间隔值,

例如,我可以创建4个表示:

boolean binaryGenome1[10e6]={false};
vector<bool> binaryGenome2; binaryGenome2.resize(10e6);
vector<char> binaryGenome3; binaryGenome3.resize(10e6);
bitset<10e6> binaryGenome4;

并以这种方式访问:

inline bool checkBinGenome(long long start , long long end){
  for(long long i = start; i < end+1 ; i++)
    if(binaryGenome[i] == false)
        return false;
  return true;
}
inline void changeBinGenome(long long start , long long end){
  for(long long i = start; i < end+1 ; i++)
    binaryGenome[i] = true;
}

vector<char>normal boolean array (ass将每个布尔值存储在一个字节中)似乎都是一个糟糕的选择,因为我需要在空间中高效。但是vector<bool>bitset有什么区别呢?

在其他地方我读到向量有一些开销,因为你可以选择它的大小和编译时间-"开销"是什么-访问?开销是多少?

我想使用CheckBinGenome()changeBinGenome()多次访问数组元素,最快的实现是什么?

使用std::bitset是最好的。

如果在编译时知道数据的长度,则考虑使用std::array<bool>std::bitset。后者可能更节省空间(您必须衡量访问时间中相关的额外工作是否超过减少缓存压力带来的速度增益—这将取决于您的工作负载)。

如果你的数组长度不固定,那么你需要一个std::vector<bool>std::vector<char>;还有boost::dynamic_bitset,但是我从来没用过。

如果您将一次更改大的区域,就像您的示例所暗示的那样,构造您自己的表示并直接操作底层存储可能是值得的,而不是通过迭代器一次操作一位。例如,如果使用char的数组作为基础表示,那么将大范围设置为0或1主要是memset()std::fill()调用,只计算范围开始和结束处的值。在尝试之前,我会先从一个简单的实现和一组良好的单元测试开始。

对于std::vector<bool>std::array<bool>和/或std::bitset的迭代器,你的标准库有专门的算法版本(至少在理论上)是可能的,它们完全可以完成上面的工作,或者你可以编写和贡献这样的专门化。如果可能的话,这是一条更好的道路——世界可能会感谢你,你也会分担一些维护的责任。

重要提示

如果使用std::array<bool>,您需要注意,与其他std::array<>实例化不同,它不实现标准容器语义。这并不是说它不应该被使用,但要确保你了解它的缺点!

,检查所有元素是否为true

我真的不确定这是否会给我们带来比加速更多的开销。实际上,我认为现在的CPU可以做到这一点相当快,你真的遇到了一个糟糕的性能?(或者这只是你真正问题的一个骨架?)

#include <omp.h>
#include <iostream>
#include <cstring>
using namespace std;
#define N 10000000
bool binaryGenome[N];
int main() {
    memset(binaryGenome, true, sizeof(bool) * N);
    int shouldBreak = 0;
    bool result = true;
    cout << result << endl;
    binaryGenome[9999995] = false;
    bool go = true;
    uint give = 0;
#pragma omp parallel
    {
        uint start, stop;
#pragma omp critical
        {
            start = give;
            give += N / omp_get_num_threads();
            stop = give;
            if (omp_get_thread_num() == omp_get_num_threads() - 1)
                stop = N;
        }
        while (start < stop && go) {
            if (!binaryGenome[start]) {
                cout << start << endl;
                go = false;
                result = false;
            }
            ++start;
        }
    }
    cout << result << endl;
}