当你只关心速度时如何存储二进制数据?

时间:2016-11-23 20:18:50

标签: c++ performance data-structures stl binary

我在D维度中有N个点,其中我们说N是100万,D 1是。我的所有点都有二进制坐标,即{0,1} ^ D,我只对 speed 感兴趣。

目前我的实施使用std::vector<int>。我想知道我是否可以通过更改来加快执行速度。我只进行插入和搜索(我不会改变这些位)。

我发现提及std::vector<char>std::vector<bool>std::bitset的所有相关问题,但都提到了使用此类结构应获得的空间利益。

对于C ++中的二进制数据,当速度是主要关注时,适当的数据结构是什么?

我打算用二进制数据填充我的数据结构,然后做很多连续的搜索(我的意思是,如果我访问一个点,我真的不关心某个点的第i个坐标我会连续访问它的所有坐标)。我将计算彼此之间的汉明距离

3 个答案:

答案 0 :(得分:3)

如果值是独立的,均匀分布的,并且您想要找到两个独立的,随机选择的点之间的汉明距离,那么最有效的布局就是一个打包的位数。

理想情况下,这个打包的数组会被嵌入到popcnt指令工作的最大块大小:64位。汉明距离是popcnt(x_blocks[i] ^ y_blocks[i])的总和。在具有高效未对齐访问的处理器上,具有未对齐读取的字节对齐可能是最有效的。在未对齐读取会产生损失的处理器上,应考虑对齐行的内存开销是否值得更快。

答案 1 :(得分:2)

参考地点可能是推动力。因此,将单个点的D坐标表示为连续的位向量非常明显。 std::bitset<D>将是一个合理的选择。

但是,要实现的下一个重要事项是,您可以轻松地看到地方性优势,最高可达4KB。这意味着你不应该选择一个点并将其与所有其他N-1点进行比较。相反,将每个组的点分组为4KB,并比较这些组。两种方式都是O(N*N),但第二种方式会更快。

您可以通过使用三角不等式O(N*N)来击败Hamming(a,b)+Hamming(b,c) >= Hamming (a,c)。我只是想知道如何。这可能取决于您想要的输出方式。天真的输出将是一组N * N的距离,并且不可避免地O(N*N)

答案 2 :(得分:0)

我编写了一个简单的程序,用二进制数据填充和连续访问数据结构:

  1. std::vector<int>
  2. std::vector<char>
  3. std::vector<bool>
  4. std::bitset
  5. 我使用了Time measurements。我使用-O3优化标志,N = 1 mil,D = 100.

    这是向量的代码:

    #include <vector>
    #include <iostream>
    #include <random>
    #include <cmath>
    #include <numeric>
    #include <functional> //plus, equal_to, not2
    
    #include <ctime>
    #include <ratio>
    #include <chrono>
    
    #define T int
    
    unsigned int hd(const std::vector<T>& s1, const std::vector<T>::iterator s2)
    {
        return std::inner_product(
            s1.begin(), s1.end(), s2, 
            0, std::plus<unsigned int>(),
            std::not2(std::equal_to<std::vector<T>::value_type>())
        );
    }
    
    
    std::uniform_int_distribution<int> uni_bit_distribution(0, 1);
    std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
    
    // g++ -Wall -O3 bitint.cpp -o bitint
    int main()
    {
        const int N = 1000000;
        const int D = 100;
        unsigned int hamming_dist[N] = {0};
        unsigned int ham_d[N] = {0};
    
        std::vector<T> q;
        for(int i = 0; i < D; ++i)
            q.push_back(uni_bit_distribution(generator));
    
        using namespace std::chrono;
        high_resolution_clock::time_point t1 = high_resolution_clock::now();
    
    
        std::vector<T> v;
        v.resize(N * D);
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < D; ++j)
                v[j + i * D] = uni_bit_distribution(generator);
    
    
        high_resolution_clock::time_point t2 = high_resolution_clock::now();
    
        duration<double> time_span = duration_cast<duration<double> >(t2 - t1);
    
        std::cout << "Build " << time_span.count() << " seconds.\n";
    
        t1 = high_resolution_clock::now();
    
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < D; ++j)
            hamming_dist[i] += (v[j + i * D] != q[j]);
    
        t2 = high_resolution_clock::now();
        time_span = duration_cast<duration<double> >(t2 - t1);
        std::cout << "No function hamming distance " << time_span.count() << " seconds.\n";
    
        t1 = high_resolution_clock::now();
    
        for(int i = 0; i < N; ++i)
            ham_d[i] = hd(q, v.begin() + (i * D));
    
        t2 = high_resolution_clock::now();
        time_span = duration_cast<duration<double> >(t2 - t1);
        std::cout << "Yes function hamming distance " << time_span.count() << " seconds.\n";
    
        return 0;
    }
    

    可以在XOR bitset when 2D bitset is stored as 1D

    中找到std::bitset的代码

    对于std::vector<int>我得到了:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    

    对于std::vector<char>我得到了:

    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    

    对于std::vector<bool>我得到了:

    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    

    对于std:bitset我得到了:

    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    

    std::vector<char>似乎是胜利者。