Skip to content

Commit ffbd82a

Browse files
committed
Performance monitoring; GitHub integration
This patch introduces two new testing targets to the verification suite based on a small configuration based on the `benchmark` regression test. The profile test is saved a `p0` in `.testing`. Future tests can be included if appropriate. The new targets: * `make profile`: Run the model and record the FMS timings. * `make perf`: Run the model through the `perf` tool and record timings for the resolvable functions (as symbols). In both cases, the timings are converted to JSON output files and the top results are reported to stdout, and readable in GitHub actions output. It can also be run locally. Support Python scripts have been included to do this work. This will require a functional Python environment. Some system and configuration data is logged alongside the timings, but this is still rather incomplete and needs some further planning. Times are compared to the target build (usually dev/gfdl). ANSI terminal highlighting (i.e. color) is to used to highlight excessive differences. Current issues: - Model configuration - GitHub timings are still rather unreliable, and should currently only be treated as crude estimates. This should be considered a work in progress. - The GitHub profiling rule still builds the standard configuration, evem though it is unused. - Additional tools are required to push the timings to some database, either a local sqlite3 or an external one.
1 parent 4273444 commit ffbd82a

11 files changed

Lines changed: 1119 additions & 1 deletion

File tree

.github/actions/testing-setup/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ runs:
3333
echo "::group::Install linux packages"
3434
sudo apt-get update
3535
sudo apt-get install netcdf-bin libnetcdf-dev libnetcdff-dev mpich libmpich-dev
36+
sudo apt-get install linux-tools-common
3637
echo "::endgroup::"
3738
3839
- name: Compile FMS library

.github/workflows/perfmon.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Performance Monitor
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
build-test-perfmon:
7+
8+
runs-on: ubuntu-latest
9+
defaults:
10+
run:
11+
working-directory: .testing
12+
13+
steps:
14+
- uses: actions/checkout@v2
15+
with:
16+
submodules: recursive
17+
18+
- uses: ./.github/actions/testing-setup
19+
20+
- name: Compile optimized models
21+
run: >-
22+
make -j build.prof
23+
MOM_TARGET_SLUG=$GITHUB_REPOSITORY
24+
MOM_TARGET_LOCAL_BRANCH=$GITHUB_BASE_REF
25+
DO_REGRESSION_TESTS=true
26+
27+
- name: Generate profile data
28+
run: >-
29+
pip install f90nml &&
30+
make profile
31+
DO_REGRESSION_TESTS=true
32+
33+
- name: Generate perf data
34+
run: |
35+
sudo sysctl -w kernel.perf_event_paranoid=2
36+
make perf DO_REGRESSION_TESTS=true

.testing/Makefile

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
# Build configuration:
3535
# FCFLAGS_DEBUG Testing ("debug") compiler flags
3636
# FCFLAGS_REPRO Production ("repro") compiler flags
37+
# FCFLAGS_OPT Aggressive optimization compiler flags
3738
# FCFLAGS_INIT Variable initialization flags
3839
# FCFLAGS_COVERAGE Code coverage flags
3940
#
@@ -72,6 +73,7 @@ export MPIFC
7273
# NOTE: FMS will be built using FCFLAGS_DEBUG
7374
FCFLAGS_DEBUG ?= -g -O0
7475
FCFLAGS_REPRO ?= -g -O2
76+
FCFLAGS_OPT ?= -g -O3 -mavx -fno-omit-frame-pointer
7577
FCFLAGS_INIT ?=
7678
FCFLAGS_COVERAGE ?=
7779
# Additional notes:
@@ -96,6 +98,7 @@ DO_REPRO_TESTS ?=
9698
# Time measurement (configurable by the CI)
9799
TIME ?= time
98100

101+
99102
#---
100103
# Dependencies
101104
DEPS = deps
@@ -122,6 +125,11 @@ ifeq ($(DO_REPRO_TESTS), true)
122125
TESTS += repros
123126
endif
124127

