Skip to content

Commit

Permalink
add repeated experiments
Browse files Browse the repository at this point in the history
  • Loading branch information
qyliu-hkust committed Aug 21, 2024
1 parent 2222f36 commit 7ca4607
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 86 deletions.
193 changes: 114 additions & 79 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@


auto bench_search(const size_t& n, const size_t& nq) {
std::cout << "===========================================" << std::endl;
std::cout << "====== n=" << n << " nq=" << nq << " ======" << std::endl;
auto data = benchmark::gen_random_keys<uint64_t>(n);
std::sort(data.begin(), data.end());
auto queries = benchmark::gen_random_keys<uint64_t>(nq);

volatile uint64_t res = 0;
Expand All @@ -31,18 +32,22 @@ auto bench_search(const size_t& n, const size_t& nq) {
std::cout << "Search result " << res << std::endl;
std::cout << "Query latency (linear) " << duration_linear / nq << std::endl;

std::vector<uint64_t> data_cpy1(data);
std::vector<uint64_t> queries_cpy1(queries);
start = std::chrono::high_resolution_clock::now();
for (auto q : queries) {
res = *search::upper_bound_branchless(data.begin(), data.end(), q);
for (auto q : queries_cpy1) {
res = *search::upper_bound_branchless(data_cpy1.begin(), data_cpy1.end(), q);
}
end = std::chrono::high_resolution_clock::now();
auto duration_branchless = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
std::cout << "Search result " << res << std::endl;
std::cout << "Query latency (branchless) " << duration_branchless / nq << std::endl;

std::vector<uint64_t> data_cpy2(data);
std::vector<uint64_t> queries_cpy2(queries);
start = std::chrono::high_resolution_clock::now();
for (auto q : queries) {
res = *std::lower_bound(data.begin(), data.end(), q);
for (auto q : queries_cpy2) {
res = *std::lower_bound(data_cpy2.begin(), data_cpy2.end(), q);
}
end = std::chrono::high_resolution_clock::now();
auto duration_branchy = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
Expand All @@ -53,6 +58,26 @@ auto bench_search(const size_t& n, const size_t& nq) {
return timer {duration_branchless/nq, duration_branchy/nq, duration_linear/nq};
}

void bench_search_repeat(const size_t& repeat, const size_t& nq, const std::string& ouput_fname) {
const size_t n_max = 21;
size_t n_list[n_max];
for (auto i=1; i<=21; ++i) {
n_list[i-1] = pow(2, i);
}

std::ofstream ofs(ouput_fname);
ofs << "n,round,brl,br,linear" << std::endl;

for (auto n : n_list) {
for (auto i=0; i<repeat; ++i) {
auto res = bench_search(n, nq);
ofs << n << "," << i << "," << res.brl << "," << res.br << "," << res.linear << std::endl;
}
}

ofs.close();
}

struct stats {
size_t eps_l;
size_t eps_i;
Expand All @@ -66,6 +91,7 @@ struct stats {
size_t latency_branchless_l;
};


template<size_t Epsilon, size_t EpsilonRecursive>
auto bench_pgm(const std::vector<uint64_t>& data, const std::vector<uint64_t>& queries) {
std::cout << "===========================================" << std::endl;
Expand Down Expand Up @@ -136,91 +162,100 @@ auto bench_pgm(const std::vector<uint64_t>& data, const std::vector<uint64_t>& q


int main(int argc, const char * argv[]) {
// bench_search_repeat(20, 500, "/Users/liuqiyu/Desktop/bench_search_result_new.csv");
// exit(0);

const std::string fname = "/Users/liuqiyu/Desktop/SOSD_data/fb_200M_uint64";
const size_t nq = 5000;
const size_t nq = 100;
const size_t repeat = 10;

std::cout << "Load data from " << fname << std::endl;
auto data = benchmark::load_data<uint64_t>(fname);
std::sort(data.begin(), data.end());

std::cout << "Generate " << nq << " random search keys." << std::endl;
auto queries = benchmark::gen_random_keys<uint64_t>(nq);
std::vector<std::pair<size_t, stats>> bench_results;

std::vector<stats> bench_results;
bench_results.emplace_back(bench_pgm<4, 4>(data, queries));
bench_results.emplace_back(bench_pgm<8, 4>(data, queries));
bench_results.emplace_back(bench_pgm<16, 4>(data, queries));
bench_results.emplace_back(bench_pgm<32, 4>(data, queries));
bench_results.emplace_back(bench_pgm<64, 4>(data, queries));
bench_results.emplace_back(bench_pgm<128, 4>(data, queries));
bench_results.emplace_back(bench_pgm<256, 4>(data, queries));
bench_results.emplace_back(bench_pgm<512, 4>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 4>(data, queries));

bench_results.emplace_back(bench_pgm<4, 8>(data, queries));
bench_results.emplace_back(bench_pgm<8, 8>(data, queries));
bench_results.emplace_back(bench_pgm<16, 8>(data, queries));
bench_results.emplace_back(bench_pgm<32, 8>(data, queries));
bench_results.emplace_back(bench_pgm<64, 8>(data, queries));
bench_results.emplace_back(bench_pgm<128, 8>(data, queries));
bench_results.emplace_back(bench_pgm<256, 8>(data, queries));
bench_results.emplace_back(bench_pgm<512, 8>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 8>(data, queries));

bench_results.emplace_back(bench_pgm<4, 16>(data, queries));
bench_results.emplace_back(bench_pgm<8, 16>(data, queries));
bench_results.emplace_back(bench_pgm<16, 16>(data, queries));
bench_results.emplace_back(bench_pgm<32, 16>(data, queries));
bench_results.emplace_back(bench_pgm<64, 16>(data, queries));
bench_results.emplace_back(bench_pgm<128, 16>(data, queries));
bench_results.emplace_back(bench_pgm<256, 16>(data, queries));
bench_results.emplace_back(bench_pgm<512, 16>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 16>(data, queries));

bench_results.emplace_back(bench_pgm<4, 32>(data, queries));
bench_results.emplace_back(bench_pgm<8, 32>(data, queries));
bench_results.emplace_back(bench_pgm<16, 32>(data, queries));
bench_results.emplace_back(bench_pgm<32, 32>(data, queries));
bench_results.emplace_back(bench_pgm<64, 32>(data, queries));
bench_results.emplace_back(bench_pgm<128, 32>(data, queries));
bench_results.emplace_back(bench_pgm<256, 32>(data, queries));
bench_results.emplace_back(bench_pgm<512, 32>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 32>(data, queries));

bench_results.emplace_back(bench_pgm<4, 64>(data, queries));
bench_results.emplace_back(bench_pgm<8, 64>(data, queries));
bench_results.emplace_back(bench_pgm<16, 64>(data, queries));
bench_results.emplace_back(bench_pgm<32, 64>(data, queries));
bench_results.emplace_back(bench_pgm<64, 64>(data, queries));
bench_results.emplace_back(bench_pgm<128, 64>(data, queries));
bench_results.emplace_back(bench_pgm<256, 64>(data, queries));
bench_results.emplace_back(bench_pgm<512, 64>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 64>(data, queries));

bench_results.emplace_back(bench_pgm<4, 128>(data, queries));
bench_results.emplace_back(bench_pgm<8, 128>(data, queries));
bench_results.emplace_back(bench_pgm<16, 128>(data, queries));
bench_results.emplace_back(bench_pgm<32, 128>(data, queries));
bench_results.emplace_back(bench_pgm<64, 128>(data, queries));
bench_results.emplace_back(bench_pgm<128, 128>(data, queries));
bench_results.emplace_back(bench_pgm<256, 128>(data, queries));
bench_results.emplace_back(bench_pgm<512, 128>(data, queries));
bench_results.emplace_back(bench_pgm<1024, 128>(data, queries));
for (auto i=0; i<repeat; ++i) {
std::cout << "Round " << i << std::endl;
std::cout << "Generate " << nq << " random search keys." << std::endl;
auto queries = benchmark::gen_random_keys<uint64_t>(nq);

bench_results.emplace_back(i, bench_pgm<4, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 4>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 4>(data, queries));

bench_results.emplace_back(i, bench_pgm<4, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 8>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 8>(data, queries));

bench_results.emplace_back(i, bench_pgm<4, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 16>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 16>(data, queries));

bench_results.emplace_back(i, bench_pgm<4, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 32>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 32>(data, queries));

bench_results.emplace_back(i, bench_pgm<4, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 64>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 64>(data, queries));

bench_results.emplace_back(i, bench_pgm<4, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<8, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<16, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<32, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<64, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<128, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<256, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<512, 128>(data, queries));
bench_results.emplace_back(i, bench_pgm<1024, 128>(data, queries));
}

// start from 7 cold cache config
std::ofstream ofs("/Users/liuqiyu/Desktop/bench_pgm_result_new_2.csv");
ofs << "eps_l,eps_i,levels,lls,ils,latency_branchy_i,latency_branchy_l,latency_branchless_i,latency_branchless_l" << std::endl;
std::ofstream ofs("/Users/liuqiyu/Desktop/bench_pgm_result_new_repeat_10.csv");
ofs << "round,eps_l,eps_i,levels,lls,ils,latency_branchy_i,latency_branchy_l,latency_branchless_i,latency_branchless_l" << std::endl;

for (auto br : bench_results) {
ofs << br.eps_l << ","
<< br.eps_i << ","
<< br.levels << ","
<< br.lls << ","
<< br.ils << ","
<< br.latency_branchy_i << ","
<< br.latency_branchy_l << ","
<< br.latency_branchless_i << ","
<< br.latency_branchless_l << std::endl;
ofs << br.first << ","
<< br.second.eps_l << ","
<< br.second.eps_i << ","
<< br.second.levels << ","
<< br.second.lls << ","
<< br.second.ils << ","
<< br.second.latency_branchy_i << ","
<< br.second.latency_branchy_l << ","
<< br.second.latency_branchless_i << ","
<< br.second.latency_branchless_l << std::endl;
}


Expand Down
10 changes: 7 additions & 3 deletions pgm_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,15 @@ class PGMIndex {

template<typename RandomIt>
auto search_data(RandomIt start, const K &key) {
auto pos = search(key);
auto k = std::max(first_key, key);
auto it = segment_for_key(k);
auto pos = std::min<size_t>((*it)(k), std::next(it)->intercept);
auto lo = PGM_SUB_EPS(pos, Epsilon);
auto hi = PGM_ADD_EPS(pos, Epsilon, n);
if constexpr (BranchLessSearch) {
return search::lower_bound_branchless(start+pos.lo, start+pos.hi, key);
return search::lower_bound_branchless(start+lo, start+hi, key);
} else {
return std::lower_bound(start+pos.lo, start+pos.hi, key);
return std::lower_bound(start+lo, start+hi, key);
}
}

Expand Down
8 changes: 4 additions & 4 deletions search_algo.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ template<typename RandomIt, typename K>
RandomIt lower_bound_linear(RandomIt start, RandomIt end, const K& key) {
auto it = start;
while (it != end) {
if (*it ==key)
break;
it++;
if (*it >= key)
return it;
++it;
}
return it;
return end;
}


Expand Down

0 comments on commit 7ca4607

Please sign in to comment.