Data structure 当您只关心速度时,如何存储二进制数据?
我在D维上有N个点,假设N是一百万,D是一百。我所有的点都有二进制坐标,即{0,1}^D,我只对速度感兴趣 目前我的实现使用的是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++ > 中的二进制数据,当关注速度最重要的时候,什么是合适的数据结构? 我打算用二进制数据填充我的数据结构,然后进
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::位集
#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::位集
#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,我很难看到你们在那个里编辑了什么,但我可以看到你们并没有投票——是的