Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/new modifier implementation #356

Open
wants to merge 35 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f5d42ea
Add initial framework for experiment init
alecbcs Aug 22, 2024
eaf72d0
saxpy: fix mismatch between variable name and usage
becker33 Aug 22, 2024
19a9cfd
cmd/experiment: fix interface to Experiment class
becker33 Aug 22, 2024
0823c12
cmd/experiment: implement benchpark experiment list
becker33 Aug 22, 2024
d80ecef
cmd/experiment: remove vestigial references to 'system'
becker33 Aug 22, 2024
7b9c2e2
spec: fix bug with ConcreteSpec.satisfies and ConcreteSpec.intersects
becker33 Aug 22, 2024
7c6f80c
spec: remove vestigial 'autospec' decorator
becker33 Aug 22, 2024
2238ac1
Merge branch 'develop' of github.com:LLNL/benchpark into develop
Aug 22, 2024
7c46969
Add amg2023 experiment.py
Aug 24, 2024
0c0bbd3
Fix formatting
Aug 24, 2024
0c46273
Changes to spack section
Aug 25, 2024
7bff318
Fix formatting
Aug 25, 2024
2de749d
Add caliper support
Aug 26, 2024
b0baff3
Merge remote-tracking branch 'origin/develop' into feature/amg2023-ex…
Aug 26, 2024
56b4737
Changes
Aug 26, 2024
fdfce26
Fixes
Aug 26, 2024
0dc3af8
Fix formatting
Aug 26, 2024
f33103d
Fix cali file name
Aug 26, 2024
54347d5
Remove redundant caliper modifier implementations
Aug 27, 2024
d7a6125
Remove modifier references in main.py
Aug 27, 2024
00c86fa
Fix formatting
Aug 27, 2024
6298921
Remove modifier.yaml config options
Aug 27, 2024
dd30ad5
Merge remote-tracking branch 'origin/develop' into feature/new-modifi…
Aug 27, 2024
4a28b43
Merge with develop
Sep 17, 2024
2fc1408
Allow caliper variant to assume multiple values
Sep 18, 2024
fa2e096
Reinstate old-format modifier definitions
Sep 18, 2024
98b1789
Merge remote-tracking branch 'origin/develop' into feature/new-modifi…
Sep 19, 2024
73cf307
Add caliper modifier experiment
Sep 20, 2024
7c9bb91
Fix lint formatting
Sep 20, 2024
0dabe54
Merge branch 'develop' into feature/new-modifier-implementation
pearce8 Sep 20, 2024
e9ed483
Make time as the default mode
Sep 23, 2024
122fe00
Add license
Sep 24, 2024
1602e0c
Merge remote-tracking branch 'origin/develop' into feature/new-modifi…
Sep 24, 2024
fb2ec64
Merge with develop
Oct 18, 2024
bb8abb7
Merge remote-tracking branch 'origin/develop' into feature/new-modifi…
Oct 18, 2024
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
65 changes: 61 additions & 4 deletions modifiers/caliper/modifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
from ramble.modkit import *


def add_mode(mode_name, mode_option, description):
mode(
name=mode_name,
description=description,
)

env_var_modification(
"CALI_CONFIG_MODE",
mode_option,
method="append",
separator=",",
modes=[mode_name],
)


class Caliper(SpackModifier):
"""Define a modifier for Caliper"""

Expand All @@ -15,15 +30,57 @@ class Caliper(SpackModifier):

maintainers("pearce8")

mode("time", description="Platform-independent collection of time")

_cali_datafile = "{experiment_run_dir}/{experiment_name}.cali"

_default_mode = "time"

add_mode(
mode_name=_default_mode,
mode_option="time.exclusive",
description="Platform-independent collection of time (default mode)",
)

env_var_modification(
"CALI_CONFIG",
"spot(output={})".format(_cali_datafile),
"spot(output={}{})".format(_cali_datafile, "${CALI_CONFIG_MODE}"),
method="set",
modes=["time"],
modes=[_default_mode],
)

add_mode(
mode_name="mpi",
mode_option="profile.mpi",
description="Profile MPI functions",
)

add_mode(
mode_name="cuda",
mode_option="profile.cuda",
description="Profile CUDA API functions",
)

add_mode(
mode_name="topdown-counters-all",
mode_option="topdown-counters.all",
description="Raw counter values for Intel top-down analysis (all levels)",
)

add_mode(
mode_name="topdown-counters-toplevel",
mode_option="topdown-counters.toplevel",
description="Raw counter values for Intel top-down analysis (top level)",
)

add_mode(
mode_name="topdown-all",
mode_option="topdown.all",
description="Top-down analysis for Intel CPUs (all levels)",
)

add_mode(
mode_name="topdown-toplevel",
mode_option="topdown.toplevel",
description="Top-down analysis for Intel CPUs (top level)",
)

archive_pattern(_cali_datafile)
Expand Down
39 changes: 35 additions & 4 deletions var/exp_repo/experiments/amg2023/experiment.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from benchpark.directives import variant
from benchpark.experiment import Experiment
from benchpark.expr.builtin.caliper import Caliper


class Amg2023(Experiment):
class Amg2023(Caliper, Experiment):
variant(
"programming_model",
default="openmp",
Expand All @@ -23,6 +24,18 @@ class Amg2023(Experiment):
description="type of experiment",
)

# TODO: Support list of 3-tuples
# variant(
# "p",
# description="value of p",
# )

# TODO: Support list of 3-tuples
# variant(
# "n",
# description="value of n",
# )

def make_experiment_example(self):
app_name = self.spec.name

Expand Down Expand Up @@ -101,6 +114,11 @@ def make_experiment_example(self):
}
}

