Skip to content

Commit

Permalink
phlop runtime process monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilipDeegan committed Aug 10, 2024
1 parent 5933e40 commit 6853bc9
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 10 deletions.
52 changes: 52 additions & 0 deletions pyphare/pyphare/simulator/monitoring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import os

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'os' is not used.

from pathlib import Path


def have_phlop():
try:
from phlop.dict import ValDict

return True
except ImportError:
...

Check notice

Code scanning / CodeQL

Statement has no effect Note

This statement has no effect.
return False


def valdict(**kwargs):
if not have_phlop():
return dict

from phlop.dict import ValDict

return ValDict(**kwargs)


_globals = valdict(stats_man=None)


def monitoring_yaml_file(cpplib):
path = Path(".phare") / "stats" / f"rank.{cpplib.mpi_rank()}.yaml"
path.parent.mkdir(exist_ok=True, parents=True)
return path


def setup_monitoring(cpplib, interval=10):
if not have_phlop():
return

from phlop.app import stats_man as sm

_globals.stats_man = sm.AttachableRuntimeStatsManager(
valdict(yaml=monitoring_yaml_file(cpplib), interval=interval),
dict(rank=cpplib.mpi_rank()),
).start()


def monitoring_shutdown(cpplib):
if not have_phlop():
return
from phlop.app import stats_man as sm

if _globals.stats_man:
_globals.stats_man.kill().join()
10 changes: 8 additions & 2 deletions pyphare/pyphare/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import time as timem
import numpy as np
import pyphare.pharein as ph
from . import monitoring as mon


life_cycles = {}
Expand Down Expand Up @@ -127,6 +128,7 @@ def initialize(self):

self.cpp_sim.initialize()
self._auto_dump() # first dump might be before first advance

return self
except:
import sys
Expand All @@ -140,7 +142,6 @@ def initialize(self):

def _throw(self, e):
import sys
from pyphare.cpp import cpp_lib

print_rank0(e)
sys.exit(1)
Expand Down Expand Up @@ -170,12 +171,16 @@ def times(self):
self.timeStep(),
)

def run(self, plot_times=False):
def run(self, plot_times=False, monitoring=True):
"""monitoring requires phlop"""
from pyphare.cpp import cpp_lib

self._check_init()

if self.simulation.dry_run:
return self
if monitoring:
mon.setup_monitoring(cpp_lib())
perf = []
end_time = self.cpp_sim.endTime()
t = self.cpp_sim.currentTime()
Expand All @@ -197,6 +202,7 @@ def run(self, plot_times=False):
if plot_times:
plot_timestep_time(perf)

mon.monitoring_shutdown(cpp_lib())
return self.reset()

def _auto_dump(self):
Expand Down
2 changes: 0 additions & 2 deletions src/simulator/simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,6 @@ double Simulator<_dimension, _interp_order, _nbRefinedPart>::advance(double dt)

try
{
PHARE_LOG_SCOPE(1, "Simulator::advance");

dt_new = integrator_->advance(dt);
currentTime_ = startTime_ + ((*timeStamper) += dt);
}
Expand Down
16 changes: 11 additions & 5 deletions tools/python3/phloping.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from dataclasses import dataclass, field

from pyphare.pharesee.run import Run
from pyphare.pharesee.hierarchy import hierarchy_from

from phlop.timing.scope_timer import ScopeTimerFile as phScopeTimerFile
from phlop.timing.scope_timer import file_parser as phfile_parser
Expand Down Expand Up @@ -124,17 +123,24 @@ def normalised_times_for_L(self, ilvl):
"""
Normalise substep time against particle count for that level
at the most recent coarse time, no refined timesteps
Particle counts may include init dump, so be one bigger.
"""
times = self.advance_times_for_L(ilvl)
counts = len(self.particles_per_level_per_time_step[ilvl])

# trim init particle count for lvl
Li_times = (
self.particles_per_level_per_time_step[ilvl]
if counts == len(times)
else self.particles_per_level_per_time_step[ilvl][1:]
)
if ilvl == 0:
return times / self.particles_per_level_per_time_step[0]
return times / Li_times
substeps = self.steps_per_coarse_timestep_for_L(ilvl)
norm_times = times.copy()
return (
norm_times.reshape(int(times.shape[0] / substeps), substeps)
/ self.particles_per_level_per_time_step[ilvl].reshape(
self.particles_per_level_per_time_step[ilvl].shape[0], 1
)
/ Li_times.reshape(Li_times.shape[0], 1)
).reshape(times.shape[0])


Expand Down
2 changes: 1 addition & 1 deletion tools/python3/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def plot_run_timer_data(diag_dir=None, rank=0):
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dir", default=".", help="Diagnostics directory")
diag_dir = parser.parse_args().dir
run = Run(diag_dir, single_hier_for_all_quantities=True)
run = Run(diag_dir)
res = phloping.file_parser(run, rank, Path(f".phare_times.{rank}.txt"))
fig, ax = plt.subplots()
L0X = res.time_steps_for_L(0)
Expand Down

0 comments on commit 6853bc9

Please sign in to comment.