128+
# Profiling
129+
ifeq ($(DO_PROFILE), false)
130+
BUILDS += opt opt_target
131+
endif
132+
125133
# The following variables are configured by Travis:
126134
# DO_REGRESSION_TESTS: true if $(TRAVIS_PULL_REQUEST) is a PR number
127135
# MOM_TARGET_SLUG: TRAVIS_REPO_SLUG
@@ -195,6 +203,7 @@ endif
195203
.PHONY: all build.regressions
196204
all: $(foreach b,$(BUILDS),build/$(b)/MOM6) $(VENV_PATH)
197205
build.regressions: $(foreach b,symmetric target,build/$(b)/MOM6)
206+
build.prof: $(foreach b,opt opt_target,build/$(b)/MOM6)
198207

199208
# Executable
200209
BUILD_TARGETS = MOM6 Makefile path_names
@@ -217,6 +226,7 @@ PATH_FMS = PATH="${PATH}:../../$(DEPS)/bin"
217226
SYMMETRIC_FCFLAGS := FCFLAGS="$(FCFLAGS_DEBUG) $(FCFLAGS_INIT) $(COVERAGE) $(FCFLAGS_FMS)"
218227
ASYMMETRIC_FCFLAGS := FCFLAGS="$(FCFLAGS_DEBUG) $(FCFLAGS_INIT) $(FCFLAGS_FMS)"
219228
REPRO_FCFLAGS := FCFLAGS="$(FCFLAGS_REPRO) $(FCFLAGS_FMS)"
229+
OPT_FCFLAGS := FCFLAGS="$(FCFLAGS_OPT) $(FCFLAGS_FMS)"
220230
OPENMP_FCFLAGS := FCFLAGS="$(FCFLAGS_DEBUG) $(FCFLAGS_INIT) $(FCFLAGS_FMS)"
221231
TARGET_FCFLAGS := FCFLAGS="$(FCFLAGS_DEBUG) $(FCFLAGS_INIT) $(FCFLAGS_FMS)"
222232

