Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions doc/generate_profiling_figures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ if needle not in content:
content = content.replace(
needle,
"env = EnvironmentOptions(\n"
" profiling_activated=True,\n"
" profiling_trace=True,\n"
" deactivate_profiling=False,\n"
")",
)
open(path, "w").write(content)
Expand Down
47 changes: 43 additions & 4 deletions doc/sections/userguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -780,13 +780,52 @@ Struphy's simulation-wide profiler is configured in
The relevant switches live in :class:`~struphy.EnvironmentOptions`:

1. ``profiling_activated=True`` enables profiling data collection.
2. ``profiling_trace=True`` additionally records a time trace of profiling
regions.

The profiler is set up automatically in ``Simulation.__init__()`` and finalized
when ``Simulation.run()`` finishes. The simulation code already wraps key work
inside regions such as ``model.integrate`` via
``ProfileManager.profile_region(...)``.
inside regions via ``ProfileManager.profile_region(...)``. Since the profiler is
active from the end of ``Simulation.__init__()``, the setup phase is covered as
well, and the following regions are recorded out of the box:

1. Setup: ``setup: allocate`` (total allocation time), with the nested regions
``setup: feec`` (``setup: derham``, ``setup: mass ops``, ``setup: basis ops``,
``setup: projected equil``), ``setup: variables`` (one
``setup var: <species>.<variable>`` region per model variable, so that e.g.
marker drawing shows up per particle species), ``setup: propagators`` (one
``setup prop: <PropagatorName>`` region per propagator) and
``setup: helpers``.
2. Remaining run preparation: ``setup: run metadata``, ``setup: data storage``,
``setup: geometry vtk``, ``setup: plasma params``,
``setup: initial diagnostics``, ``setup: hdf5 datasets`` and, for restarted
runs, ``setup: restart``.
3. Time loop: ``model.integrate``, ``diagnostics``, ``save data`` and
``sort particles``.

Inside ``model.integrate`` the regions nest as follows:

1. ``prop: <PropagatorName>``, one per propagator call (twice per step for the
half steps of Strang splitting).
2. Particle pushing: ``pusher: <kernel_name>`` for a full
:class:`~struphy.pic.pushing.pusher.Pusher` call, containing one
``kernel: <kernel_name>`` region per pusher, init and eval kernel call.
3. Accumulation: ``accum: <kernel_name>`` for a full
:class:`~struphy.pic.accumulation.particles_to_grid.Accumulator` call,
containing the ``kernel: <kernel_name>`` region of the accumulation kernel
and ``accum comm: <kernel_name>`` for the assembly/ghost-region exchange and
the inter-clone ``Allreduce``.
4. Particle bookkeeping and communication, recorded wherever they are called
from: ``mpi_sort_markers``, ``apply_kinetic_bc``, ``put_particles_in_boxes``
and ``do_sort``.
5. Linear solves: ``solve: SchurSolver``, ``solve: SchurSolverFull``,
``solve: SchurSolverFull3``, ``solve: SaddlePointSolver``,
``solve: ODEsolverFEEC`` for the shared solver classes, and
``solve: <PropagatorName>`` for propagators that call a
``feectools`` inverse operator directly.
6. ``update_feec_variables`` for writing back FEEC coefficients (includes the
ghost-region update).

Since regions nest, the sum over all regions exceeds the wall-clock time; use
the flame graph (below) to read the containment.

Example configuration:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
# --------------------------

# Environment options
env = EnvironmentOptions(sim_folder="sim_1",profiling_activated=True, profiling_trace=True, restart=False)
env = EnvironmentOptions(sim_folder="sim_1",profiling_activated=True, restart=False)

# Time stepping
time_opts = Time(dt=0.001, Tend=0.01, split_algo="LieTrotter")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
# --------------------------

# Environment options
env = EnvironmentOptions(sim_folder="sim_1", profiling_activated=True, profiling_trace=True, restart=False)
env = EnvironmentOptions(sim_folder="sim_1", profiling_activated=True, restart=False)

# Time stepping
time_opts = Time(dt=5.0, Tend=500.0, split_algo="LieTrotter")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
# --------------------------

# Environment options
env = EnvironmentOptions(sim_folder="sim_1", profiling_activated=True, profiling_trace=True, restart=False)
env = EnvironmentOptions(sim_folder="sim_1", profiling_activated=True, restart=False)

