Various hash table improvements.
This commit is contained in:
parent
4c3755cdce
commit
983cc2c45c
@ -93,7 +93,7 @@ struct MaskNeon {
|
||||
auto eq_mask = vceqq_u8(input_mask, needle_mask);
|
||||
uint16x8_t MASK = vdupq_n_u16(0x180);
|
||||
uint16x8_t a_masked = vandq_u16(vreinterpretq_u16_u8(eq_mask), MASK);
|
||||
const int16_t __attribute__((aligned(16))) SHIFT_ARR[8] = {-7, -5, -3, -1, 1, 3, 5, 7};
|
||||
const int16 __attribute__((aligned(16))) SHIFT_ARR[8] = {-7, -5, -3, -1, 1, 3, 5, 7};
|
||||
int16x8_t SHIFT = vld1q_s16(SHIFT_ARR);
|
||||
uint16x8_t a_shifted = vshlq_u16(a_masked, SHIFT);
|
||||
return {vaddvq_u16(a_shifted) & ((1u << 14) - 1)};
|
||||
|
@ -51,11 +51,8 @@ struct MapNode {
|
||||
new (&second) ValueT(std::move(value));
|
||||
DCHECK(!empty());
|
||||
}
|
||||
~MapNode() {
|
||||
if (!empty()) {
|
||||
second.~ValueT();
|
||||
}
|
||||
}
|
||||
MapNode(const MapNode &other) = delete;
|
||||
MapNode &operator=(const MapNode &other) = delete;
|
||||
MapNode(MapNode &&other) noexcept {
|
||||
*this = std::move(other);
|
||||
}
|
||||
@ -68,6 +65,11 @@ struct MapNode {
|
||||
other.second.~ValueT();
|
||||
return *this;
|
||||
}
|
||||
~MapNode() {
|
||||
if (!empty()) {
|
||||
second.~ValueT();
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return is_key_empty(key());
|
||||
@ -109,6 +111,8 @@ struct SetNode {
|
||||
SetNode() = default;
|
||||
explicit SetNode(KeyT key) : first(std::move(key)) {
|
||||
}
|
||||
SetNode(const SetNode &other) = delete;
|
||||
SetNode &operator=(const SetNode &other) = delete;
|
||||
SetNode(SetNode &&other) noexcept {
|
||||
*this = std::move(other);
|
||||
}
|
||||
@ -119,6 +123,7 @@ struct SetNode {
|
||||
other.first = KeyT{};
|
||||
return *this;
|
||||
}
|
||||
~SetNode() = default;
|
||||
|
||||
bool empty() const {
|
||||
return is_key_empty(key());
|
||||
@ -126,7 +131,7 @@ struct SetNode {
|
||||
|
||||
void clear() {
|
||||
first = KeyT();
|
||||
CHECK(empty());
|
||||
DCHECK(empty());
|
||||
}
|
||||
|
||||
void emplace(KeyT key) {
|
||||
@ -240,16 +245,17 @@ class FlatHashTable {
|
||||
|
||||
FlatHashTable(std::initializer_list<Node> nodes) {
|
||||
reserve(nodes.size());
|
||||
for (auto &node : nodes) {
|
||||
CHECK(!node.empty());
|
||||
auto bucket = calc_bucket(node.first);
|
||||
for (auto &new_node : nodes) {
|
||||
CHECK(!new_node.empty());
|
||||
auto bucket = calc_bucket(new_node.first);
|
||||
while (true) {
|
||||
if (nodes_[bucket].key() == node.first) {
|
||||
nodes_[bucket].second = node.second;
|
||||
auto &node = nodes_[bucket];
|
||||
if (node.key() == new_node.first) {
|
||||
node.second = new_node.second;
|
||||
break;
|
||||
}
|
||||
if (nodes_[bucket].empty()) {
|
||||
nodes_[bucket].emplace(node.first, node.second);
|
||||
if (node.empty()) {
|
||||
node.emplace(new_node.first, new_node.second);
|
||||
used_nodes_++;
|
||||
break;
|
||||
}
|
||||
@ -289,10 +295,11 @@ class FlatHashTable {
|
||||
}
|
||||
auto bucket = calc_bucket(key);
|
||||
while (true) {
|
||||
if (EqT()(nodes_[bucket].key(), key)) {
|
||||
return Iterator{nodes_.begin() + bucket, this};
|
||||
auto &node = nodes_[bucket];
|
||||
if (EqT()(node.key(), key)) {
|
||||
return Iterator{&node, this};
|
||||
}
|
||||
if (nodes_[bucket].empty()) {
|
||||
if (node.empty()) {
|
||||
return end();
|
||||
}
|
||||
next_bucket(bucket);
|
||||
@ -346,13 +353,14 @@ class FlatHashTable {
|
||||
CHECK(!is_key_empty(key));
|
||||
auto bucket = calc_bucket(key);
|
||||
while (true) {
|
||||
if (EqT()(nodes_[bucket].key(), key)) {
|
||||
return {Iterator{nodes_.begin() + bucket, this}, false};
|
||||
auto &node = nodes_[bucket];
|
||||
if (EqT()(node.key(), key)) {
|
||||
return {Iterator{&node, this}, false};
|
||||
}
|
||||
if (nodes_[bucket].empty()) {
|
||||
nodes_[bucket].emplace(std::move(key), std::forward<ArgsT>(args)...);
|
||||
if (node.empty()) {
|
||||
node.emplace(std::move(key), std::forward<ArgsT>(args)...);
|
||||
used_nodes_++;
|
||||
return {Iterator{nodes_.begin() + bucket, this}, true};
|
||||
return {Iterator{&node, this}, true};
|
||||
}
|
||||
next_bucket(bucket);
|
||||
}
|
||||
@ -400,7 +408,7 @@ class FlatHashTable {
|
||||
|
||||
template <class F>
|
||||
void remove_if(F &&f) {
|
||||
auto it = nodes_.begin();
|
||||
auto it = begin().it_;
|
||||
while (it != nodes_.end() && !it->empty()) {
|
||||
++it;
|
||||
}
|
||||
@ -473,15 +481,15 @@ class FlatHashTable {
|
||||
fixed_vector<Node> old_nodes(new_size);
|
||||
std::swap(old_nodes, nodes_);
|
||||
|
||||
for (auto &node : old_nodes) {
|
||||
if (node.empty()) {
|
||||
for (auto &old_node : old_nodes) {
|
||||
if (old_node.empty()) {
|
||||
continue;
|
||||
}
|
||||
size_t bucket = calc_bucket(node.key());
|
||||
size_t bucket = calc_bucket(old_node.key());
|
||||
while (!nodes_[bucket].empty()) {
|
||||
next_bucket(bucket);
|
||||
}
|
||||
nodes_[bucket] = std::move(node);
|
||||
nodes_[bucket] = std::move(old_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,8 +525,8 @@ static void BM_cache_miss(benchmark::State &state) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t equal_mask_slow(td::uint8 *bytes, td::uint8 needle) {
|
||||
uint64_t mask = 0;
|
||||
static td::uint64 equal_mask_slow(td::uint8 *bytes, td::uint8 needle) {
|
||||
td::uint64 mask = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
mask |= (bytes[i] == needle) << i;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user