@@ -230,6 +240,8 @@ build/asymmetric/Makefile: MOM_ENV=$(PATH_FMS) $(ASYMMETRIC_FCFLAGS) $(MOM_LDFLA
230240
build/repro/Makefile: MOM_ENV=$(PATH_FMS) $(REPRO_FCFLAGS) $(MOM_LDFLAGS)
231241
build/openmp/Makefile: MOM_ENV=$(PATH_FMS) $(OPENMP_FCFLAGS) $(MOM_LDFLAGS)
232242
build/target/Makefile: MOM_ENV=$(PATH_FMS) $(TARGET_FCFLAGS) $(MOM_LDFLAGS)
243+
build/opt/Makefile: MOM_ENV=$(PATH_FMS) $(OPT_FCFLAGS) $(MOM_LDFLAGS)
244+
build/opt_target/Makefile: MOM_ENV=$(PATH_FMS) $(OPT_FCFLAGS) $(MOM_LDFLAGS)
233245
build/coupled/Makefile: MOM_ENV=$(PATH_FMS) $(SYMMETRIC_FCFLAGS) $(SYMMETRIC_LDFLAGS)
234246
build/nuopc/Makefile: MOM_ENV=$(PATH_FMS) $(SYMMETRIC_FCFLAGS) $(SYMMETRIC_LDFLAGS)
235247
build/mct/Makefile: MOM_ENV=$(PATH_FMS) $(SYMMETRIC_FCFLAGS) $(SYMMETRIC_LDFLAGS)
@@ -240,12 +252,15 @@ build/asymmetric/Makefile: MOM_ACFLAGS=--enable-asymmetric
240252
build/repro/Makefile: MOM_ACFLAGS=
241253
build/openmp/Makefile: MOM_ACFLAGS=--enable-openmp
242254
build/target/Makefile: MOM_ACFLAGS=
255+
build/opt/Makefile: MOM_ACFLAGS=
256+
build/opt_target/Makefile: MOM_ACFLAGS=
243257
build/coupled/Makefile: MOM_ACFLAGS=--with-driver=coupled_driver
244258
build/nuopc/Makefile: MOM_ACFLAGS=--with-driver=nuopc_driver
245259
build/mct/Makefile: MOM_ACFLAGS=--with-driver=mct_driver
246260

247261
# Fetch regression target source code
248262
build/target/Makefile: | $(TARGET_CODEBASE)
263+
build/opt_target/Makefile: | $(TARGET_CODEBASE)
249264

250265

251266
# Define source code dependencies
@@ -276,7 +291,8 @@ build/%/Makefile: ../ac/configure ../ac/Makefile.in $(DEPS)/lib/libFMS.a $(MKMF)
276291

277292

278293
# Fetch the regression target codebase
279-
build/target/Makefile: $(TARGET_CODEBASE)/ac/configure $(DEPS)/lib/libFMS.a $(MKMF) $(LIST_PATHS)
294+
build/target/Makefile build/opt_target/Makefile: \
295+
$(TARGET_CODEBASE)/ac/configure $(DEPS)/lib/libFMS.a $(MKMF) $(LIST_PATHS)
280296
mkdir -p $(@D)
281297
cd $(@D) \
282298
&& $(MOM_ENV) ../../$(TARGET_CODEBASE)/ac/configure $(MOM_ACFLAGS) \
@@ -620,6 +636,64 @@ test.summary:
620636
fi
621637

622638

639+
#---
640+
# Profiling
641+
# XXX: This is experimental work to track, log, and report changes in runtime
642+
PCONFIGS = p0
643+
644+
.PHONY: profile
645+
profile: $(foreach p,$(PCONFIGS), prof.$(p))
646+
647+
.PHONY: prof.p0
648+
prof.p0: work/p0/opt/clocks.json work/p0/opt_target/clocks.json
649+
python tools/compare_clocks.py $^
650+
651+
work/p0/%/clocks.json: work/p0/%/std.out
652+
python tools/parse_fms_clocks.py -d $(@D) $^ > $@
653+
654+
work/p0/opt/std.out: build/opt/MOM6
655+
work/p0/opt_target/std.out: build/opt_target/MOM6
656+
657+
work/p0/%/std.out:
658+
mkdir -p $(@D)
659+
cp -RL p0/* $(@D)
660+
mkdir -p $(@D)/RESTART
661+
echo -e "" > $(@D)/MOM_override
662+
cd $(@D) \
663+
&& $(MPIRUN) -n 1 ../../../$< 2> std.err > std.out
664+
665+
#---
666+
# Same but with perf
667+
668+
# TODO: This expects the -e flag, can I handle it in the command?
669+
PERF_EVENTS ?=
670+
671+
.PHONY: perf
672+
perf: $(foreach p,$(PCONFIGS), perf.$(p))
673+
674+
.PHONY: prof.p0
675+
perf.p0: work/p0/opt/profile.json work/p0/opt_target/profile.json
676+
python tools/compare_perf.py $^
677+
678+
work/p0/%/profile.json: work/p0/%/perf.data
679+
python tools/parse_perf.py -f $< > $@
680+
681+
work/p0/opt/perf.data: build/opt/MOM6
682+
work/p0/opt_target/perf.data: build/opt_target/MOM6
683+
684+
work/p0/%/perf.data:
685+
mkdir -p $(@D)
686+
cp -RL p0/* $(@D)
687+
mkdir -p $(@D)/RESTART
688+
echo -e "" > $(@D)/MOM_override
689+
cd $(@D) \
690+
&& perf record \
691+
-F 3999 \
692+
${PERF_EVENTS} \
693+
../../../$< 2> std.perf.err > std.perf.out \
694+
|| cat std.perf.err
695+
696+
623697
#----
624698
# NOTE: These tests assert that we are in the .testing directory.
625699

0 commit comments

Comments
 (0)