Thread safety and parallelism
Object ownership, synchronization and parallel assembly.
The thread-safety model
Rodin parallelizes mesh iteration within its assembly backends. Each worker evaluates local forms using its own expression objects.
- Per-object serial access. Every variational node derives from FormLanguage::
Base. Methods of a given integrator, function, shape function or problem are called by one thread at a time. - Per-thread expression trees. Expressions deep-copy their operands through
copy(). Parallel evaluation uses a separate integrator or function instance for each worker. - Concurrent immutable reads. Fully constructed meshes, connectivity and finite element spaces support concurrent reads. Access to lazily computed state follows the synchronization contract of the owning class.
- Exclusive mutation. Coordinate updates, transformation attachment, connectivity computation, mesh builders and grid-function writes require external synchronization. Required incidence relations are computed before entering a parallel region.
Synchronization of shared state
The class owning shared state defines its synchronization contract. AttributeIndex, for example, uses atomic attribute slots and per-dimension mutexes for storage growth and writes. Its contract specifies concurrent slot access and the structural operations requiring external synchronization. Mesh and field mutations follow the contracts of their respective classes.
Parallel assembly
The Assembly module provides sequential and OpenMP backends, selected by Assembly/
Floating-point summation order can vary with thread count. Numerical comparisons therefore use the specified solver and regression tolerances.
Assembly performance depends on memory bandwidth and work per quadrature point. Record thread counts, hardware and complete workload details when evaluating scaling. Reusing cell- and quadrature-dependent quantities in an integrator's bind step reduces evaluation work. Thread scaling is measured for the target workload.
MPI-distributed assembly is provided by the mirrored MPI/ module tree and composes with local assembly; see Distributed computing with MPI.
External libraries
- PETSc. Rodin calls PETSc from one thread per rank. For PETSc-dominated runs,
OMP_NUM_THREADS=1gives a serial local execution path while MPI distributes the work. Mixed OpenMP/PETSc programs must satisfy PETSc's per-object access requirements. - Eigen. Const operations support concurrent access. Eigen's internal OpenMP products can nest within Rodin's parallel regions; OpenMP nesting controls limit oversubscription.
Writing parallel-friendly code
A mesh-sweeping algorithm separates a read-only evaluation phase from a deterministic commit phase. Evaluation produces independent proposals over polytopes. Commit applies a compatible subset in a defined order. This organization supports sequential and parallel execution with the same operation semantics.
See also
- Distributed computing with MPI — distributed meshes and assembly
- Parallel solvers and distributed linear algebra with PETSc — PETSc-backed solves
- Assembly — backend selection