group by optimization

This commit is contained in:
2023-01-09 22:59:41 +08:00
parent 181abacc55
commit aee803adce
7 changed files with 163 additions and 66 deletions
-4
View File
@@ -132,7 +132,3 @@ namespace ankerl::unordered_dense{
struct hash<std::tuple<Types...>> : public hasher<Types...>{ };
}
struct aq_hashtable_value_t {
uint32_t id;
uint32_t cnt;
};
+1
View File
@@ -295,6 +295,7 @@ void initialize_module(const char* module_name, void* module_handle, Context* cx
printf("Warning: module %s have no session support.\n", module_name);
}
}
#pragma endregion
int dll_main(int argc, char** argv, Context* cxt){
aq_timer timer;
+28 -28
View File
@@ -1062,7 +1062,7 @@ public:
// template <class K>
// bool hashtable_push(K&& key) {
// auto it_isinserted = try_emplace(std::forward<K>(key), 1);
// if (!it_isinserted.second)
// if (!it_isinserted.second)
// ++ it_isinserted.first->second;
// return it_isinserted.second;
// }
@@ -1113,8 +1113,8 @@ public:
template <class K,
typename Q = T,
typename H = Hash,
typename KE = KeyEqual,
std::enable_if_t<!is_map_v<Q> && is_transparent_v<H, KE>, bool> = true>
typename KE = KeyEqual>//,
//std::enable_if_t<!is_map_v<Q> && is_transparent_v<H, KE>, bool> = true>
auto hashtable_push(K&& key) -> unsigned {
if (is_full()) {
increase_size();
@@ -1141,35 +1141,35 @@ template <class K,
place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
return static_cast<uint32_t>(value_idx);
}
template <class... Args>
auto hashtable_push(Args&&... args) -> unsigned {
if (is_full()) {
increase_size();
}
// template <class... Args>
// auto hashtable_push(Args&&... args) -> unsigned {
// if (is_full()) {
// increase_size();
// }
// we have to instantiate the value_type to be able to access the key.
// 1. emplace_back the object so it is constructed. 2. If the key is already there, pop it later in the loop.
auto& key = get_key(m_values.emplace_back(std::forward<Args>(args)...));
auto hash = mixed_hash(key);
auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
auto bucket_idx = bucket_idx_from_hash(hash);
// // we have to instantiate the value_type to be able to access the key.
// // 1. emplace_back the object so it is constructed. 2. If the key is already there, pop it later in the loop.
// auto& key = get_key(m_values.emplace_back(std::forward<Args>(args)...));
// auto hash = mixed_hash(key);
// auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
// auto bucket_idx = bucket_idx_from_hash(hash);
while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
m_equal(key, get_key(m_values[at(m_buckets, bucket_idx).m_value_idx]))) {
m_values.pop_back(); // value was already there, so get rid of it
return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
}
dist_and_fingerprint = dist_inc(dist_and_fingerprint);
bucket_idx = next(bucket_idx);
}
// while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
// if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
// m_equal(key, get_key(m_values[at(m_buckets, bucket_idx).m_value_idx]))) {
// m_values.pop_back(); // value was already there, so get rid of it
// return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
// }
// dist_and_fingerprint = dist_inc(dist_and_fingerprint);
// bucket_idx = next(bucket_idx);
// }
// value is new, place the bucket and shift up until we find an empty spot
auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
// // value is new, place the bucket and shift up until we find an empty spot
// auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
// place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
return static_cast<uint32_t>(value_idx);
}
// return static_cast<uint32_t>(value_idx);
// }
template <class... Args>
auto emplace(Args&&... args) -> std::pair<iterator, bool> {
if (is_full()) {
+57
View File
@@ -427,6 +427,19 @@ constexpr vector_type<std::string_view>::vector_type(const uint32_t size, void*
// }
// }
// template<template <typename> class VT>
// inline void
// prealloc_vector (VT &vt, uint32_t sz) {
// vt.reserve(sz);
// }
// template<class T>
// inline void
// prealloc_vector (vector_type<vector_type<T>> &vt,
// uint32_t outer_sz, uint32_t inner_sz) {
// vt.reserve(outer_sz);
// auto mem = static_cast<T*>(malloc(inner_sz * sizeof(T)));
// }
template <>
class vector_type<void> {
@@ -460,4 +473,48 @@ public:
vector_type<void> subvec_deep(uint32_t);
};
#pragma pack(pop)
template <class Key, class Hash>
class AQHashTable : public ankerl::unordered_dense::set<Key, Hash> {
public:
uint32_t* reversemap, *mapbase, *ht_base;
AQHashTable() = default;
explicit AQHashTable(uint32_t sz)
: ankerl::unordered_dense::set<Key, Hash>{} {
this->reserve(sz);
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
mapbase = reversemap + sz;
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
}
void init(uint32_t sz) {
ankerl::unordered_dense::set<Key, Hash>::reserve(sz);
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
mapbase = reversemap + sz;
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
}
inline void hashtable_push(Key&& k, uint32_t i){
reversemap[i] = ankerl::unordered_dense::set<Key, Hash>::hashtable_push(std::forward<Key&&>(k));
++ht_base[reversemap[i]];
}
auto ht_postproc(uint32_t sz) {
auto& arr_values = this->values();
const auto& len = this->size();
auto vecs = static_cast<vector_type<uint32_t>*>(malloc(sizeof(vector_type<uint32_t>) * len));
vecs[0].init_from(ht_base[0], mapbase);
for (uint32_t i = 1; i < len; ++i) {
vecs[i].init_from(ht_base[i], mapbase + ht_base[i - 1]);
ht_base[i] += ht_base[i - 1];
}
for (uint32_t i = 0; i < sz; ++i) {
auto id = reversemap[i];
mapbase[--ht_base[id]] = i;
}
return vecs;
}
};
#endif