Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 17 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Add the CMake option SAMURAI_MEASURE_SET_ALGEBRA (OFF by default). When it is on and the timers are enabled, every apply() traverses its set expression three times: once with a sink callback (timer "set algebra (pure)", count column = rows visited), once for real (timer "set algebra + callback", count column = intervals emitted) and once, untimed, to count the row blocks (consecutive rows emitting the same x intervals) and the empty row segments. SAMURAI_MEASURE_APPLY=0 in the environment keeps only the phase timers. SAMURAI_MEASURE_PHASE(name) splits a hot function into timed phases and publishes the phase name, so that finalize() can print the counters (applies, rows, intervals, cells, blocks, empty segments) per phase. update_ghost_mr is split into projection, prediction, outer (B.C.) and periodic ghosts. Everything expands to nothing without the option.
gouarin
force-pushed
the
set-algebra-granularity
branch
from
September 7, 2026 07:42
c3916cb to
681edbc
Compare
…st update Half to 60 % of the ghost update (advection 2D and 3D, scalar Burgers 2D) was the filling of the outer ghosts by the boundary conditions, and 85 to 90 % of that phase was pure set algebra visiting 20 to 40 rows per interval emitted. Two causes, both in the way the expressions were written: - the domain, the corners and the B.C. regions are stored at max_level and were coarsened on the fly with self(x).on(level), whose traverser materialises 2^(max_level - level) fine rows per coarse row; - difference(cells, translate(domain, -d)) visits every row of cells even when the boundary in direction d lies on a single row. The geometry that depends on the domain only is now built once per domain at every level and inherited by the meshes constructed from a reference mesh (level_pyramid.hpp): - mesh.corner(direction, level): corner pyramids, which also stops construct_corners from recomputing the domain corners at every mesh construction (2.1 s of a 17.7 s 3D run); - mesh.boundary_inner_layer(level, d) = domain \ translate(domain, -d) and mesh.boundary_outer_layer(level, d, k) = translate(domain, k d) \ translate(domain, (k - 1) d); - bc.region(d, level): the B.C. regions at every level. The outer ghost expressions read those sets at their level and intersect with the thin layers instead of subtracting the domain: domain_boundary is intersection(cells, inner layer); project_bc intersects the translated union with the outer layer (inner is inside the domain, so the sets are the same); predict_bc, on a box domain, predicts each layer straight from the expression with the order-0 prediction kernel per interval instead of materialising a level cell array and copying cell by cell. The non-box paths keep their former expressions. Measured in the sandbox (gcc 15, Release, 3 runs, median), ghost update inside the adaptation: advection 2D 0.430 s -> 0.241 s (x1.78), scalar Burgers 2D 2.583 s -> 1.819 s (x1.42), advection 3D 4.225 s -> 2.219 s (x1.90); total runtime x1.16, x1.11 and x1.40. The HDF5 outputs of the three demos are bit-identical to main. bench_set: no entry moves by more than 2 %, the codegen canary BM_RefineFootprint_adapted<3> is unchanged (subset/ is not touched). tests/test_boundary_geometry.cpp checks, cell by cell on an adapted 2D and 3D mesh whose refinement reaches the boundary, that every precomputed set equals its .on(level) definition, that the rewritten expressions equal the former ones, and that the predict_bc layers are disjoint. The geometry is a pure function of the domain: it is copied to the neighbour meshes together with the domain, and the accessors build it on first use when a mesh received its domain without going through finalize_mesh (a deserialised neighbour mesh, on which petsc::compute_cell_ownership calls domain_boundary_outer_layer).
gouarin
force-pushed
the
set-algebra-granularity
branch
from
September 7, 2026 08:31
681edbc to
41d6788
Compare
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.
Available tags: 'build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'
Description
Half to 60 % of
ghost update(advection 2D and 3D, scalar Burgers 2D) is the filling of the outer ghosts by the boundary conditions, and 85 to 90 % of that phase is pure set algebra visiting 20 to 40 rows per interval emitted. Two causes, both in the way the expressions are written:max_leveland coarsened on the fly withself(x).on(level), whose traverser materialises2^(max_level - level)fine rows per coarse row;difference(cells, translate(domain, -d))visits every row ofcellseven when the boundary in directiondlies on a single row.The geometry that depends on the domain only is now built once per domain at every level and inherited by the meshes constructed from a reference mesh (
level_pyramid.hpp):mesh.corner(direction, level): corner pyramids. This also stopsconstruct_cornersfrom recomputing the domain corners at every mesh construction (2.1 s of a 17.7 s 3D run);mesh.boundary_inner_layer(level, d)=domain \ translate(domain, -d)andmesh.boundary_outer_layer(level, d, k)=translate(domain, k d) \ translate(domain, (k - 1) d);bc.region(d, level): the B.C. regions at every level.The outer ghost expressions read those sets at their level and intersect with the thin layers instead of subtracting the domain:
domain_boundaryisintersection(cells, inner layer);project_bcintersects the translated union with the outer layer (the union lies inside the domain, so the sets are the same);predict_bc, on a box domain, predicts each layer straight from the expression with the order-0 prediction kernel per interval instead of materialising a level cell array and copying cell by cell. The non-box paths keep their former expressions.The first commit adds the measurement build used to find this (
-DSAMURAI_MEASURE_SET_ALGEBRA=ON, off by default, expands to nothing otherwise): per-phase timers inupdate_ghost_mrand, perapply(), the pure set algebra time, the rows visited, the intervals emitted, the row blocks and the empty row segments. It can be reviewed or dropped independently of the second commit.Measurements
Sandbox Linux aarch64, gcc 15, Release, 3 runs, median,
--timers,--nfiles 1:bench_set(3 repetitions, medians): no entry moves by more than 2 %, the codegen canaryBM_RefineFootprint_adapted<3>is unchanged;subset/is not touched. Not yet measured with clang on macOS nor with MPI.Related issue
None.
How has this been tested?
h5diffon the 16 HDF5 files written byfinite-volume-advection-2d(both prediction stencils),finite-volume-scalar-burgers-2dandfinite-volume-advection-3d: bit-identical tomain.tests/test_boundary_geometry.cpp(2D and 3D, adapted mesh whose refinement reaches the boundary and the corners, levels 2 to 6): every precomputed set equals its.on(level)definition cell by cell, every rewritten expression equals its former form, and thepredict_bclayers are disjoint.test_samurai_lib: 442 tests pass (440 existing + 2 new).Code of Conduct
By submitting this PR, you agree to follow our Code of Conduct