Data structure 当您只关心速度时,如何存储二进制数据?

Data structure 当您只关心速度时,如何存储二进制数据?,data-structure,c++,performance,data-structures,stl,binary,Data Structure,C++,Performance,Data Structures,Stl,Binary,我在D维上有N个点,假设N是一百万,D是一百。我所有的点都有二进制坐标,即{0,1}^D,我只对速度感兴趣 目前我的实现使用的是std::vector。我想知道我是否可以通过改变我的状态来提高执行速度。我只做插入和搜索(我不更改位) 我发现的所有相关问题都提到了std::vector、std::vector和std::bitset,但都提到了使用这种结构应该获得的空间优势 < C++ > 中的二进制数据,当关注速度最重要的时候,什么是合适的数据结构? 我打算用二进制数据填充我的数据结构,然后进

我在D维上有N个点,假设N是一百万,D是一百。我所有的点都有二进制坐标,即{0,1}^D,我只对速度感兴趣

目前我的实现使用的是
std::vector
。我想知道我是否可以通过改变我的状态来提高执行速度。我只做插入和搜索(我不更改位)

我发现的所有相关问题都提到了
std::vector
std::vector
std::bitset
,但都提到了使用这种结构应该获得的空间优势

< C++ >

中的二进制数据,当关注速度最重要的时候,什么是合适的数据结构?

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

如果这些值是独立、均匀分布的,并且您希望找到两个独立、随机选择的点之间的汉明距离,则最有效的布局是压缩位数组


理想情况下,此压缩数组将被分块为
popcnt
指令工作的最大块大小:64位。汉明距离是
popcnt(x_块[i]^y_块[i])
的总和。在具有高效未对齐访问的处理器上,具有未对齐读取的字节对齐可能是最有效的。在不对齐读会引起惩罚的处理器上,人们应该考虑对齐行的内存开销是否值得更快的逻辑。

< P>如果这些值是独立的、均匀分布的,并且您想在两个独立的、随机选择的点之间找到汉明距离,最有效的布局是位的压缩数组


理想情况下,此压缩数组将被分块为
popcnt
指令工作的最大块大小:64位。汉明距离是
popcnt(x_块[i]^y_块[i])
的总和。在具有高效未对齐访问的处理器上,具有未对齐读取的字节对齐可能是最有效的。在不对齐读取引起惩罚的处理器上,人们应该考虑对齐行的内存开销是否值得更快的逻辑。

< P>引用的位置可能是驱动力。因此,很明显,您可以将单个点的
D
坐标表示为一个连续的位向量<代码>标准::位集将是一个合乎逻辑的选择

然而,要认识到的下一件重要事情是,您可以很容易地看到高达4KB的本地性优势。这意味着您不应选择一个点并将其与所有其他N-1点进行比较。相反,将点分组,每组4KB,并比较这些组。这两种方法都是
O(N*N)
,但第二种方法的速度要快得多


你可以使用三角形不等式-
Hamming(a,b)+Hamming(b,c)>=Hamming(a,c)
击败
O(N*N)
。我只是想知道怎么做。这可能取决于您希望输出的方式。原始输出将是一组N*N的距离,这是不可避免的
O(N*N)

参考位置可能是驱动力。因此,很明显,您可以将单个点的
D
坐标表示为一个连续的位向量<代码>标准::位集将是一个合乎逻辑的选择

然而,要认识到的下一件重要事情是,您可以很容易地看到高达4KB的本地性优势。这意味着您不应选择一个点并将其与所有其他N-1点进行比较。相反,将点分组,每组4KB,并比较这些组。这两种方法都是
O(N*N)
,但第二种方法的速度要快得多


你可以使用三角形不等式-
Hamming(a,b)+Hamming(b,c)>=Hamming(a,c)
击败
O(N*N)
。我只是想知道怎么做。这可能取决于您希望输出的方式。原始输出将是一组N*N距离,这是不可避免的
O(N*N)

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

  • std::vector
  • std::vector
  • std::vector
  • std::位集
  • 我用了我的手机。我使用了-O3优化标志,N=1密耳,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;
    }
    
    对于
    std::vector
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    
    对于
    std::vector
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    
    对于
    std:bitset
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    


    std::vector
    似乎是赢家。

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

  • std::vector
  • std::vector
  • std::vector
  • std::位集
  • 我用了我的手机。我使用了-O3优化标志,N=1密耳,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;
    }
    
    对于
    std::vector
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    
    对于
    std::vector
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    
    对于
    std:bitset
    我得到:

    Build 3.80404 seconds.
    No function hamming distance 0.0322335 seconds.
    Yes function hamming distance 0.0352869 seconds.
    
    Build 8.2e-07 seconds.
    No function hamming distance 8.4e-08 seconds.
    Yes function hamming distance 2.01e-07 seconds.
    
    Build 4.34496 seconds.
    No function hamming distance 0.162005 seconds.
    Yes function hamming distance 0.258315 seconds.
    
    Build 4.28947 seconds.
    Hamming distance 0.00385685 seconds.
    


    std::vector
    似乎是赢家。

    @ks1322,我很难看到你在那里编辑了什么,但我可以看到你没有投票-这是否意味着这个问题很糟糕,应该删除?没有问题很糟糕。有些人需要一些指导,但每个问题都有潜力。@nicomp这有点乐观,但我明白你的意思。然而,您和ks1322看到了这个问题,没有投票。我开始担心了,你有什么改进的建议吗?我刚刚修复了损坏的格式,你可以通过单击
    并排标记
    轻松看到它。是的,我同意@nicomp,但我这里没有调试问题要解决。:)@ks1322,我很难看到你们在那个里编辑了什么,但我可以看到你们并没有投票——是的