2) Writing an HPL application definition
This tutorial will provide an introduction to writing a more complex application definition in Ramble. In this tutorial, you will create and test an application definition file to run the High-Performance Linpack (HPL) benchmark.
This tutorial builds on the concepts introduced in the Basic Application Tutorial and introduces new concepts such as software dependencies and input file templating.
It is a good idea to have a basic working understanding of how to create and use Ramble workspaces before starting this tutorial. You should at least be familiar with the content of the Hello World Tutorial.
Installation
To install Ramble, see the Getting Started guide.
NOTE: This tutorial requires a package manager to be installed and configured to build HPL. For the purposes of this tutorial, we will focus on Spack. You will need a working Spack installation and configuration on your system for this tutorial. For more information on Spack installation or usage, please refer to the official Spack documentation. Ramble will leverage your configured Spack instance during the workspace setup stage to build HPL.
Ramble Repositories
Before writing our application definition, we will create a repository to house the application definition.
$ ramble repo create tutorial-repo
This will create a new directory named tutorial-repo in your current
directory. Inside, directories will exist for each of the object types.
Once your repository is created, you can register it with Ramble by issuing the following command:
$ ramble repo add tutorial-repo
HPL Application Definition
For the remainder of this tutorial, we will be writing and testing the contents of the HPL application definition.
Create Application Definition
To begin with, we will create an empty application definition file and a placeholder for our input file template. These will live in the same directory.
$ mkdir -p tutorial-repo/applications/hpl/templates
$ touch tutorial-repo/applications/hpl/application.py
$ touch tutorial-repo/applications/hpl/templates/HPL.dat.tpl
For the remainder of this tutorial, ramble edit hpl will open this
file with the editor specified with your EDITOR environment variable.
Application Class
Following the description of the application class in the Basic Application Tutorial, the following can be used as the beginning of our HPL application definition.
from ramble.appkit import *
class Hpl(ExecutableApplication):
name = 'hpl'
At this stage, our application should show up in the output of ramble list
and ramble info hpl should show limited information about this application.
Software Specification
Unlike the hostname utility, HPL is not typically pre-installed. We need to
tell Ramble how to build it. We can do this using the software_spec
directive. This directive takes a Spack spec to define the
software and its dependencies.
with when("package_manager_family=spack"):
software_spec(name="hpl", pkg_spec="hpl@2.3")
This tells Ramble to use Spack to install HPL version 2.3. The with when(...)
construct makes these directives conditional on the package manager being used.
NOTE: By default, Spack will be allowed to select any MPI implementation it
wants for this installation. Application definitions can optionally define
additional software_specs to further control the default software stack for
applications.
Input File Template
HPL requires an HPL.dat input file to run. Ramble has directives for
downloading input files from websites. However, given this is a basic text
file, Ramble can generate this file from a template. We use the
register_template directive to tell Ramble how to generate this file for
us.
register_template(
"hpl.dat.in",
template_file="templates/HPL.dat.tpl",
destination="HPL.dat"
)
Now, let’s populate the template file
tutorial-repo/applications/hpl/templates/HPL.dat.tpl. We can refer to any
workload variables we are going to add into the application definition using
curly brace syntax. When Ramble renders this file into the experiment
directory, these values will be expanded for us.
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
{Ns} Ns
1 # of NBs
{NBs} NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
{Ps} Ps
{Qs} Qs
16.0 threshold
1 # of panel fact
2 PFACTs (0=left, 1=Crout, 2=Right)
1 # of recursive stopping criterium
4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
1 # of recursive panel fact.
1 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
1 DEPTHs (>= 0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
Definition Experiment Constructs
Now we will define the executable and workload for HPL.
Application Executables
HPL is an MPI application. We will define an executable that runs xhpl, the
HPL executable. We’ll set use_mpi=True to tell Ramble to prepend the
workspace’s MPI command to this executable. This allows users to run it with an
MPI launcher like mpirun or srun.
executable(
"hpl-execute",
"xhpl",
use_mpi=True,
)
Application Workloads
Here, we’ll create a default workload that uses our executable. Given our input file is generated from a template, we do not need to list it in the workload specification.
workload(
"default",
executables=["hpl-execute"],
)
Workload Variables
Now that we have a workload defined, we can define the variables that we added
into our template input file (e.g. {Ns}). We need to define them in our
application definition using the workload_variable directive so users can
set them.
workload_variable("Ns", default=1000, description="Problem size", workload="default")
workload_variable("NBs", default=256, description="Block size", workload="default")
workload_variable("Ps", default=1, description="Number of process rows", workload="default")
workload_variable("Qs", default=1, description="Number of process columns", workload="default")
Analysis of experiments
Ramble can analyze experiment output to extract performance metrics and determine success or failure.
Figure of merit
HPL itself provides a mechanism for running several problem sizes in an attempt to maximize the GFlops rating. To ensure we do not lose data when extracting GFlops rating from HPL, we can create a figure of merit context to relate the GFlops rating to the input parameters. We can then define the figure of merit to exist within this context. The context can look like the following:
figure_of_merit_context(
"problem-name",
regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
output_format="N-NB-P-Q = {N}-{NB}-{P}-{Q}",
)
This creates a new figure of merit context named problem-name which figures
of merit can be associated with. The context will have the N, NB,
P, and Q values associated with all figures of merit within. Since
HPL reports its performance in Gflops, we extract this value using the
figure_of_merit directive with a regular expression.
figure_of_merit(
"gflops",
fom_regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
group_name="gflops",
units="Gflops",
contexts=["problem-name"],
fom_type=FomType.THROUGHPUT
)
Here we have associated the figure of merit with the problem-name and also
added the fom_type attribute to convey to users (and Ramble) that this is a
throughput metric.
HPL additionally outputs time for the experiments. We can track this as a separate figure of merit:
figure_of_merit(
"Time",
fom_regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
group_name="time",
units="s",
contexts=["problem-name"],
fom_type=FomType.TIME,
)
Putting it all together
Our complete application definition at this point is as follows:
from ramble.appkit import *
class Hpl(ExecutableApplication):
name = 'hpl'
with when("package_manager_family=spack"):
software_spec(name="hpl", pkg_spec="hpl@2.3")
register_template(
"hpl.dat.in",
template_file="templates/HPL.dat.tpl",
destination="HPL.dat"
)
executable(
"hpl-execute",
"xhpl",
use_mpi=True,
)
workload(
"default",
executables=["hpl-execute"],
)
workload_variable("Ns", default=1000, description="Problem size", workload="default")
workload_variable("NBs", default=256, description="Block size", workload="default")
workload_variable("Ps", default=1, description="Number of process rows", workload="default")
workload_variable("Qs", default=1, description="Number of process columns", workload="default")
figure_of_merit_context(
"problem-name",
regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
output_format="N-NB-P-Q = {N}-{NB}-{P}-{Q}",
)
figure_of_merit(
"gflops",
fom_regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
group_name="gflops",
units="Gflops",
contexts=["problem-name"],
fom_type=FomType.THROUGHPUT
)
figure_of_merit(
"Time",
fom_regex=r".*?\s+(?P<N>[0-9]+)\s+(?P<NB>[0-9]+)\s+(?P<P>[0-9]+)\s+(?P<Q>[0-9]+)\s+(?P<time>[0-9]+\.[0-9]+)\s+(?P<gflops>\S+)",
group_name="time",
units="s",
contexts=["problem-name"],
fom_type=FomType.TIME,
)
Final Tests
To complete this tutorial we will test the application.
First, create a workspace:
$ ramble workspace create -d tutorial-workspace -a
Now, add an experiment. We’ll need to provide values for the number of nodes and ranks. For HPL, the number of ranks should equal PxQ.
$ ramble workspace manage experiments hpl --overwrite \
-v n_nodes=1 \
-v n_ranks=4 \
-v Ps=2 \
-v Qs=2 \
-v Ns=2000 \
-v NBs=256
Now, to complete the test we can execute:
$ ramble workspace setup
$ ramble on
$ ramble workspace analyze
The ramble workspace setup command will build HPL using Spack (if not
already installed), which can take some time. Then, the ramble on command
will run the experiment. After analysis, the result of these commands should be
the creation of a results.latest.txt file that contains the Gflops of your
machine, and the time spent running HPL.
Summary and Final Cleanup
At this stage, you have now created a new application definition to build and run the HPL benchmark.
To clean up your system, make sure to deactivate your workspace before trying to remove it.
$ ramble workspace deactivate
$ rm -rf tutorial-workspace
The application definition you have now matches some of the basic functionality
from Ramble’s HPL implementation. You should now be able to compare your
definition from the one seen by using
ramble edit --type base_applications -N builtin hpl.