# Time stepping
time_opts = Time(dt=0.01, Tend=51.0, split_algo="LieTrotter")
Expand Down
116 changes: 0 additions & 116 deletions params_LinearMHDDriftkineticCC.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
env = EnvironmentOptions(
sim_folder=f"sim_{args.id:02d}",
profiling_activated=True,
profiling_trace=True,
restart=False,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
env = EnvironmentOptions(
sim_folder=f"sim_{args.id:02d}",
profiling_activated=True,
profiling_trace=True,
restart=False
)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dependencies = [
"pytest-testmon<=2.2.0",
"ruff==0.15.0, <=0.16.0",
"line_profiler<=5.0.2",
"scope-profiler==0.2.6, <=0.2.6",
"scope-profiler<=0.2.8",
]

[project.license]
Expand Down
8 changes: 4 additions & 4 deletions src/struphy/io/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,9 @@ class EnvironmentOptions(OptionsBase):
Folder in ``out_folders/`` for the current simulation (default= ``sim_1/`` ).
Will create the folder if it does not exist OR cleans the folder for new runs.

sim_label: str | None, optional
Label for the simulation (default=None)

restart : bool
Whether to restart a run (default=False).

Expand All @@ -332,20 +335,17 @@ class EnvironmentOptions(OptionsBase):

profiling_activated: bool, optional
Activate profiling with scope-profiler (default=False)

profiling_trace: bool, optional
Save time-trace of each profiling region (default=False)
"""

out_folders: str = os.getcwd()
sim_folder: str = "sim_1"
sim_label: str | None = None
Comment thread
max-models marked this conversation as resolved.
restart: bool = False
max_runtime: int = 300
save_step: int = 1
sort_step: int = 0
num_clones: int = 1
profiling_activated: bool = False
profiling_trace: bool = False

def __post_init__(self):
self.path_out: str = os.path.join(self.out_folders, self.sim_folder)
Expand Down
2 changes: 2 additions & 0 deletions src/struphy/linear_algebra/saddle_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from feectools.linalg.block import BlockLinearOperator, BlockVector, BlockVectorSpace
from feectools.linalg.direct_solvers import SparseSolver
from feectools.linalg.solvers import inverse
from scope_profiler import ProfileManager

from struphy.linear_algebra.tests.test_saddlepoint_massmatrices import _plot_residual_norms

Expand Down Expand Up @@ -249,6 +250,7 @@ def Apre(self, a):
elif self._variant == "Inverse_Solver":
self._Apre = a

@ProfileManager.profile("solve: SaddlePointSolver")
def __call__(self, U_init=None, Ue_init=None, P_init=None, out=None):
"""
Solves the saddle-point problem using the Uzawa algorithm.
Expand Down
4 changes: 4 additions & 0 deletions src/struphy/linear_algebra/schur_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from feectools.linalg.block import BlockLinearOperator, BlockVector
from feectools.linalg.solvers import inverse
from line_profiler import profile
from scope_profiler import ProfileManager

from struphy.linear_algebra.solver import SolverParameters

Expand Down Expand Up @@ -108,6 +109,7 @@ def BC(self, bc):
self._BC = bc

@profile
@ProfileManager.profile("solve: SchurSolver")
def __call__(self, xn, Byn, dt, out=None):
"""Solves the 2x2 block matrix linear system.

Expand Down Expand Up @@ -228,6 +230,7 @@ def __init__(self, M, solver_name, **solver_params):
self._rhs = self._A.codomain.zeros()

@profile
@ProfileManager.profile("solve: SchurSolverFull")
def dot(self, v, out=None):
"""Solves the 2x2 block matrix linear system.

Expand Down Expand Up @@ -346,6 +349,7 @@ def __init__(self, M, solver_name, **solver_params):
self._rhs2 = self._A.codomain.zeros()

@profile
@ProfileManager.profile("solve: SchurSolverFull3")
def dot(self, v, out=None):
"""Solves the 3x3 block matrix linear system.

Expand Down
1 change: 0 additions & 1 deletion src/struphy/models/tests/utils_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def call_test(model: StruphyModel, test_profiling: bool = False):
out_folders=test_folder,
sim_folder=f"{model_name}",
profiling_activated=test_profiling,
profiling_trace=test_profiling,
)

# read parameters
Expand Down
2 changes: 2 additions & 0 deletions src/struphy/ode/solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cunumpy as xp
from feectools.linalg.block import BlockVector
from feectools.linalg.stencil import StencilVector
from scope_profiler import ProfileManager

from struphy.ode.utils import ButcherTableau

Expand Down Expand Up @@ -59,6 +60,7 @@ def __init__(
self._yn = [v.copy() for v in self.y]
self._ystar = [v.copy() for v in self.y]

@ProfileManager.profile("solve: ODEsolverFEEC")
def __call__(self, tn, h):
a = self.butcher.a
b = self.butcher.b
Expand Down
Loading
Loading