Files
parallel-hashmap/examples/matt.cc
T

141 lines
4.6 KiB
C++
Raw Normal View History

2020-07-26 17:35:55 -04:00
#include <chrono>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
2023-04-23 19:40:33 -04:00
#include <utility>
2020-07-26 17:35:55 -04:00
#include <vector>
#include <random>
#include <parallel_hashmap/phmap.h>
2020-07-27 17:30:11 -04:00
#include <parallel_hashmap/btree.h>
2020-07-26 17:35:55 -04:00
// -------------------------------------------------------------------
// -------------------------------------------------------------------
class Timer
{
public:
2023-04-23 19:40:33 -04:00
Timer(std::string name) : _name(std::move(name)), _start(std::chrono::high_resolution_clock::now()) {}
2020-07-26 17:35:55 -04:00
~Timer()
{
std::chrono::duration<float> elapsed_seconds = std::chrono::high_resolution_clock::now() - _start;
printf("%s: %.3fs\n", _name.c_str(), elapsed_seconds.count());
}
private:
std::string _name;
std::chrono::high_resolution_clock::time_point _start;
};
// --------------------------------------------------------------------------
// from: https://github.com/preshing/RandomSequence
// --------------------------------------------------------------------------
class RSU
{
private:
uint32_t m_index;
uint32_t m_intermediateOffset;
static uint32_t permuteQPR(uint32_t x)
{
static const uint32_t prime = 4294967291u;
if (x >= prime)
return x; // The 5 integers out of range are mapped to themselves.
uint32_t residue = ((unsigned long long) x * x) % prime;
return (x <= prime / 2) ? residue : prime - residue;
}
public:
RSU(uint32_t seedBase, uint32_t seedOffset)
{
m_index = permuteQPR(permuteQPR(seedBase) + 0x682f0161);
m_intermediateOffset = permuteQPR(permuteQPR(seedOffset) + 0x46790905);
}
uint32_t next()
{
return permuteQPR((permuteQPR(m_index++) + m_intermediateOffset) ^ 0x5bf03635);
}
};
using Perturb = std::function<void (std::vector<uint64_t> &)>;
2020-07-26 17:35:55 -04:00
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
template<class Set, size_t N>
2023-04-23 19:40:33 -04:00
void test(const char *name, const Perturb &perturb1, const Perturb& /* perturb2 */)
2020-07-26 17:35:55 -04:00
{
2020-07-27 17:30:11 -04:00
//phmap::btree_set<uint64_t> s;
2020-07-26 17:35:55 -04:00
Set s;
unsigned int seed = 76687;
RSU rsu(seed, seed + 1);
for (uint32_t i=0; i<N; ++i)
s.insert(rsu.next());
2020-07-27 17:30:11 -04:00
std::vector<uint64_t> order(s.begin(), s.end()); // contains sorted, randomly generated keys (when using phmap::btree_set)
// or keys in the final order of a Set (when using Set).
2020-07-27 17:30:11 -04:00
perturb1(order); // either keep them in same order, or shuffle them
#if 0
2020-07-26 17:35:55 -04:00
order.resize(N/4);
perturb2(order);
#endif
2020-07-26 17:35:55 -04:00
Timer t(name); // start timer
2020-07-27 17:30:11 -04:00
Set c;
//c.reserve(order.size()); // whether this "reserve()" is present or not makes a huge difference
2020-07-27 17:30:11 -04:00
c.insert(order.begin(), order.end()); // time for inserting the same keys into the set
// should not depend on them being sorted or not.
2020-07-26 17:35:55 -04:00
}
2020-07-27 17:30:11 -04:00
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
2020-07-26 18:09:54 -04:00
template <class T, size_t N>
using pset = phmap::parallel_flat_hash_set<T,
phmap::priv::hash_default_hash<T>,
phmap::priv::hash_default_eq<T>,
phmap::priv::Allocator<T>, // alias for std::allocator
2020-07-26 18:09:54 -04:00
N>;
2020-07-26 17:35:55 -04:00
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
int main()
{
auto shuffle = [](std::vector<uint64_t> &order) {
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(order.begin(), order.end(), g);
};
2020-07-26 17:39:10 -04:00
auto noop = [](std::vector<uint64_t> &) {};
auto perturb2 = noop;
constexpr uint32_t num_keys = 10000000;
using T = uint64_t;
2020-07-26 17:35:55 -04:00
test<phmap::flat_hash_set<T>, num_keys>("flat_hash_set ordered ", noop, perturb2);
2020-07-26 17:39:10 -04:00
test<phmap::flat_hash_set<T>, num_keys>("flat_hash_set shuffled", shuffle, perturb2);
2020-07-26 17:39:10 -04:00
test<pset<T, 4>, num_keys>("parallel (16) ordered ", noop, perturb2);
test<pset<T, 4>, num_keys>("parallel (16) shuffled", shuffle, perturb2);
test<pset<T, 6>, num_keys>("parallel (64) ordered ", noop, perturb2);
test<pset<T, 6>, num_keys>("parallel (64) shuffled", shuffle, perturb2);
test<pset<T, 8>, num_keys>("parallel (256) ordered ", noop, perturb2);
test<pset<T, 8>, num_keys>("parallel (256) shuffled", shuffle, perturb2);
2020-07-26 17:35:55 -04:00
}