Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Reduce TASO hashtable size #133

Merged
merged 6 commits into from
Sep 27, 2023
Merged

perf: Reduce TASO hashtable size #133

merged 6 commits into from
Sep 27, 2023

Conversation

lmondada
Copy link
Contributor

@lmondada lmondada commented Sep 25, 2023

The idea of this PR is to store hashes of seen circuits in buckets given by the gate count of the circuit. That way hashes above a certain gate count can be cleared.

@aborgna-q I had to remove the call to tracing::trace_span. Where should I re-introduce it in the new code?

EDIT: I had run tests to compare memory usage, but the variation between runs was too big for it to mean anything. Not sure how to track memory usage well enough.

@lmondada
Copy link
Contributor Author

lmondada commented Sep 26, 2023

After some more testing (and one very crucial improvement, see latest commit), improvements are very clear. These are run with PRIORITY_QUEUE_CAPACITY = 500 to make the difference more obvious on short-ish time scales.

Command: cargo run --release -- -j1 --eccs ../test_files/Nam_6_3_complete_ECC_set.json -i ../bench-vs-quartz/circuits/barenco_tof_5.json -t120

On main

Tried 31941 circuits
END RESULT: 183
Saving result
Peak memory usage: 1.9340135 GB
Done.

This PR:

Tried 18078 circuits
END RESULT: 178
Saving result
Peak memory usage: 0.98692214 GB
Done.

Copy link
Collaborator

@aborgna-q aborgna-q left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

The changes to the priority channel will also be useful as a base for the sharding idea.

Comment on lines 137 to 138
if (pq.len() > PRIORITY_QUEUE_CAPACITY / 2
&& new_circ_cost > *pq.max_cost().unwrap())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check this before computing the hash, so we may skip that computation on some cases.

@@ -130,18 +131,23 @@ where
let rewrites = self.rewriter.get_rewrites(&circ);
for new_circ in self.strategy.apply_rewrites(rewrites, &circ) {
let new_circ_hash = new_circ.circuit_hash();
let new_circ_cost = (self.cost)(&new_circ);
circ_cnt += 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this; do we want to count repeated hashes as seen multiple times? Otherwise this should go after the branch.

src/optimiser/taso/hugr_pchannel.rs Outdated Show resolved Hide resolved
Comment on lines 158 to 163
self.log
.send(PriorityChannelLog::CircuitCount(
self.circ_cnt,
self.seen_hashes.len(),
))
.unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this out of the loop, so other breaks also trigger a last log.

self.circ_cnt += 1;
if self.circ_cnt % 1000 == 0 {
// TODO: Add a minimum time between logs
self.log
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could log directly from this thread, but currently TasoLogger is non-copyable so we cannot share it.

LGTM for now, but we'll probably want to simplify it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree.

self.buckets.push_front([hash].into_iter().collect());
return true;
};
while cost < *min_cost {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
while cost < *min_cost {
self.buckets.reserve(min_cost.saturating_sub(cost));
while cost < *min_cost {

*min_cost -= 1;
}
let bucket_index = cost - *min_cost;
while bucket_index >= self.buckets.len() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
while bucket_index >= self.buckets.len() {
let missing_back = (bucket_index+1).saturating_sub(self.buckets.len());
self.buckets.reserve(missing_back);
while bucket_index >= self.buckets.len() {

Or alternatively

let missing_back = (bucket_index+1).saturating_sub(self.buckets.len());
self.buckets.extend(iter::repeat_with(|| FxHashSet::default()).take(missing_back));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or even

if bucket_index >= self.buckets.len() {
    self.buckets.resize_with(bucket_index + 1, FxHashSet::default);
}

self.buckets[bucket_index].insert(hash)
}

// /// Returns whether the given hash is present in the set.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// /// Returns whether the given hash is present in the set.
/// Returns whether the given hash is present in the set.

@lmondada lmondada merged commit e33fc6a into main Sep 27, 2023
@lmondada lmondada deleted the fix/reduce-hash-memory branch September 27, 2023 12:16
lmondada added a commit that referenced this pull request Sep 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants