Skip to content

Commit 700d7bb

Browse files
authored
Merge pull request #498 from llnl/395-gpu-performance-tests
Simplify performance benchmark data
2 parents fbf96cf + 9321017 commit 700d7bb

17 files changed

Lines changed: 152 additions & 74 deletions

File tree

.gitlab/performance.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
- cd $INSTALL_DIR
1616
- INSTALL_BENCHMARK_DIR=$(./bin/spheral-ats --get-benchmark)
1717
- PERF_OUT_DIR=$INSTALL_BENCHMARK_DIR/$(date +%s)
18-
- mkdir $PERF_OUT_DIR
18+
- echo "Creating benchmark directory at ${PERF_OUT_DIR}"
19+
- mkdir -p $PERF_OUT_DIR
1920
- echo "Running performance tests using install at $INSTALL_DIR"
2021
- rm -rf perf_logs gpu_perf_logs
2122
- ./bin/spheral-ats --ciRun --numNodes 2 --logs perf_logs $INSTALL_DIR/$PERF_ATS_FILE
2223
- cp perf_logs/*.cali $PERF_OUT_DIR
2324
- ./bin/spheral-ats --gpu --ciRun --numNodes 2 --logs gpu_perf_logs $INSTALL_DIR/$PERF_ATS_FILE
2425
# Copy caliper files to the benchmark directory and don't complain if you cant
2526
- cp gpu_perf_logs/*.cali $PERF_OUT_DIR 2>/dev/null || true
26-
- chmod -R gu+rwx $PERF_OUT_DIR
27+
- chmod -R gu+rx $PERF_OUT_DIR
2728
- chgrp -R sduser $PERF_OUT_DIR
2829

2930
toss_gcc_mpi_perf:

.gitlab/scripts.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,24 +65,25 @@
6565

6666
# This copies the install so scheduled perf tests can use it
6767
# Adding test-perf to commit message will trigger the perf install from that branch
68+
# Requires upstream TPLs to be up to date
6869
.perf_install:
6970
extends: [.retry_rule]
7071
stage: perf_install
7172
variables:
7273
GIT_STRATEGY: none
7374
rules:
74-
- if: '($CI_COMMIT_MESSAGE =~ /test-perf/ || $CI_COMMIT_REF_NAME == "develop")'
75+
- !reference [.merge_pr_rule, rules]
76+
- if: '$CI_COMMIT_MESSAGE =~ /test-perf/'
7577
when: always
7678
script:
79+
- umask 027
7780
- CI_BUILD_DIR=$(cat ci-dir.txt)
7881
- INSTALL_DIR=$PERF_INSTALL_DIR/${SPEC//%/_}
7982
- ml load mpifileutils
8083
- echo "Doing install in ${INSTALL_DIR}"
8184
- if [[ -d $INSTALL_DIR ]]; then $RUN_CMD -n $NPROC drm $INSTALL_DIR; else echo "No install exists."; fi
82-
- cd $CI_BUILD_DIR/build_gitlab/build
83-
- cmake ../../ -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
84-
- make -j $NPROC install
85-
- $RUN_CMD -n $NPROC dchmod --mode go+rx $INSTALL_DIR
85+
- cd $CI_BUILD_DIR
86+
- ./$SCRIPT_DIR/devtools/host-config-build.py --no-clean --build --nprocs $NPROC --host-config gitlab.cmake --install-dir $INSTALL_DIR
8687
artifacts:
8788
paths:
8889
- ci-dir.txt
@@ -136,7 +137,7 @@
136137
stage: update_tpls
137138
rules:
138139
- !reference [.merge_pr_rule, rules]
139-
- if: '$CI_COMMIT_MESSAGE =~ /update-tpls/'
140+
- if: '($CI_COMMIT_MESSAGE =~ /update-tpls/ || $CI_COMMIT_MESSAGE =~ /test-perf/)'
140141
script:
141142
- umask 027
142143
- ./$SCRIPT_DIR/devtools/tpl-manager.py --update-upstream

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CMakeLists to build the Spheral library.
22

3-
cmake_minimum_required(VERSION 3.21)
3+
cmake_minimum_required(VERSION 3.24)
44
include(cmake/SpheralVersion.cmake)
55
project(spheral LANGUAGES C CXX Fortran VERSION ${SPHERAL_VERSION})
66

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Notable changes include:
2424
* Added a page to the docs about GPU development.
2525
* Optimized field lookups in state, reducing per-call cost from O(N) to O(log N)
2626
* Added the more aptly named SPHERAL_EXTERNAL_INSTALL in places where ENABLE_STATIC_TPLS was being used.
27+
* Require minimum CMake version 3.24.
2728

2829
* Bug fixes:
2930
* Adiak memory leak is fixed by calling adiak::clean() before exit.
@@ -52,6 +53,7 @@ Notable changes include:
5253
* Added umask command for updating upstreams and removed separate job to update permissions.
5354
* Build and test job now fails if import of Spheral module fails.
5455
* Number of ranks on RZAdams increased from 84 to 96 per node for performance tests.
56+
* Created advanced timers for lower level timers. These are disabled by default for cleaner Caliper timer trees.
5557
* Builds and installs are cleaner:
5658
* Rpaths are no longer overwritten, allowing things set in the Spack host config file to be used.
5759
* Spheral libraries are only installed once now and a Spheral.pth with a relative path to the install lib is used in the virtual python environment.

docs/developer/dev/diagnostic_tools.rst

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,32 @@ The following macros are used to create timing regions in the Spheral C++ interf
7878

7979
- ``TIME_BEGIN("timer_name")`` and ``TIME_END("timer_name")`` create a region between the two different calls and use the string (in this case ``timer_name``) as the name.
8080

81+
It is not recommended to add timers to lower level functions. For example, functions that are called on a per SPH node basis should not have timers. If timers are desired for these types of functions, use advanced timers, denoted as ``ADV_TIME_BEGIN("timer_name")`` and ``ADV_TIME_END("timer_name")``. Advanced timers must be enabled through the python interface, as described below.
8182

8283
Adding Region Timers in Python
8384
------------------------------
8485

8586
Region timers can be added inside the python code using the following function calls:
8687
::
8788

88-
from SpheralUtilities import TimerMgr
89+
from SpheralCompiledModules.SpheralUtilities import TimerMgr
90+
if (not TimerMgr.is_started()):
91+
TimerMgr.default_start("TestName.cali")
8992
TimerMgr.timer_begin("timer_name")
9093
some_function_call()
9194
TimerMgr.timer_end("timer_name")
9295

96+
Similarly, advanced timers can be added through the python interface. They must be enabled through the python interface for any advanced timers to be included:
97+
::
98+
99+
from SpheralCompiledModules.SpheralUtilities import TimerMgr
100+
if (not TimerMgr.is_started()):
101+
TimerMgr.default_start("TestName.cali")
102+
TimerMgr.enable_advanced_timers() # Required for advanced timers to be included
103+
TimerMgr.adv_timer_begin("timer_name")
104+
some_function_call()
105+
TimerMgr.adv_timer_end("timer_name")
106+
93107
.. note::
94108
All timers must have both a start and end call. Otherwise, memory issues will occur.
95109

@@ -129,7 +143,7 @@ Starting Caliper Manually
129143
As mentioned above, the Caliper timing manager is normally configured and started in the ``commandLine()`` routine. However, Caliper can be directly configured and started through the python interface, if desired. This can be done by putting the following into the python file:
130144
::
131145

132-
from SpheralUtilities import TimerMgr
146+
from SpheralCompiledModules.SpheralUtilities import TimerMgr
133147
caliper_config = "some_configuration(output=some_filename.txt)"
134148
TimerMgr.add(caliper_config)
135149
TimerMgr.start()
@@ -184,7 +198,7 @@ The general procedure to comparing performance regression tests is:
184198
If ``run_perf.py`` is run on a non-MPI Spheral build, it will only use 1 rank and will thread all other available cores.
185199

186200

187-
To simply display the Thicket timing tree for a performance run without doing any sort of comparison, use:
201+
To simply display the Thicket timing tree for a performance run without doing any comparison, use:
188202
::
189203

190204
./bin/spheral ./scripts/performance_analysis.py --perfdata /path/to/perf/data

scripts/devtools/host-config-build.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,28 @@ def main():
5757
build_dir="{0}/build_{1}".format(source_dir, hostconfig)
5858
else:
5959
build_dir="{0}/{1}".format(source_dir, args.build_dir)
60-
if not args.install_dir:
61-
install_dir="{0}/install".format(build_dir)
60+
61+
# Set install directory, give preference to the CMAKE_INSTALL_PREFIX
62+
if args.D and any("CMAKE_INSTALL_PREFIX" in x for x in args.D):
63+
install_dir = None
64+
elif args.install_dir:
65+
install_dir = args.install_dir
6266
else:
63-
install_dir=args.install_dir
67+
install_dir="{0}/install".format(build_dir)
68+
6469
build_dir=build_dir+"/build"
6570
# Pull the cmake command to use out of our host config.
6671
cmake_cmd=sexe("grep 'CMake executable' \"{0}\"".format(hostconfig_path), ret_output=True, echo=False).split()[-1]
6772

6873
cmake_extra_args=""
6974
if args.D and args.D != ['']:
7075
cmake_extra_args="-D"+" -D".join(args.D)
71-
76+
7277
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
7378
print("~ Host-config: {0}".format(hostconfig_path))
7479
print("~ Build Dir: {0}".format(build_dir))
75-
print("~ Install Dir: {0}".format(install_dir))
80+
if install_dir:
81+
print("~ Install Dir: {0}".format(install_dir))
7682
print("~ Source Dir: {0}".format(source_dir))
7783
print("~ Cmake cmd: {0}".format(cmake_cmd))
7884
print("~ Extra CMake Args: {0}".format(cmake_extra_args))
@@ -82,15 +88,18 @@ def main():
8288
# Clean our build and install dirs...
8389
if not args.no_clean:
8490
sexe("rm -rf \"{0}\" 2>/dev/null".format(build_dir),echo=True)
85-
sexe("rm -rf \"{0}\" 2>/dev/null".format(install_dir),echo=True)
91+
if install_dir:
92+
sexe("rm -rf \"{0}\" 2>/dev/null".format(install_dir),echo=True)
8693
sexe("mkdir -p \"{0}\"".format(build_dir),echo=True)
87-
sexe("mkdir -p \"{0}\"".format(install_dir),echo=True)
94+
if install_dir:
95+
sexe("mkdir -p \"{0}\"".format(install_dir),echo=True)
8896

8997
# Move to the build directory.
9098
os.chdir(build_dir)
9199

92100
# Run our CMake config step.
93-
sexe(f"{cmake_cmd} -C {hostconfig_path} -DCMAKE_INSTALL_PREFIX={install_dir} {cmake_extra_args} {source_dir}")
101+
install_str = f"-DCMAKE_INSTALL_PREFIX={install_dir}" if install_dir else ""
102+
sexe(f"{cmake_cmd} -C {hostconfig_path} {install_str} {cmake_extra_args} {source_dir}")
94103

95104
# Build and install Spheral
96105

scripts/devtools/performance_analysis.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def compare_config(cdata, rdata):
136136
Do not use if comparing across hardware or install configurations.
137137
Assumes Thicket data has comparable test_name, total_internal_nodes, and total_steps
138138
"""
139-
hardware_tests = ["install_config", "cluster", "jobsize", "threads_per_rank"]
139+
hardware_tests = ["spec", "cluster", "jobsize", "threads_per_rank"]
140140
return compare_metadata(cdata, rdata, hardware_tests)
141141

142142
def filter_tests(data, test_name):
@@ -271,9 +271,9 @@ def main():
271271
raise Exception("No reference or benchmark data specified")
272272
# If using benchmark reference data, only grab the current install/machine
273273
# Get install config and machine name from current data
274-
install_config = curdata.metadata["install_config"].iloc[0]
274+
install_spec = curdata.metadata["spec"].iloc[0]
275275
machine_name = curdata.metadata["cluster"].iloc[0]
276-
ref_loc = os.path.join(ref_files, install_config, machine_name)
276+
ref_loc = os.path.join(ref_files, machine_name, install_spec)
277277
if (not os.path.exists(ref_loc)):
278278
raise Exception(f"Benchmark location {ref_loc} does not exists")
279279
cali_ref_files = glob.glob(os.path.join(ref_loc, "**/*.cali"), recursive=True)

