Replace O(N^2) transistor deduplication with a hash set - #20
Open
Roxxik wants to merge 1 commit into
Open
Conversation
setupNodesAndTransistors removed duplicates by scanning the survivors for each input transistor, roughly 5.3M comparisons per call. That is a one-off for cbmbasic, as the comment says, but not for measure, which rebuilds chip state 22832 times per run and spent 51% of its profile in setup. Use an open-addressed hash set instead, keyed on the canonical triple (gate, min(c1,c2), max(c1,c2)) packed into one word. The first occurrence is still kept and input order unchanged: later initialization indexes transistors_c1/c2 by a prefix sum over gate counts, so the arrays must stay in the netlist's own gate-sorted order. measure drops from 106.7 s to 62.9 s, output byte-identical.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
setupNodesAndTransistorsremoves duplicate transistors by scanning the list ofsurvivors for each input transistor. At 3288 transistors against a list growing
to 3239, that is roughly 5.3M three-array comparisons per call.
The comment on it says:
which holds for
cbmbasic, and does not hold formeasure.measurecallsresetChip_testfrom inside its per-opcode loops and so rebuilds chip state22832 times per run. Setup was 51% of that profile, with this scan at the top.
This is setup cost only. It does not touch the solver, and no simulation result
changes.
What it does instead
Detects duplicates with an open-addressed hash set, keyed on the canonical triple
(gate, min(c1,c2), max(c1,c2))packed into one 64-bit word.c1andc2areinterchangeable, so ordering them folds the reversed-
c1c2case into a plain keycomparison. The table is sized to a power of two at least twice the transistor
count, keeping the load factor at or below 0.5 so linear probing always
terminates.
The first occurrence is still the one kept, and input order is unchanged.
Later initialisation indexes
transistors_c1/c2by a prefix sum over gate counts,so the arrays have to stay in the netlist's own gate-sorted order. A sort-based fix
would have had to sort by gate for the same reason.
Verification
Both algorithms keep the same 3239 transistors in the same order, element for
element, on the shipped netlist. Checked directly rather than inferred.
measure's 256-opcode output is byte-identical, same md5 over three runs eachside.
cbmbasic --benchmarkoutput is identical apart from its own timing lines.Performance
measure, whole runcbmbasic, setup plus startupcbmbasic --benchmark, whole runmeasureis where this shows an effect: 41% off the whole run.That follows from what the change is.
measurerunsinitAndResetChip22832times, so the saving per setup is collected 22832 times; 1.8 ms times 22832 is 41 s,
against a measured difference of 44 s.
cbmbasicsets the chip up once and so collects the saving once. Its run totaldoes not change. The setup row is the split at the benchmark's own internal
clock, which starts after
initAndResetChip.Machine
AMD Ryzen 5 7640U (Zen 4), 6C/12T, SMT on. Frequency boost disabled, governor
performance,amd_pstate=active. Kernel 7.1.4-arch1-1, gcc 16.1.1. All runspinned with
taskset -c 8, both sides built up front and never rebuilt betweenruns, interleaved round-robin with the sweep direction alternating each pass. N=3
for
measure, N=42 for thecbmbasicsplit, medians reported.I used an LLM to help me out in this work, but I manually reviewed all changes made.