def compute_modifiers_section(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a suggestion for refactoring this to make it easier to add analogs to caliper:

  • Experiment.__init__ (in the base class Experiment) calls Experiment.initialize
  • Move all functionality in caliper.Caliper except for variant declaration into caliper.Helper
  • Amg2023.initialize sets helpers = [caliper.Helper()]
  • Experiment (the base class) handles tacking on extra modifiers from all .helpers
    • It can also take care of caliper_package_specs

The benefit of this organization is that you can add more functionality (that defines other modifiers/specs) without having to modify functions in this class other than .initialize.

return Experiment.compute_modifiers_section(
self
) + Caliper.compute_modifiers_section(self)

def compute_applications_section(self):
if self.spec.satisfies("workload=problem1"):
self.workload = "problem1"
Expand All @@ -124,7 +142,6 @@ def compute_spack_section(self):
# set package versions
app_version = "develop"
hypre_version = "2.31.0"
# caliper_version = "master"

# get system config options
# TODO: Get compiler/mpi/package handles directly from system.py
Expand Down Expand Up @@ -171,6 +188,14 @@ def compute_spack_section(self):
"compiler": system_specs["compiler"],
}

caliper_package_specs = Caliper.compute_spack_section(self)
if Caliper.is_enabled(self):
package_specs["hypre"]["pkg_spec"] += "+caliper"
package_specs[app_name]["pkg_spec"] += "+caliper"
else:
package_specs["hypre"]["pkg_spec"] += "~caliper"
package_specs[app_name]["pkg_spec"] += "~caliper"

if self.spec.satisfies("programming_model=openmp"):
package_specs["hypre"]["pkg_spec"] += "+openmp"
package_specs[app_name]["pkg_spec"] += "+openmp"
Expand All @@ -190,6 +215,12 @@ def compute_spack_section(self):
)

return {
"packages": {k: v for k, v in package_specs.items() if v},
"environments": {app_name: {"packages": list(package_specs.keys())}},
"packages": {k: v for k, v in package_specs.items() if v}
| caliper_package_specs["packages"],
"environments": {
app_name: {
"packages": list(package_specs.keys())
+ list(caliper_package_specs["packages"].keys())
}
},
}
94 changes: 94 additions & 0 deletions var/exp_repo/experiments/caliper/experiment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2023 Lawrence Livermore National Security, LLC and other
# Benchpark Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: Apache-2.0


from benchpark.directives import variant
from benchpark.experiment import Experiment


class Caliper(Experiment):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(suggestion, not a problem) IIRC you mentioned that caliper would never be instantiated as an experiment itself. FWIW, this could move from var/exp_repo/experiments/caliper/ to lib/benchpark, possibly into a new subdir like lib/benchpark/experiment_addons

variant(
"caliper",
default="none",
values=(
"none",
"time",
"mpi",
"cuda",
"topdown-counters-all",
"topdown-counters-toplevel",
"topdown-all",
"topdown-toplevel",
),
multi=True,
description="caliper mode",
)

def is_enabled(self):
return not self.spec.satisfies("caliper=none")

def compute_modifiers_section(self):
modifier_list = []
if not self.spec.satisfies("caliper=none"):
for var in list(self.spec.variants["caliper"]):
if var != "time":
caliper_modifier_modes = {}
caliper_modifier_modes["name"] = "caliper"
caliper_modifier_modes["mode"] = var
modifier_list.append(caliper_modifier_modes)
# Add time as the last mode
modifier_list.append({"name": "caliper", "mode": "time"})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(question) When you mentioned having to order things yourself, is this what you mean?

In a separate conversation, you mention that this is so "In this case, the time mode is always added last to the modifier list which adds the CALI_CONFIG variable after each of the CALI_CONFIG_MODE variables have been defined. "

I'm not clear on how this achieves that. Is time the only modifier mode that defines CALI_CONFIG?

return modifier_list

def compute_spack_section(self):
# set package versions
caliper_version = "master"

# get system config options
# TODO: Get compiler/mpi/package handles directly from system.py
system_specs = {}
system_specs["compiler"] = "default-compiler"
if self.spec.satisfies("programming_model=cuda"):
system_specs["cuda_arch"] = "{cuda_arch}"
if self.spec.satisfies("programming_model=rocm"):
system_specs["rocm_arch"] = "{rocm_arch}"

# set package spack specs
package_specs = {}

if not self.spec.satisfies("caliper=none"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the impression that some combinations of caliper=... are not allowed. I don't know if we support conflict yet, but FWIW you can raise an exception here for forbidden combinations.

package_specs["caliper"] = {
"pkg_spec": f"caliper@{caliper_version}+adiak+mpi~libunwind~libdw",
"compiler": system_specs["compiler"],
}
if any("topdown" in var for var in self.spec.variants["caliper"]):
papi_support = True # check if target system supports papi
if papi_support:
package_specs["caliper"]["pkg_spec"] += "+papi"
else:
raise NotImplementedError(
"Target system does not support the papi interface"
)
elif self.spec.satisfies("caliper=cuda"):
cuda_support = (
self.spec.satisfies("caliper=cuda") and True
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and True looks vestigial

) # check if target system supports cuda
if cuda_support:
package_specs["caliper"][
"pkg_spec"
] += "~papi+cuda cuda_arch={}".format(system_specs["cuda_arch"])
else:
raise NotImplementedError(
"Target system does not support the cuda interface"
)
elif self.spec.satisfies("caliper=time") or self.spec.satisfies(
"caliper=mpi"
):
package_specs["caliper"]["pkg_spec"] += "~papi"

return {
"packages": {k: v for k, v in package_specs.items() if v},
"environments": {"caliper": {"packages": list(package_specs.keys())}},
}