Adding an Experiment

Glossary terms: Benchmark, Package, Application, Spec, Variant, Experiment, System, Modifier, Scaling Study

Create either missing prerequisite before adding the experiment:

This guide is intended for developers who want to add the ability to run a benchmark with Benchpark. Once a Spack package.py and Ramble application.py describe how to build and run the benchmark, the next step is creating its experiment.py. This guide demonstrates that process for HPL.

Create the Experiment Definition

This example defines the HPL experiment used throughout the Beginner Tutorial. Replace experiments/hpl/experiment.py with the below definition:

 1# Copyright 2023 Lawrence Livermore National Security, LLC and other
 2# Benchpark Project Developers. See the top-level COPYRIGHT file for details.
 3#
 4# SPDX-License-Identifier: Apache-2.0
 5
 6from benchpark.experiment import Experiment
 7# Step 1 adds the programming-model import here.
 8from benchpark.caliper import Caliper
 9from benchpark.directives import variant, maintainers
10from benchpark.scaling import Scaling, ScalingMode
11
12
13class Hpl(
14    Experiment,
15    # Step 1 adds the supported programming models here.
16    Caliper,
17    Scaling(ScalingMode.Strong, ScalingMode.Weak),
18):
19    variant(
20        "workload",
21        default="standard",
22        description="Which ramble workload to execute.",
23    )
24
25    # Step 2 adds the version variant here.
26
27    maintainers("daboehme")
28
29    def compute_applications_section(self):
30
31        if self.spec.satisfies("exec_mode=test"):
32            self.add_experiment_variable("n_ranks", 1, True)
33            self.add_experiment_variable("Ns", 1000, True)
34            self.add_experiment_variable("N-Grids", 1, False)
35            self.add_experiment_variable("Ps", "{n_ranks}", True)
36            self.add_experiment_variable("Qs", "1", False)
37            self.add_experiment_variable("N-Ns", 1, False)
38            self.add_experiment_variable("N-NBs", 1, False)
39            self.add_experiment_variable("NBs", 128, False)
40
41        # Step 3 adds the exec_mode=perf else block here.
42
43        # Step 4 adds the required-variable definitions here.
44
45        self.register_scaling_config(
46            {
47                ScalingMode.Strong: {
48                    "n_ranks": lambda var, itr, dim, scaling_factor: (
49                        var.val(dim) * scaling_factor
50                    ),
51                    "Ns": lambda var, itr, dim, scaling_factor: var.val(dim),
52                },
53                ScalingMode.Weak: {
54                    "n_ranks": lambda var, itr, dim, scaling_factor: (
55                        var.val(dim) * scaling_factor
56                    ),
57                    "Ns": lambda var, itr, dim, scaling_factor: (
58                        var.val(dim) * scaling_factor
59                    ),
60                },
61            }
62        )
63
64    def compute_package_section(self):
65        self.add_package_spec(self.name, [f"hpl{self.determine_version()}"])

1. Add Programming Models

Programming models specify how the source code parallelizes the benchmark. Replace the first Step 1 placeholder with the programming-model import:

from benchpark.programming_model import ProgrammingModel, ProgrammingModelType

Replace the second Step 1 placeholder in the Hpl class bases with the supported MPI and OpenMP programming models:

ProgrammingModel(ProgrammingModelType.Mpionly, ProgrammingModelType.Openmp),

2. Add the Version Variant

The version variant will enable us to build and run the source code versions specified in the benchmark’s Spack package. For HPL, 2.3-caliper, 2.3 and 2.2 are defined in repos/spack_repo/benchpark/packages/hpl/package.py. The latest value is a Benchpark keyword that selects the newest version defined by the Spack package.

Replace the Step 2 placeholder with the complete version variant:

variant(
    "version",
    default="2.3-caliper",
    values=("latest", "2.3-caliper", "2.3", "2.2"),
    description="Which benchmark version to use.",
)

3. Add a Performance Mode

The exec_mode=test experiment definition provides small values for the problem size and number of ranks, suitable for short CI runs. Replace the Step 3 placeholder with the following else branch to define a set of larger experiment variables for collecting performance data:

# Must be exec_mode=perf if not test mode.
else:
    self.add_experiment_variable("n_ranks", 32, True)
    self.add_experiment_variable("Ns", 100000, True)
    self.add_experiment_variable("N-Grids", 1, False)
    self.add_experiment_variable("Ps", "({n_ranks} // 8)", True)
    self.add_experiment_variable("Qs", "8", False)
    self.add_experiment_variable("N-Ns", 1, False)
    self.add_experiment_variable("N-NBs", 1, False)
    self.add_experiment_variable("NBs", 128, False)

4. Set Required Variables

We record the problem sizes for each experiment, and the resources the experiment requires. Replace the Step 4 placeholder with the following call, which defines the number of ranks, the HPL problem size per rank, and the total HPL problem size:

# Set the variables required by the experiment
self.set_required_variables(
    n_resources="{n_ranks}",
    process_problem_size="{Ns}/{n_ranks}",
    total_problem_size="{Ns}",
)

For the complete experiment authoring reference, see Adding an Experiment.

Next Step