perf: two-level grid makes point location outpace TriFinder - #5
Merged
Conversation
The single grid sized cells to the whole domain, but a graded MARE2DEM mesh concentrates its small triangles -- and every region seed -- in a core the huge boundary triangles dwarf. Profiling the largest fixture showed the median cell held 2 triangles while the cells the seeds actually landed in held up to 2,940: 65M candidate pairs, 1.07s. Two levels fix the mismatch. The fine level sizes cells to the median triangle, so the dense core stays at a few candidates per query; the triangles too large for it (they would smear across >64 fine cells) go to a coarse sqrt(n) grid, where they are few enough to keep cells small. Queries check the fine level first and skip resolved points on the coarse pass. Largest fixture (75k triangles x 38k seeds), identical indices: - single grid 1.09s - two-level 0.137s - TriFinder 0.402s 380k-seed stress (the target workload), identical indices: - two-level 0.392s - TriFinder 0.791s The 0.7s regression PR #4 accepted is gone; the pure-numpy locator is now 2-3x faster than matplotlib's C++ trapezoid map on these workloads, because its per-instantiation build is 72ms against TriFinder's O(n log n) construction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Follow-up to #4, removing the 0.7s regression it accepted — and going past the matplotlib implementation it replaced. Motivated by upcoming models with much larger seed counts.
Diagnosis
Profiling the largest fixture showed the single grid was healthy on average but wrong exactly where it mattered:
A graded MARE2DEM mesh concentrates its small triangles — and every region seed — in a core that the huge boundary triangles dwarf. Cells sized to the whole domain put thousands of core triangles into single cells.
Fix
Two grid levels:
Queries hit the fine level first; the coarse pass skips already-resolved points.
Measured (identical indices to TriFinder in every case)
The pure-numpy locator now beats the C++ trapezoid map 2–3× on these workloads: TriFinder pays an O(n log n) build per instantiation, the two-level grid builds in 72ms.
New test class exercises both levels on a synthetic graded mesh (tiny core inside ±500 boundary giants) with an 800-point cross-check against matplotlib. Suite: 379 passed.
🤖 Generated with Claude Code