Skip to content

Commit

Permalink
add tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
jdolence committed Nov 7, 2023
1 parent 0b13b20 commit 6cf5bc0
Show file tree
Hide file tree
Showing 16 changed files with 298 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ option(PARTHENON_DISABLE_HDF5 "HDF5 is enabled by default if found, set this to
option(PARTHENON_DISABLE_HDF5_COMPRESSION "HDF5 compression is enabled by default, set this to True to disable compression in HDF5 output/restart files" OFF)
option(PARTHENON_DISABLE_SPARSE "Sparse capability is enabled by default, set this to True to compile-time disable all sparse capability" OFF)
option(PARTHENON_ENABLE_LB_TIMERS "Timer-based load balancing is disabled by default, set this to True to enable timers" OFF)
option(PARTHENON_ENABLE_TRACE "Tracing is disabled by default, set to ON to enable tracing" OFF)
option(PARTHENON_ENABLE_ASCENT "Enable Ascent for in situ visualization and analysis" OFF)
option(PARTHENON_LINT_DEFAULT "Linting is turned off by default, use the \"lint\" target or set \
this to True to enable linting in the default target" OFF)
Expand Down Expand Up @@ -138,6 +139,11 @@ if (PARTHENON_ENABLE_LB_TIMERS)
set(ENABLE_LB_TIMERS ON)
endif()

set(ENABLE_TRACE OFF)
if (PARTHENON_ENABLE_TRACE)
set(ENABLE_TRACE ON)
endif()

set(ENABLE_HDF5 OFF)
if (NOT PARTHENON_DISABLE_HDF5)
set(HDF5_PREFER_PARALLEL ${ENABLE_MPI})
Expand Down
168 changes: 168 additions & 0 deletions scripts/python/packages/parthenon_plot_trace/plot_trace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import sys
import re
import matplotlib.pyplot as plt
import itertools
from collections import OrderedDict
from argparse import ArgumentParser

parser = ArgumentParser(prog="plot_trace", description="Plot parthenon tracer output")

parser.add_argument(
"--start",
dest="step_start",
type=int,
default=-1,
help="First step to include",
)

parser.add_argument(
"--stop",
dest="step_stop",
type=int,
default=-1,
help="Final step to include (inclusive)",
)

parser.add_argument("files", type=str, nargs="+", help="trace files to plot")


class Region:
def __init__(self):
self.start = []
self.duration = []

def add_samples(self, line):
words = line.split()
start = float(words[0])
stop = float(words[1])
self.start.append(start)
self.duration.append(stop - start)

def trim(self, tstart, tstop):
istart = 0
istop = 0
set_start = False
set_stop = False
for i in range(len(self.start)):
if not set_start and self.start[i] > tstart:
istart = i
set_start = True
if not set_stop and self.start[i] + self.duration[i] > tstop:
istop = i
set_stop = True
if set_start and set_stop:
break
if not set_stop:
istop = len(self.start)
if not set_start:
istart = istop
self.start = self.start[istart:istop]
self.duration = self.duration[istart:istop]


class Trace:
def __init__(self, name, step_start, step_stop):
self.step_start = step_start
self.step_stop = step_stop
self.rank = int(re.search("trace_(.*).txt", name).group(1))
with open(name) as f:
data = f.readlines()
self.regions = {}
current_region = ""
for line in data:
l = line.rstrip()
words = l.split()
if words[0] == "Region:":
if words[1] == "StepTimer":
reg_name = words[1]
self.regions[reg_name] = Region()
current_region = reg_name
continue
else:
fstr = l[l.find("::") + 2 :]
reg_name = fstr[fstr.find(":") + 2 :]
self.regions[reg_name] = Region()
current_region = reg_name
continue
self.regions[current_region].add_samples(line)
step_start_time = 0.0
step_stop_time = 999999.0
if step_start > 0:
if step_start < len(self.regions["StepTimer"].start):
step_start_time = self.regions["StepTimer"].start[step_start]
if step_stop > -1 and step_stop < len(self.regions["StepTimer"].start):
step_stop_time = (
self.regions["StepTimer"].start[step_stop]
+ self.regions["StepTimer"].duration[step_stop]
)
for key, val in self.regions.items():
if key == "StepTimer":
continue
val.trim(step_start_time, step_stop_time)

def region_names(self):
return list(self.regions.keys())

def plot_trace(self, ax, colorMap, hatchMap):
for key, val in self.regions.items():
if key == "StepTimer":
continue
ax.barh(
self.rank,
val.duration,
left=val.start,
height=0.5,
label=key,
color=colorMap[key],
hatch=hatchMap[key],
)


def main(files, step_start, step_stop):
trace = []
for f in files:
print("Getting trace", f, end="")
trace.append(Trace(f, step_start, step_stop))
print(" done!")
# get max number of functions
all_funcs = OrderedDict()
for t in trace:
for key in t.region_names():
all_funcs[key] = ""

num_colors = len(all_funcs)
cm = plt.get_cmap("tab20")
hatch = ["", "--", "/", "\\", "+", "x"]
num_hatches = len(hatch)
colorMap = {}
hatchMap = {}
cindex = 0
for f, dum in all_funcs.items():
colorMap[f] = cm((cindex + 0.5) / num_colors)
hatchMap[f] = hatch[cindex % num_hatches]
cindex += 1
fig, ax = plt.subplots(figsize=(18, 12))
for t in trace:
print("Plotting trace", t.rank, end="")
t.plot_trace(ax, colorMap, hatchMap)
print(" done!")
plt.xlabel("Time (s)")
plt.ylabel("Rank")
# box = ax.get_position()
# ax.set_position([box.x0, box.y0 + box.height*0.2, box.width, box.height * 0.8])
handles, labels = plt.gca().get_legend_handles_labels()
by_label = OrderedDict(zip(labels, handles))
ax.legend(
by_label.values(),
by_label.keys(),
loc="upper center",
bbox_to_anchor=(0, -0.02, 1, -0.02),
ncol=3,
)
plt.tight_layout()
plt.show()


if __name__ == "__main__":
args = parser.parse_args()
main(args.files, args.step_start, args.step_stop)
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ add_library(parthenon
utils/error_checking.cpp
utils/hash.hpp
utils/indexer.hpp
utils/instrument.cpp
utils/instrument.hpp
utils/loop_utils.hpp
utils/morton_number.hpp
Expand Down
2 changes: 2 additions & 0 deletions src/amr_criteria/refinement_package.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,15 @@ void SetRefinement_(MeshBlockData<Real> *rc) {

template <>
TaskStatus Tag(MeshBlockData<Real> *rc) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
SetRefinement_(rc);
return TaskStatus::complete;
}

template <>
TaskStatus Tag(MeshData<Real> *rc) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
for (int i = 0; i < rc->NumBlocks(); i++) {
SetRefinement_(rc->GetBlockData(i).get());
Expand Down
1 change: 1 addition & 0 deletions src/bvals/boundary_conditions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ TaskStatus ApplyBoundaryConditionsMD(std::shared_ptr<MeshData<Real>> &pmd) {

TaskStatus ApplyBoundaryConditionsOnCoarseOrFineMD(std::shared_ptr<MeshData<Real>> &pmd,
bool coarse) {
PARTHENON_TRACE
for (int b = 0; b < pmd->NumBlocks(); ++b)
ApplyBoundaryConditionsOnCoarseOrFine(pmd->GetBlockData(b), coarse);
return TaskStatus::complete;
Expand Down
5 changes: 5 additions & 0 deletions src/bvals/comms/boundary_communication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ using namespace loops::shorthands;

template <BoundaryType bound_type>
TaskStatus SendBoundBufs(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down Expand Up @@ -169,6 +170,7 @@ SendBoundBufs<BoundaryType::nonlocal>(std::shared_ptr<MeshData<Real>> &);

template <BoundaryType bound_type>
TaskStatus StartReceiveBoundBufs(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
Mesh *pmesh = md->GetMeshPointer();
auto &cache = md->GetBvarsCache().GetSubCache(bound_type, false);
Expand All @@ -191,6 +193,7 @@ StartReceiveBoundBufs<BoundaryType::nonlocal>(std::shared_ptr<MeshData<Real>> &)

template <BoundaryType bound_type>
TaskStatus ReceiveBoundBufs(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down Expand Up @@ -235,6 +238,7 @@ ReceiveBoundBufs<BoundaryType::nonlocal>(std::shared_ptr<MeshData<Real>> &);

template <BoundaryType bound_type>
TaskStatus SetBounds(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down Expand Up @@ -319,6 +323,7 @@ template TaskStatus SetBounds<BoundaryType::nonlocal>(std::shared_ptr<MeshData<R

template <BoundaryType bound_type>
TaskStatus ProlongateBounds(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down
4 changes: 4 additions & 0 deletions src/bvals/comms/flux_correction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace parthenon {
using namespace impl;

TaskStatus LoadAndSendFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down Expand Up @@ -118,6 +119,7 @@ TaskStatus LoadAndSendFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
}

TaskStatus StartReceiveFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
Mesh *pmesh = md->GetMeshPointer();
auto &cache = md->GetBvarsCache().GetSubCache(BoundaryType::flxcor_recv, false);
Expand All @@ -132,6 +134,7 @@ TaskStatus StartReceiveFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
}

TaskStatus ReceiveFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand All @@ -150,6 +153,7 @@ TaskStatus ReceiveFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
}

TaskStatus SetFluxCorrections(std::shared_ptr<MeshData<Real>> &md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT

Mesh *pmesh = md->GetMeshPointer();
Expand Down
3 changes: 3 additions & 0 deletions src/config.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
// define ENABLE_LB_TIMERS or not at all
#cmakedefine ENABLE_LB_TIMERS

// define ENABLE_TRACE or not at all
#cmakedefine ENABLE_TRACE

// define PARTHENON_ENABLE_ASCENT or not at all
#cmakedefine PARTHENON_ENABLE_ASCENT

Expand Down
3 changes: 3 additions & 0 deletions src/driver/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ DriverStatus EvolutionDriver::Execute() {
{ // Main t < tmax loop region
PARTHENON_INSTRUMENT
while (tm.KeepGoing()) {
PARTHENON_TRACE_REGION("StepTimer")
if (Globals::my_rank == 0) OutputCycleDiagnostics();

pmesh->PreStepUserWorkInLoop(pmesh, pinput, tm);
Expand Down Expand Up @@ -160,6 +161,7 @@ void EvolutionDriver::PostExecute(DriverStatus status) {
}

void EvolutionDriver::InitializeBlockTimeStepsAndBoundaries() {
PARTHENON_TRACE
// calculate the first time step using Block function
for (auto &pmb : pmesh->block_list) {
Update::EstimateTimestep(pmb->meshblock_data.Get().get());
Expand All @@ -180,6 +182,7 @@ void EvolutionDriver::InitializeBlockTimeStepsAndBoundaries() {
// \brief function that loops over all MeshBlocks and find new timestep

void EvolutionDriver::SetGlobalTimeStep() {
PARTHENON_TRACE
// don't allow dt to grow by more than 2x
// consider making this configurable in the input
if (tm.dt < 0.1 * std::numeric_limits<Real>::max()) {
Expand Down
9 changes: 9 additions & 0 deletions src/interface/update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace Update {

template <>
TaskStatus FluxDivergence(MeshBlockData<Real> *in, MeshBlockData<Real> *dudt_cont) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
std::shared_ptr<MeshBlock> pmb = in->GetBlockPointer();

const IndexDomain interior = IndexDomain::interior;
Expand All @@ -61,6 +63,8 @@ TaskStatus FluxDivergence(MeshBlockData<Real> *in, MeshBlockData<Real> *dudt_con

template <>
TaskStatus FluxDivergence(MeshData<Real> *in_obj, MeshData<Real> *dudt_obj) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
const IndexDomain interior = IndexDomain::interior;

std::vector<MetadataFlag> flags({Metadata::WithFluxes, Metadata::Cell});
Expand Down Expand Up @@ -88,6 +92,8 @@ template <>
TaskStatus UpdateWithFluxDivergence(MeshBlockData<Real> *u0_data,
MeshBlockData<Real> *u1_data, const Real gam0,
const Real gam1, const Real beta_dt) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
std::shared_ptr<MeshBlock> pmb = u0_data->GetBlockPointer();

const IndexDomain interior = IndexDomain::interior;
Expand Down Expand Up @@ -116,6 +122,8 @@ template <>
TaskStatus UpdateWithFluxDivergence(MeshData<Real> *u0_data, MeshData<Real> *u1_data,
const Real gam0, const Real gam1,
const Real beta_dt) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
const IndexDomain interior = IndexDomain::interior;

std::vector<MetadataFlag> flags({Metadata::WithFluxes, Metadata::Cell});
Expand All @@ -141,6 +149,7 @@ TaskStatus UpdateWithFluxDivergence(MeshData<Real> *u0_data, MeshData<Real> *u1_
}

TaskStatus SparseDealloc(MeshData<Real> *md) {
PARTHENON_TRACE
PARTHENON_INSTRUMENT
if (!Globals::sparse_config.enabled || (md->NumBlocks() == 0)) {
return TaskStatus::complete;
Expand Down
Loading

0 comments on commit 6cf5bc0

Please sign in to comment.