group by optimization
This commit is contained in:
@@ -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;
|
||||
};
|
||||
@@ -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
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user