From f77e1eacfc6a19fd1e6c70ede021788d93edbcd8 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:30:11 +0300 Subject: [PATCH 1/9] add redesigned namd tests --- cscs-checks/apps/namd/namd_check.py | 164 +++++++++++++--------------- hpctestlib/apps/namd/base_check.py | 95 ++++++++++++++++ 2 files changed, 170 insertions(+), 89 deletions(-) create mode 100644 hpctestlib/apps/namd/base_check.py diff --git a/cscs-checks/apps/namd/namd_check.py b/cscs-checks/apps/namd/namd_check.py index 8fd72a0b0f..9e9eea5612 100644 --- a/cscs-checks/apps/namd/namd_check.py +++ b/cscs-checks/apps/namd/namd_check.py @@ -7,65 +7,79 @@ import reframe as rfm import reframe.utility.sanity as sn +from hpctestlib.apps.namd.base_check import Namd_BaseCheck +REFERENCE_GPU_PERFORMANCE = { + 'dom:gpu': { + 'small': (0.15, None, 0.05, 'days/ns'), + }, + 'daint:gpu': { + 'small': (0.15, None, 0.05, 'days/ns'), + 'large': (0.07, None, 0.05, 'days/ns') + }, +} -@rfm.simple_test -class NamdCheck(rfm.RunOnlyRegressionTest): - scale = parameter(['small', 'large']) - variant = parameter(['maint', 'prod']) - arch = parameter(['gpu', 'cpu']) +REFERENCE_CPU_PERFORMANCE = { + 'dom:mc': { + 'small': (0.51, None, 0.05, 'days/ns'), + }, + 'daint:mc': { + 'small': (0.51, None, 0.05, 'days/ns'), + 'large': (0.28, None, 0.05, 'days/ns') + }, + 'eiger:mc': { + 'small': (0.12, None, 0.05, 'days/ns'), + 'large': (0.05, None, 0.05, 'days/ns') + }, + 'pilatus:mc': { + 'small': (0.12, None, 0.05, 'days/ns'), + 'large': (0.05, None, 0.05, 'days/ns') + }, +} - valid_prog_environs = ['builtin', 'cpeIntel'] - modules = ['NAMD'] - executable = 'namd2' - use_multithreading = True - num_tasks_per_core = 2 +@rfm.simple_test +class NamdCheckCSCS(Namd_BaseCheck): maintainers = ['CB', 'LM'] tags = {'scs', 'external-resources'} + modules = ['NAMD'] extra_resources = { 'switches': { 'num_switches': 1 } } + use_multithreading = True + num_tasks_per_core = 2 + platform_name = parameter(['gpu', 'cpu']) + scale = parameter(['small', 'large']) + mode = parameter(['maint', 'prod']) @run_after('init') - def adapt_description(self): - self.descr = f'NAMD check ({self.arch}, {self.variant})' - self.tags |= { - 'maintenance' if self.variant == 'maint' else 'production' - } + def env_define(self): + if self.current_system.name in ['eiger', 'pilatus']: + self.valid_prog_environs = ['cpeGNU'] + else: + self.valid_prog_environs = ['builtin'] @run_after('init') - def adapt_valid_systems(self): - if self.arch == 'gpu': - self.valid_systems = ['daint:gpu'] - if self.scale == 'small': - self.valid_systems += ['dom:gpu'] - else: - self.valid_systems = ['daint:mc', 'eiger:mc', 'pilatus:mc'] - if self.scale == 'small': - self.valid_systems += ['dom:mc'] + def set_description(self): + self.mydescr = f'NAMD check ({self.platform_name}, {self.mode})' @run_after('init') - def adapt_valid_prog_environs(self): - if self.current_system.name == 'pilatus': - self.valid_prog_environs.remove('builtin') - else: - self.valid_prog_environs.remove('cpeIntel') + def set_tags(self): + self.tags |= {'maintenance' if self.mode == 'maint' + else 'production'} @run_after('init') - def setup_parallel_run(self): - if self.arch == 'gpu': - self.executable_opts = ['+idlepoll', '+ppn 23', 'stmv.namd'] - self.num_cpus_per_task = 24 - self.num_gpus_per_node = 1 + def set_valid_systems(self): + if self.platform_name =='gpu': + self.valid_systems = ['daint:gpu'] else: - # On Eiger a no-smp NAMD version is the default - if self.current_system.name in ['eiger', 'pilatus']: - self.executable_opts = ['+idlepoll', 'stmv.namd'] - else: - self.executable_opts = ['+idlepoll', '+ppn 71', 'stmv.namd'] - self.num_cpus_per_task = 72 + self.valid_systems = ['daint:mc', + 'eiger:mc', + 'pilatus:mc'] + + @run_after('setup') + def set_num_tasks(self): if self.scale == 'small': # On Eiger a no-smp NAMD version is the default if self.current_system.name in ['eiger', 'pilatus']: @@ -82,56 +96,28 @@ def setup_parallel_run(self): self.num_tasks = 16 self.num_tasks_per_node = 1 - @run_before('compile') - def prepare_build(self): - # Reset sources dir relative to the SCS apps prefix - self.sourcesdir = os.path.join(self.current_system.resourcesdir, - 'NAMD', 'prod') - - @sanity_function - def validate_energy(self): - energy = sn.avg(sn.extractall( - r'ENERGY:([ \t]+\S+){10}[ \t]+(?P\S+)', - self.stdout, 'energy', float) - ) - energy_reference = -2451359.5 - energy_diff = sn.abs(energy - energy_reference) - return sn.all([ - sn.assert_eq(sn.count(sn.extractall( - r'TIMING: (?P\S+) CPU:', - self.stdout, 'step_num')), 50), - sn.assert_lt(energy_diff, 2720) - ]) + @run_after('setup') + def set_executable_opts(self): + if self.platform_name =='gpu': + self.executable_opts = ['+idlepoll', '+ppn 23', 'stmv.namd'] + self.num_cpus_per_task = 24 + self.num_gpus_per_node = 1 + else: + # On Eiger a no-smp NAMD version is the default + if self.current_system.name in ['eiger', 'pilatus']: + self.executable_opts = ['+idlepoll', 'stmv.namd'] + self.num_tasks_per_core = 2 + else: + self.executable_opts = ['+idlepoll', '+ppn 71', 'stmv.namd'] + self.num_cpus_per_task = 72 - @run_before('performance') - def setup_perf_vars(self): - self.perf_patterns = { - 'days_ns': sn.avg(sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) - } - if self.arch == 'gpu': + @run_after('setup') + def set_reference(self): + if self.platform_name =='gpu': + self.reference = REFERENCE_GPU_PERFORMANCE if self.scale == 'small': - self.reference = { - 'dom:gpu': {'days_ns': (0.15, None, 0.05, 'days/ns')}, - 'daint:gpu': {'days_ns': (0.15, None, 0.05, 'days/ns')} - } - else: - self.reference = { - 'daint:gpu': {'days_ns': (0.07, None, 0.05, 'days/ns')} - } + self.valid_systems += ['dom:gpu'] else: if self.scale == 'small': - self.reference = { - 'dom:mc': {'days_ns': (0.51, None, 0.05, 'days/ns')}, - 'daint:mc': {'days_ns': (0.51, None, 0.05, 'days/ns')}, - 'eiger:mc': {'days_ns': (0.12, None, 0.05, 'days/ns')}, - 'pilatus:mc': {'days_ns': (0.12, None, 0.05, 'days/ns')}, - } - else: - self.reference = { - 'daint:mc': {'days_ns': (0.28, None, 0.05, 'days/ns')}, - 'eiger:mc': {'days_ns': (0.05, None, 0.05, 'days/ns')}, - 'pilatus:mc': {'days_ns': (0.05, None, 0.05, 'days/ns')} - } + self.valid_systems += ['dom:mc'] + self.reference = REFERENCE_CPU_PERFORMANCE diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py new file mode 100644 index 0000000000..f6041f7c9a --- /dev/null +++ b/hpctestlib/apps/namd/base_check.py @@ -0,0 +1,95 @@ +# Copyright 2016-2021 Swiss National Supercomputing Centre (CSCS/ETH Zurich) +# ReFrame Project Developers. See the top-level LICENSE file for details. +# +# SPDX-License-Identifier: BSD-3-Clause + +import os + +import reframe as rfm +import reframe.utility.sanity as sn + + +class Namd_BaseCheck(rfm.RunOnlyRegressionTest): + '''Base class for the NAMD Test. + + NAMD is a parallel molecular dynamics code designed for + high-performance simulation of large biomolecular systems. + Based on Charm++ parallel objects, NAMD scales to hundreds of + cores for typical simulations and beyond 500,000 cores for the + largest simulations. NAMD uses the popular molecular graphics + program VMD for simulation setup and trajectory analysis, + but is also file-compatible with AMBER, CHARMM, and X-PLOR. + (see ks.uiuc.edu/Research/namd/) + + The presented abstract run-only class checks the NAMD perfomance. + To do this, it is necessary to define in tests the reference values + of energy and possible deviations from this value. This data is used + to check if the task is being executed correctly, that is, the final + energy is correct (approximately the reference). The default + assumption is that NAMD is already installed on the device under test. + ''' + + #: Reference value of energy, that is used for the comparison + #: with the execution ouput on the sanity step. The absolute + #: difference between final energy value and reference value + #: should be smaller than energy_tolerance + #: + #: :type: str + #: :default: :class:`required` + energy_value = variable(float) + + #: Maximum deviation from the reference value of energy, + #: that is acceptable. + #: + #: :default: :class:`required` + energy_tolerance = variable(float) + + #: :default: :class:`required` + executable = required + + executable = 'namd2' + energy_value = -2451359.5 + energy_tolerance = 2720. + + @run_after('init') + def source_install(self): + # Reset sources dir relative to the SCS apps prefix + self.sourcesdir = os.path.join(self.current_system.resourcesdir, + 'NAMD', 'prod') + + @run_before('performance') + def set_the_performance_dict(self): + self.perf_variables = {self.scale: + sn.make_performance_function( + sn.avg( + sn.extractall( + r'Info: Benchmark time: \S+ CPUs' + r' \S+ s/step (?P\S+) ' + r'days/ns \S+ MB memory', + self.stdout, 'days_ns', float)), + 'days/ns')} + + @performance_function('days/ns', perf_key='perf') + def set_perf_patterns(self): + return sn.avg( + sn.extractall( + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) + + @sanity_function + def assert_energy_readout(self): + '''Assert the obtained energy meets the specified tolerances.''' + + energy = sn.avg(sn.extractall( + r'ENERGY:([ \t]+\S+){10}[ \t]+(?P\S+)', + self.stdout, 'energy', float) + ) + energy_diff = sn.abs(energy - self.energy_value) + ref_ener_diff = sn.abs(self.energy_tolerance) + return sn.all([ + sn.assert_eq(sn.count(sn.extractall( + r'TIMING: (?P\S+) CPU:', + self.stdout, 'step_num')), 50), + sn.assert_lt(energy_diff, self.energy_tolerance) + ]) From c4e62e67b10e692b55480d516c2ebf1a951e57a4 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:42:19 +0300 Subject: [PATCH 2/9] add problems with blank lines and indents --- cscs-checks/apps/namd/namd_check.py | 7 ++++--- hpctestlib/apps/namd/base_check.py | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/cscs-checks/apps/namd/namd_check.py b/cscs-checks/apps/namd/namd_check.py index 9e9eea5612..c1f17af411 100644 --- a/cscs-checks/apps/namd/namd_check.py +++ b/cscs-checks/apps/namd/namd_check.py @@ -37,6 +37,7 @@ }, } + @rfm.simple_test class NamdCheckCSCS(Namd_BaseCheck): maintainers = ['CB', 'LM'] @@ -71,7 +72,7 @@ def set_tags(self): @run_after('init') def set_valid_systems(self): - if self.platform_name =='gpu': + if self.platform_name == 'gpu': self.valid_systems = ['daint:gpu'] else: self.valid_systems = ['daint:mc', @@ -98,7 +99,7 @@ def set_num_tasks(self): @run_after('setup') def set_executable_opts(self): - if self.platform_name =='gpu': + if self.platform_name == 'gpu': self.executable_opts = ['+idlepoll', '+ppn 23', 'stmv.namd'] self.num_cpus_per_task = 24 self.num_gpus_per_node = 1 @@ -113,7 +114,7 @@ def set_executable_opts(self): @run_after('setup') def set_reference(self): - if self.platform_name =='gpu': + if self.platform_name == 'gpu': self.reference = REFERENCE_GPU_PERFORMANCE if self.scale == 'small': self.valid_systems += ['dom:gpu'] diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index f6041f7c9a..519d744e00 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -61,21 +61,21 @@ def source_install(self): def set_the_performance_dict(self): self.perf_variables = {self.scale: sn.make_performance_function( - sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs' - r' \S+ s/step (?P\S+) ' - r'days/ns \S+ MB memory', - self.stdout, 'days_ns', float)), - 'days/ns')} + sn.avg( + sn.extractall( + r'Info: Benchmark time: \S+ CPUs' + r' \S+ s/step (?P\S+) ' + r'days/ns \S+ MB memory', + self.stdout, 'days_ns', float)), + 'days/ns')} @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + sn.extractall( + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From e2c8538e2a24a8d87d53e82788c89021d15cf9dd Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:49:06 +0300 Subject: [PATCH 3/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 519d744e00..193caf339b 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -61,18 +61,18 @@ def source_install(self): def set_the_performance_dict(self): self.perf_variables = {self.scale: sn.make_performance_function( - sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs' - r' \S+ s/step (?P\S+) ' - r'days/ns \S+ MB memory', - self.stdout, 'days_ns', float)), - 'days/ns')} + sn.avg( + sn.extractall( + r'Info: Benchmark time: \S+ CPUs' + r' \S+ s/step (?P\S+) ' + r'days/ns \S+ MB memory', + self.stdout, 'days_ns', float)), + 'days/ns')} @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg( - sn.extractall( + sn.extractall( r'Info: Benchmark time: \S+ CPUs \S+ ' r's/step (?P\S+) days/ns \S+ MB memory', self.stdout, 'days_ns', float)) From 0aed835f0c869b74502fd0d1c646981dbdf703b7 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:50:44 +0300 Subject: [PATCH 4/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 193caf339b..743f0ee15f 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -67,15 +67,15 @@ def set_the_performance_dict(self): r' \S+ s/step (?P\S+) ' r'days/ns \S+ MB memory', self.stdout, 'days_ns', float)), - 'days/ns')} + 'days/ns')} @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + sn.extractall( + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From a6ba593a840b43f2d10db1653a32a82fefe4087b Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:52:35 +0300 Subject: [PATCH 5/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 743f0ee15f..0e86411d28 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -67,15 +67,15 @@ def set_the_performance_dict(self): r' \S+ s/step (?P\S+) ' r'days/ns \S+ MB memory', self.stdout, 'days_ns', float)), - 'days/ns')} + 'days/ns')} @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + sn.extractall( + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From 405ea87130d429a3f722de3fb9f74765e1d03ad7 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:54:53 +0300 Subject: [PATCH 6/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 0e86411d28..5f4e4011bc 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -67,15 +67,14 @@ def set_the_performance_dict(self): r' \S+ s/step (?P\S+) ' r'days/ns \S+ MB memory', self.stdout, 'days_ns', float)), - 'days/ns')} + 'days/ns')} @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): - return sn.avg( - sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + return sn.avg(sn.extractall( + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From cf857e350a70cec0af6beb209f2da9392b1444e1 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:55:44 +0300 Subject: [PATCH 7/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 5f4e4011bc..7ad8688e04 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -72,9 +72,9 @@ def set_the_performance_dict(self): @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg(sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From 4c925a637a1061987fbbb1a0a4b75636f96449c8 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:56:42 +0300 Subject: [PATCH 8/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 7ad8688e04..94f945a5b5 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -72,9 +72,9 @@ def set_the_performance_dict(self): @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg(sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self): From 3a7e98bbc6b467b7ab165e1e9f8dc05a71fa6275 Mon Sep 17 00:00:00 2001 From: Sergei Kliavinek Date: Thu, 9 Sep 2021 16:57:13 +0300 Subject: [PATCH 9/9] fix problems with indents --- hpctestlib/apps/namd/base_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hpctestlib/apps/namd/base_check.py b/hpctestlib/apps/namd/base_check.py index 94f945a5b5..06c610cb5f 100644 --- a/hpctestlib/apps/namd/base_check.py +++ b/hpctestlib/apps/namd/base_check.py @@ -72,9 +72,9 @@ def set_the_performance_dict(self): @performance_function('days/ns', perf_key='perf') def set_perf_patterns(self): return sn.avg(sn.extractall( - r'Info: Benchmark time: \S+ CPUs \S+ ' - r's/step (?P\S+) days/ns \S+ MB memory', - self.stdout, 'days_ns', float)) + r'Info: Benchmark time: \S+ CPUs \S+ ' + r's/step (?P\S+) days/ns \S+ MB memory', + self.stdout, 'days_ns', float)) @sanity_function def assert_energy_readout(self):