@@ -16,79 +16,70 @@ def to_seconds(str):
1616 datetime .strptime ('00:00:00' , '%H:%M:%S' )).total_seconds ()
1717
1818
19- @rfm .parameterized_test (
20- ['serial' , 'gpu' , 24 , 12 , 1 , 1 ],
21- ['serial' , 'mc' , 72 , 36 , 1 , 1 ],
22- ['openmp' , 'gpu' , 24 , 3 , 1 , 4 ],
23- ['openmp' , 'mc' , 72 , 9 , 1 , 4 ],
24- ['mpi' , 'gpu' , 24 , 4 , 3 , 1 ],
25- ['mpi' , 'mc' , 72 , 12 , 3 , 1 ],
26- ['mpi+openmp' , 'gpu' , 24 , 3 , 2 , 2 ],
27- ['mpi+openmp' , 'mc' , 72 , 6 , 3 , 2 ]
28- )
19+ @rfm .simple_test
2920class GREASYCheck (rfm .RegressionTest ):
30- def __init__ (self , variant , partition , num_greasy_tasks , nworkes_per_node ,
31- nranks_per_worker , ncpus_per_worker ):
32- self .valid_systems = ['daint:' + partition , 'dom:' + partition ]
33-
34- self .valid_prog_environs = ['PrgEnv-gnu' ]
35- self .sourcepath = 'tasks_mpi_openmp.c'
36- self .build_system = 'SingleSource'
37-
38- # sleep enough time to distinguish if the files are running in parallel
39- # or not
40- self .sleep_time = 60
21+ configuration = parameter ([('serial' , 'gpu' , 24 , 12 , 1 , 1 ),
22+ ('serial' , 'mc' , 72 , 36 , 1 , 1 ),
23+ ('openmp' , 'gpu' , 24 , 3 , 1 , 4 ),
24+ ('openmp' , 'mc' , 72 , 9 , 1 , 4 ),
25+ ('mpi' , 'gpu' , 24 , 4 , 3 , 1 ),
26+ ('mpi' , 'mc' , 72 , 12 , 3 , 1 ),
27+ ('mpi+openmp' , 'gpu' , 24 , 3 , 2 , 2 ),
28+ ('mpi+openmp' , 'mc' , 72 , 6 , 3 , 2 )])
29+ valid_prog_environs = ['PrgEnv-gnu' ]
30+ sourcepath = 'tasks_mpi_openmp.c'
31+ build_system = 'SingleSource'
32+ executable = 'tasks_mpi_openmp.x'
33+ tasks_file = 'tasks.txt'
34+ greasy_logfile = 'greasy.log'
35+ nnodes = 2
36+
37+ # sleep enough time to distinguish if the files are running in parallel
38+ # or not
39+ sleep_time = 60
40+ use_multithreading = False
41+ modules = ['GREASY' ]
42+ maintainers = ['VH' , 'SK' ]
43+ tags = {'production' }
44+
45+ @run_after ('init' )
46+ def unpack_configuration_parameter (self ):
47+ self .variant , self .partition = self .configuration [0 :2 ]
48+ self .num_greasy_tasks , self .workers_per_node = self .configuration [2 :4 ]
49+ self .ranks_per_worker , self .cpus_per_worker = self .configuration [4 :6 ]
50+
51+ @run_after ('init' )
52+ def set_valid_systems (self ):
53+ self .valid_systems = [f'daint:{ self .partition } ' ,
54+ f'dom:{ self .partition } ' ]
55+
56+ @run_before ('compile' )
57+ def setup_build_system (self ):
4158 self .build_system .cflags = [f'-DSLEEP_TIME={ self .sleep_time :d} ' ]
42- self .variant = variant
43- if variant == 'openmp' :
59+ if self .variant == 'openmp' :
4460 self .build_system .cflags += ['-fopenmp' ]
45- elif variant == 'mpi' :
61+ elif self . variant == 'mpi' :
4662 self .build_system .cflags += ['-D_MPI' ]
47- elif variant == 'mpi+openmp' :
63+ elif self . variant == 'mpi+openmp' :
4864 self .build_system .cflags += ['-fopenmp' , '-D_MPI' ]
4965
50- self . executable = 'tasks_mpi_openmp.x'
51- self . tasks_file = 'tasks.txt'
66+ @ run_before ( 'run' )
67+ def setup_greasy_run ( self ):
5268 self .executable_opts = [self .tasks_file ]
53- self .greasy_logfile = 'greasy.log'
5469 self .keep_files = [self .tasks_file , self .greasy_logfile ]
55- nnodes = 2
56- self .use_multithreading = False
57- self .num_greasy_tasks = num_greasy_tasks
58- self .nworkes_per_node = nworkes_per_node
59- self .nranks_per_worker = nranks_per_worker
60- self .num_tasks_per_node = nranks_per_worker * nworkes_per_node
61- self .num_tasks = self .num_tasks_per_node * nnodes
62- self .num_cpus_per_task = ncpus_per_worker
63- self .sanity_patterns = self .eval_sanity ()
70+ self .num_tasks_per_node = self .ranks_per_worker * self .workers_per_node
71+ self .num_tasks = self .num_tasks_per_node * self .nnodes
72+ self .num_cpus_per_task = self .cpus_per_worker
6473
65- # Reference value is system agnostic
66- # Adding 10 secs of slowdown per greasy tasks
67- # this is to compensate for whenever the systems are full and srun gets
68- # slightly slower
69- refperf = (
70- (self .sleep_time + 10 )* num_greasy_tasks / nworkes_per_node / nnodes
71- )
72- self .reference = {
73- '*' : {
74- 'time' : (refperf , None , 0.5 , 's' )
75- }
76- }
77- self .perf_patterns = {
78- 'time' : sn .extractsingle (r'Total time: (?P<perf>\S+)' ,
79- self .greasy_logfile ,
80- 'perf' , to_seconds )
81- }
74+ @run_before ('run' )
75+ def set_variables (self ):
8276 # On SLURM there is no need to set OMP_NUM_THREADS if one defines
8377 # num_cpus_per_task, but adding for completeness and portability
8478 self .variables = {
8579 'OMP_NUM_THREADS' : str (self .num_cpus_per_task ),
86- 'GREASY_NWORKERS_PER_NODE' : str (nworkes_per_node ),
80+ 'GREASY_NWORKERS_PER_NODE' : str (self . workers_per_node ),
8781 'GREASY_LOGFILE' : self .greasy_logfile
8882 }
89- self .modules = ['GREASY' ]
90- self .maintainers = ['VH' , 'SK' ]
91- self .tags = {'production' }
9283
9384 @run_before ('run' )
9485 def generate_tasks_file (self ):
@@ -114,7 +105,7 @@ def daint_dom_gpu_specific_workaround(self):
114105 }
115106 }
116107 elif self .current_partition .fullname in ['daint:mc' ]:
117- if self .variant != 'serial' :
108+ if self .configuration . variant != 'serial' :
118109 self .extra_resources = {
119110 'gres' : {
120111 'gres' : 'craynetwork:72'
@@ -133,17 +124,19 @@ def set_launcher(self):
133124 # make calls to srun
134125 self .job .launcher = getlauncher ('local' )()
135126
136- @sn . sanity_function
137- def eval_sanity (self ):
127+ @sanity_function
128+ def assert_success (self ):
138129 output_files = []
139130 output_files = [file for file in os .listdir (self .stagedir )
140131 if file .startswith ('output-' )]
141132 num_greasy_tasks = len (output_files )
142133 failure_msg = (f'Requested { self .num_greasy_tasks } task(s), but '
143134 f'executed only { num_greasy_tasks } tasks(s)' )
144- sn .evaluate (sn .assert_eq (num_greasy_tasks , self .num_greasy_tasks ,
145- msg = failure_msg ))
146- num_tasks = sn .getattr (self , 'nranks_per_worker' )
135+ sn .evaluate (
136+ sn .assert_eq (num_greasy_tasks , self .num_greasy_tasks ,
137+ msg = failure_msg )
138+ )
139+ num_tasks = sn .getattr (self , 'ranks_per_worker' )
147140 num_cpus_per_task = sn .getattr (self , 'num_cpus_per_task' )
148141
149142 def tid (match ):
@@ -184,7 +177,7 @@ def num_ranks(match):
184177 lambda x : sn .assert_lt (
185178 rank (x ), num_ranks (x ),
186179 msg = (f'Rank id { rank (x )} is not lower than the '
187- f'number of ranks { self .nranks_per_worker } '
180+ f'number of ranks { self .ranks_per_worker } '
188181 f'in output file' )
189182 ), result
190183 ),
@@ -217,7 +210,7 @@ def num_ranks(match):
217210 lambda x : sn .assert_eq (
218211 num_ranks (x ), num_tasks ,
219212 msg = (f'Number of ranks { num_ranks (x )} is not '
220- f'equal to { self .nranks_per_worker } in '
213+ f'equal to { self .ranks_per_worker } in '
221214 f'output file { output_file } ' )
222215 ), result
223216 )
@@ -234,3 +227,24 @@ def num_ranks(match):
234227 ))
235228
236229 return True
230+
231+ @run_before ('performance' )
232+ def set_perf_patterns (self ):
233+ # Reference value is system agnostic
234+ # Adding 10 secs of slowdown per greasy tasks
235+ # this is to compensate for whenever the systems are full and srun gets
236+ # slightly slower
237+ refperf = (
238+ (self .sleep_time + 10 ) * self .num_greasy_tasks /
239+ self .workers_per_node / self .nnodes
240+ )
241+ self .reference = {
242+ '*' : {
243+ 'time' : (refperf , None , 0.5 , 's' )
244+ }
245+ }
246+ self .perf_patterns = {
247+ 'time' : sn .extractsingle (r'Total time: (?P<perf>\S+)' ,
248+ self .greasy_logfile ,
249+ 'perf' , to_seconds )
250+ }
0 commit comments