Skip to content

Commit 21c7e96

Browse files
Replace vector<bool> with vector<char> for faster computations
Signed-off-by: Dragana Grbic <draganaurosgrbic@gmail.com>
1 parent becf5a3 commit 21c7e96

2 files changed

Lines changed: 24 additions & 22 deletions

File tree

src/tesseract.cc

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ bool Node::operator>(const Node& other) const {
2323
}
2424

2525
double TesseractDecoder::get_detcost(size_t d,
26-
const std::vector<bool>& blocked_errs,
26+
const std::vector<char>& blocked_errs,
2727
const std::vector<size_t>& det_counts,
28-
const std::vector<bool>& dets) const {
28+
const std::vector<char>& dets) const {
2929
double min_cost = INF;
3030
for (size_t ei : d2e[d]) {
3131
if (!blocked_errs[ei]) {
@@ -86,14 +86,16 @@ void TesseractDecoder::initialize_structures(size_t num_detectors) {
8686
}
8787

8888
struct VectorBoolHash {
89-
size_t operator()(const std::vector<bool>& v) const {
90-
std::hash<bool> bool_hash;
91-
size_t seed = 0;
92-
for (bool b : v) {
93-
// Combine hash values of individual booleans.
94-
// A simple way is to use XOR and bit shifting,
95-
// but you can use other combining strategies as well.
96-
seed ^= bool_hash(b) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
89+
size_t operator()(const std::vector<char>& v) const {
90+
size_t seed = v.size(); // Still good practice to incorporate vector size
91+
92+
// Iterate over char elements. Accessing 'b_val' is now a direct memory read.
93+
for (char b_val : v) {
94+
// The polynomial rolling hash with 31 (or another prime)
95+
// 'b_val' is already a char (an 8-bit integer).
96+
// static_cast<size_t>(b_val) ensures it's promoted to size_t before arithmetic.
97+
// This cast is efficient (likely a simple register extension/move).
98+
seed = seed * 31 + static_cast<size_t>(b_val);
9799
}
98100
return seed;
99101
}
@@ -151,7 +153,7 @@ bool QNode::operator>(const QNode& other) const {
151153
}
152154

153155
void TesseractDecoder::to_node(const QNode& qnode,
154-
const std::vector<bool>& shot_dets,
156+
const std::vector<char>& shot_dets,
155157
size_t det_order, Node& node) const {
156158
node.cost = qnode.cost;
157159
node.errs = qnode.errs;
@@ -197,20 +199,20 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
197199
size_t det_beam = config.det_beam;
198200
predicted_errors_buffer.clear();
199201
low_confidence_flag = false;
200-
std::vector<bool> dets(num_detectors, false);
202+
std::vector<char> dets(num_detectors, false);
201203
for (size_t d : detections) {
202204
dets[d] = true;
203205
}
204206

205207
std::priority_queue<QNode, std::vector<QNode>, std::greater<QNode>> pq;
206208
std::unordered_map<size_t,
207-
std::unordered_set<std::vector<bool>, VectorBoolHash>>
209+
std::unordered_set<std::vector<char>, VectorBoolHash>>
208210
discovered_dets;
209211

210212
size_t min_num_dets;
211213
{
212214
std::vector<size_t> errs;
213-
std::vector<bool> blocked_errs(num_errors, false);
215+
std::vector<char> blocked_errs(num_errors, false);
214216
std::vector<size_t> det_counts(num_errors, 0);
215217

216218
for (size_t d = 0; d < num_detectors; ++d) {
@@ -238,8 +240,8 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
238240
size_t max_num_dets = min_num_dets + det_beam;
239241
Node node;
240242
std::vector<size_t> next_det_counts;
241-
std::vector<bool> next_next_blocked_errs;
242-
std::vector<bool> next_dets;
243+
std::vector<char> next_next_blocked_errs;
244+
std::vector<char> next_dets;
243245
std::vector<size_t> next_errs;
244246
while (!pq.empty()) {
245247
const QNode qnode = pq.top();
@@ -311,7 +313,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
311313
}
312314
// We cache as we recompute the det costs
313315
std::vector<double> det_costs(num_detectors, -1);
314-
std::vector<bool> next_blocked_errs = node.blocked_errs;
316+
std::vector<char> next_blocked_errs = node.blocked_errs;
315317
if (config.at_most_two_errors_per_detector) {
316318
for (int ei : d2e[min_det]) {
317319
// Block all errors of this detector -- note this is an approximation

src/tesseract.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ struct TesseractConfig {
4141
class Node {
4242
public:
4343
std::vector<size_t> errs;
44-
std::vector<bool> dets;
44+
std::vector<char> dets;
4545
double cost;
4646
size_t num_dets;
47-
std::vector<bool> blocked_errs;
47+
std::vector<char> blocked_errs;
4848

4949
bool operator>(const Node& other) const;
5050
};
@@ -96,10 +96,10 @@ struct TesseractDecoder {
9696
size_t num_errors;
9797

9898
void initialize_structures(size_t num_detectors);
99-
double get_detcost(size_t d, const std::vector<bool>& blocked_errs,
99+
double get_detcost(size_t d, const std::vector<char>& blocked_errs,
100100
const std::vector<size_t>& det_counts,
101-
const std::vector<bool>& dets) const;
102-
void to_node(const QNode& qnode, const std::vector<bool>& shot_dets,
101+
const std::vector<char>& dets) const;
102+
void to_node(const QNode& qnode, const std::vector<char>& shot_dets,
103103
size_t det_order, Node& node) const;
104104
};
105105

0 commit comments

Comments
 (0)