Skip to content

Tetrahedral_remeshing: replace hash containers with linear scans over small, bounded sets - #9594

Open
IasonManolas wants to merge 4 commits into
CGAL:mainfrom
IasonManolas:mr/collapse-simulation-and-index-counting
Open

Tetrahedral_remeshing: replace hash containers with linear scans over small, bounded sets#9594
IasonManolas wants to merge 4 commits into
CGAL:mainfrom
IasonManolas:mr/collapse-simulation-and-index-counting

Conversation

@IasonManolas

Copy link
Copy Markdown
Member

Summary

Four independent optimizations, grouped together because each replaces a hash-based container
with a direct lookup or a linear scan, in places where the container never holds more than a
handful of elements, so hashing costs more than it saves:

  • Ask the triangulation which facets bound the cell set. is_cells_set_manifold() counted,
    for each facet of a candidate cell set, how many times each vertex triple appears, via a hashed
    vertex-triple-to-count map, to find facets shared by exactly one cell (the boundary of the
    set). The triangulation already knows which facets border a given cell set: a direct
    cell-neighbor lookup replaces the hashed triple counting.
  • Build the collapse simulation without hash containers. CollapseTriangulation's
    constructor numbered the star's roughly twenty vertices via an unordered_set plus an
    unordered_map, hashing a compact-container iterator for each. A small_vector of pairs with
    linear scan replaces both, since a star this small is cheaper to scan than to hash.
  • Search the collapse work list by hash, not in order. The collapse work list is a bimap
    whose element side was set_of<Edge, Compare_edges>, an ordered container, so every membership
    test (the priority update or erase that follows each collapse) cost O(log n) comparisons, each
    building and comparing canonical vertex pairs. That side is never iterated in order; only the
    priority side is, and it is untouched. Switched to unordered_set_of with matching
    Hash_edges/Equal_edges.
  • Count the indices around a simplex without a hash set. nb_incident_subdomains() and
    nb_incident_surface_patches() filled an unordered_set with every index seen around a vertex
    or edge just to read its size back out, for a count that is almost always 1 or 2. Replaced with
    an inline small_vector and linear dedup.

Testing

Verdict equivalence. All four changes are alternative implementations of the same predicate
or count; none change which candidate is evaluated, selected, or in what order. Full test suite
(all executables in test/Tetrahedral_remeshing) passes.

Byte-identical output, against plain cgal/main:

mesh tets byte-identical
bear ~40K YES
bunny00 ~225K YES
101556.mesh (Thingi10K) 3,521,237 YES

Performance. perf stat -e instructions, Linux, Release, sequential, measured with
PR #9587 applied as the base, since that PR's decisive-accept fast path already skips
CollapseTriangulation for most candidates and changes how often the second optimization above
gets exercised. Byte-identical to that base on all three meshes.

mesh iterations base (#9587) instr this MR Δ instr
bear 10 50.40 G 47.40 G -5.95%
bunny00 10 123.35 G 117.05 G -5.11%
101556.mesh 3 1775.84 G 1669.82 G -5.97%

Release Management

  • Affected package(s): Tetrahedral_remeshing
  • License and copyright ownership: unchanged

…ell set

is_cells_set_manifold() counted, for each facet of a candidate cell
set, how many times each vertex triple appears, via a hashed
vertex-triple-to-count map, to find facets shared by exactly one cell
(the boundary of the set). The triangulation already knows which
facets border a given cell set: a direct cell-neighbor lookup replaces
the hashed triple counting.
…tainers

CollapseTriangulation's constructor numbered the star's ~20 vertices
via an unordered_set plus an unordered_map, hashing a compact-container
iterator through Time_stamper for each. A small_vector of pairs with
linear scan replaces both, since a star this small is cheaper to scan
than to hash.
…order

The collapse work list is a bimap whose element side was set_of<Edge,
Compare_edges>, an ordered container, so every membership test (the
priority update or erase that follows each collapse) cost O(log n)
comparisons, each building and comparing canonical vertex pairs. That
side is never iterated in order; only the priority side is, and it is
untouched. Switched to unordered_set_of with matching Hash_edges and
Equal_edges.
…ash set

nb_incident_subdomains() and nb_incident_surface_patches() filled an
unordered_set with every index seen around a vertex or edge just to
read its size back out, for a count that is almost always 1 or 2.
Replaced with an inline small_vector and linear dedup.
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