Skip to content

Commit 089d232

Browse files
committed
handle equal k merge case separately, remove reference from iterators over primitive coupons
1 parent 3aad1b6 commit 089d232

3 files changed

Lines changed: 74 additions & 33 deletions

File tree

hll/include/Hll4Array-internal.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Hll4Array<A>::Hll4Array(const HllArray<A>& other) :
6060
this->hllByteArr_.resize(numBytes, 0);
6161
this->oooFlag_ = other.isOutOfOrderFlag();
6262

63-
for (const auto& coupon : other) { // all = false, so skip empty values
63+
for (const auto coupon : other) { // all = false, so skip empty values
6464
internalCouponUpdate(coupon); // updates KxQ registers
6565
}
6666
this->hipAccum_ = other.getHipAccum();

hll/include/Hll6Array-internal.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Hll6Array<A>::Hll6Array(const HllArray<A>& other) :
4343
this->oooFlag_ = other.isOutOfOrderFlag();
4444
uint32_t num_zeros = 1 << this->lgConfigK_;
4545

46-
for (const auto& coupon : other) { // all = false, so skip empty values
46+
for (const auto coupon : other) { // all = false, so skip empty values
4747
num_zeros--;
4848
internalCouponUpdate(coupon); // updates KxQ registers
4949
}

hll/include/Hll8Array-internal.hpp

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Hll8Array<A>::Hll8Array(const HllArray<A>& other):
4141
this->oooFlag_ = other.isOutOfOrderFlag();
4242
uint32_t num_zeros = 1 << this->lgConfigK_;
4343

44-
for (const auto& coupon : other) { // all = false, so skip empty values
44+
for (const auto coupon : other) { // all = false, so skip empty values
4545
num_zeros--;
4646
internalCouponUpdate(coupon); // updates KxQ registers
4747
}
@@ -114,37 +114,78 @@ void Hll8Array<A>::mergeList(const CouponList<A>& src) {
114114
template<typename A>
115115
void Hll8Array<A>::mergeHll(const HllArray<A>& src) {
116116
// at this point src_k >= dst_k
117-
const uint32_t dst_mask = (1 << this->getLgConfigK()) - 1;
118-
// special treatment below to optimize performance
119-
if (src.getTgtHllType() == target_hll_type::HLL_8) {
120-
uint32_t i = 0;
121-
for (const auto value: src.getHllArray()) {
122-
processValue(i++, dst_mask, value);
117+
// we can optimize further when the k values are equal
118+
if (this->getLgConfigK() == src.getLgConfigK()) {
119+
if (src.getTgtHllType() == target_hll_type::HLL_8) {
120+
uint32_t i = 0;
121+
for (const auto value: src.getHllArray()) {
122+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
123+
++i;
124+
}
125+
} else if (src.getTgtHllType() == target_hll_type::HLL_6) {
126+
const uint32_t src_k = 1 << src.getLgConfigK();
127+
uint32_t i = 0;
128+
const uint8_t* ptr = src.getHllArray().data();
129+
while (i < src_k) {
130+
uint8_t value = *ptr & 0x3f;
131+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
132+
++i;
133+
value = *ptr++ >> 6;
134+
value |= (*ptr & 0x0f) << 2;
135+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
136+
++i;
137+
value = *ptr++ >> 4;
138+
value |= (*ptr & 3) << 4;
139+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
140+
++i;
141+
value = *ptr++ >> 2;
142+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
143+
++i;
144+
}
145+
} else { // HLL_4
146+
const auto& src4 = static_cast<const Hll4Array<A>&>(src);
147+
uint32_t i = 0;
148+
for (const auto byte: src.getHllArray()) {
149+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
150+
++i;
151+
this->hllByteArr_[i] = std::max(this->hllByteArr_[i], src4.adjustRawValue(i, byte >> 4));
152+
++i;
153+
}
123154
}
124-
} else if (src.getTgtHllType() == target_hll_type::HLL_6) {
125-
const uint32_t src_k = 1 << src.getLgConfigK();
126-
uint32_t i = 0;
127-
const uint8_t* ptr = src.getHllArray().data();
128-
while (i < src_k) {
129-
uint8_t value = *ptr & 0x3f;
130-
processValue(i++, dst_mask, value);
131-
value = *ptr++ >> 6;
132-
value |= (*ptr & 0x0f) << 2;
133-
processValue(i++, dst_mask, value);
134-
value = *ptr++ >> 4;
135-
value |= (*ptr & 3) << 4;
136-
processValue(i++, dst_mask, value);
137-
value = *ptr++ >> 2;
138-
processValue(i++, dst_mask, value);
139-
}
140-
} else { // HLL_4
141-
const auto& src4 = static_cast<const Hll4Array<A>&>(src);
142-
uint32_t i = 0;
143-
for (const auto byte: src.getHllArray()) {
144-
processValue(i, dst_mask, src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
145-
++i;
146-
processValue(i, dst_mask, src4.adjustRawValue(i, byte >> 4));
147-
++i;
155+
} else {
156+
// src_k > dst_k
157+
const uint32_t dst_mask = (1 << this->getLgConfigK()) - 1;
158+
// special treatment below to optimize performance
159+
if (src.getTgtHllType() == target_hll_type::HLL_8) {
160+
uint32_t i = 0;
161+
for (const auto value: src.getHllArray()) {
162+
processValue(i++, dst_mask, value);
163+
}
164+
} else if (src.getTgtHllType() == target_hll_type::HLL_6) {
165+
const uint32_t src_k = 1 << src.getLgConfigK();
166+
uint32_t i = 0;
167+
const uint8_t* ptr = src.getHllArray().data();
168+
while (i < src_k) {
169+
uint8_t value = *ptr & 0x3f;
170+
processValue(i++, dst_mask, value);
171+
value = *ptr++ >> 6;
172+
value |= (*ptr & 0x0f) << 2;
173+
processValue(i++, dst_mask, value);
174+
value = *ptr++ >> 4;
175+
value |= (*ptr & 3) << 4;
176+
processValue(i++, dst_mask, value);
177+
value = *ptr++ >> 2;
178+
processValue(i++, dst_mask, value);
179+
}
180+
} else { // HLL_4
181+
const auto& src4 = static_cast<const Hll4Array<A>&>(src);
182+
uint32_t i = 0;
183+
for (const auto byte: src.getHllArray()) {
184+
processValue(i, dst_mask, src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
185+
++i;
186+
processValue(i, dst_mask, src4.adjustRawValue(i, byte >> 4));
187+
++i;
188+
}
148189
}
149190
}
150191
this->setRebuildKxqCurminFlag(true);

0 commit comments

Comments
 (0)