scripts/lc/hist_data_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def create_header(title, file_dict):
1212
<body>
1313
<form>
1414
<select onchange="window.location.href = this.value;">
15-
<option value="">-- Select machine/config --</option>
15+
<option value="">-- Select machine --</option>
1616
"""
1717
for link, ff in file_dict.items():
1818
html_string += " "*6

scripts/lc/plot_hist_data.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ def extract_data(cali_file):
6363
rtimes[rg] = tval
6464
return runday, rtimes
6565

66+
def update_spec(spec):
67+
"Spec names changes from spack 0.12 to 1.0, so we must update the names to match"
68+
repl_dict = [("clang", "llvm"), ("rocmcc", "llvm-amdgpu"),
69+
("cray-mpich", "mpi"), ("mvapich2", "mpi")]
70+
newspec = spec
71+
for i in repl_dict:
72+
newspec = newspec.replace(i[0], i[1])
73+
return newspec
74+
6675
def get_globals(cali_file):
6776
# If cali_file is just a dir, grab the latest caliper file
6877
if type(cali_file) == list:
@@ -83,7 +92,9 @@ def get_spec(cali_file):
8392
return gls["spec"]
8493

8594
def compare_time(cfile, num_of_months):
86-
tdelta = (time.time() - os.path.getmtime(cfile))/ (60*60*24)
95+
# The benchmark file times might not be accurate, use file names instead
96+
file_mtime = int(cfile.split("_")[-1].split(".")[0])
97+
tdelta = (time.time() - file_mtime)/ (60*60*24)
8798
if (tdelta < 30*num_of_months):
8899
return True
89100
return False
@@ -101,19 +112,12 @@ def split_test_name(test_name, test_base_names):
101112
return base, variant
102113
return None, None
103114

104-
def update_spec(spec):
105-
"Spec names changes from spack 0.12 to 1.0, so we must update the names to match"
106-
newspec = spec.replace("clang", "llvm")
107-
newspec = newspec.replace("rocmcc", "llvm-amdgpu")
108-
return newspec
109-
110115
# Convert array of dictionaries into panda dataframe
111116
def convert_to_dataframe(in_array, test_base_names):
112117
data = []
113118
for in_data in in_array:
114119
mac_name = in_data["machine"]
115120
spec_name = update_spec(in_data["spec"])
116-
config = in_data["config"]
117121
data_dict = in_data["data_dict"]
118122
for test_name, tdata in data_dict.items():
119123
test_base, test_var = split_test_name(test_name, test_base_names)
@@ -123,7 +127,6 @@ def convert_to_dataframe(in_array, test_base_names):
123127
for reg, val in time_dict.items():
124128
data.append({"Machine": mac_name,
125129
"Spec": spec_name,
126-
"Config": config,
127130
"Test Name": test_name,
128131
"Test Base": test_base,
129132
"Test Var": test_var,
@@ -210,29 +213,28 @@ def main():
210213
if (args.test):
211214
test_names = [test_names[0]]
212215
test_bases = pt.get_test_bases()
213-
# Benchmark directory is organized as /configs/machines/run_dates/*.cali
216+
# Benchmark directory is organized as /machine/spec/run_dates/*.cali
214217
# Each set of caliper files contain a single spec
215-
# Multiple configs could span a single machine+spec
216-
config_dirs = glob.glob(os.path.join(args.bench, "*"))
218+
mac_dirs = glob.glob(os.path.join(args.bench, "*"))
217219
# Extract all machine directories
218220
all_mac_specs = {}
219221
all_specs = {}
220222
if (rank == 0):
221-
for cc in config_dirs:
222-
mac_dirs = glob.glob(os.path.join(cc, "*"))
223-
for mc_path in mac_dirs:
224-
mac_name = os.path.basename(mc_path)
225-
cspec = get_spec(mc_path)
223+
for mc_path in mac_dirs:
224+
mac_name = os.path.basename(mc_path)
225+
spec_dirs = glob.glob(os.path.join(mc_path, "*"))
226+
for cc in spec_dirs:
227+
cspec = os.path.basename(cc)
226228
key = mac_name+" "+cspec
227229
all_specs[key] = cspec
228-
cur_path = os.path.join(mc_path, "*")
230+
cur_path = os.path.join(cc, "*")
229231
if key in all_mac_specs:
230232
all_mac_specs[key].append(cur_path)
231233
else:
232234
all_mac_specs.update({key: [cur_path]})
233235
if (args.local_run_dir):
234236
local_cali_files = glob.glob(os.path.join(args.local_run_dir, "*.cali"))
235-
cspec = get_spec(local_cali_files)
237+
cspec = update_spec(get_spec(local_cali_files))
236238
mac_name = get_host(local_cali_files)
237239
key = mac_name+" "+cspec
238240
if key in all_mac_specs:

scripts/spack/configs/toss_4_x86_64_ib/packages.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ packages:
6262

6363
mvapich2:
6464
externals:
65-
- spec: mvapich2@2.3.6.gcc process_managers=slurm %gcc@10.3.1
65+
- spec: mvapich2@2.3.6 process_managers=slurm %gcc@10.3.1
6666
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3.6-gcc-10.3.1-magic
67-
- spec: mvapich2@2.3.7.llvm process_managers=slurm %clang@19.1.3
67+
- spec: mvapich2@2.3.7 process_managers=slurm %clang@19.1.3
6868
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3
6969
buildable: false
7070

0 commit comments

Comments
 (0)