NeoPZ
test.py
Go to the documentation of this file.
1 #! /usr/bin/env python2.7
2 #***************************************************************************
3 #* Copyright (C) 2013 by Edson Borin *
4 #* edson@ic.unicamp.br *
5 #* *
6 #* This program is free software; you can redistribute it and/or modify *
7 #* it under the terms of the GNU General Public License as published by *
8 #* the Free Software Foundation; either version 2 of the License, or *
9 #* (at your option) any later version. *
10 #* *
11 #* This program is distributed in the hope that it will be useful, *
12 #* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 #* GNU General Public License for more details. *
15 #* *
16 #* You should have received a copy of the GNU General Public License *
17 #* along with this program; if not, write to the *
18 #* Free Software Foundation, Inc., *
19 #* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 #**************************************************************************/
21 
22 import sys
23 import os.path
24 import shlex, subprocess
25 import resource
26 
27 # Try to import rdt and stats modules, if available.
28 import sys
29 # Add the perf_base_dir/scripts/misc to the system path to enable importing misc modules
30 sys.path.append("@PERFTEST_SCRIPTS_SRC_DIR@/misc_modules/")
31 try:
32  import rdt, stats
33  summarize_results=True
34 except ImportError, e:
35  print "WARNING: I wont summarize results because I could not import modules: ", e
36  summarize_results=False
37 
38 # Variables to be defined by cmake
39 builddir="@PERFTEST_BASE_DIR@"
40 datadir="@PERFTEST_SMALL_DATA_DIR@"
41 
42 def error(message, status):
43  sys.stderr.write('ERROR (test.py): '+message+'\n')
44  sys.exit(status)
45 
46 # (rdt_id, rdt_opt, rdt_filename, rdt_description)
47 assfn=("ass", "-ass_rdt", "ass.rdt", "Assemble: dohrstruct->Assemble(...). Assemble element matrices and decompose matrices.")
48 crefn=("cre", "-cre_rdt", "cre.rdt", "Create: dohrstruct->Create()")
49 solfn=("sol", "-sol_rdt", "sol.rdt", "Solver: cg.Solve(...)")
50 totfn=("tot", "-tot_rdt", "tot.rdt", "Total: all the steps")
51 tpzdohrassfn=("dohrass", "-tpz_dohr_ass", "tpzdohrass.rdt", "Assemble element matrices")
52 tpzdohrdecfn=("dohrdec", "-tpz_dohr_dec", "tpzdohrdec.rdt", "Decompose matrices")
53 # List of rdt files produced by the test
54 rdtfiles_l=[assfn, crefn, solfn, totfn, tpzdohrassfn, tpzdohrdecfn]
55 
56 # Setup the command line
57 def setup_cmd():
58  # Check build directory
59  if not os.path.isdir(builddir) :
60  error(builddir+' is an invalid build directory.', 5)
61  # Check run directory
62  rundir = os.path.join(builddir,'scripts','substruct_tst14')
63  if not os.path.isdir(rundir) :
64  error(rundir+' is an invalid run directory.', 1)
65  if not os.path.isdir(builddir) :
66  error(builddir+' is an invalid build directory.', 1)
67  # Check executable
68  executable=os.path.join(builddir,"progs","substruct", "substruct-perf")
69  if not os.path.isfile(executable) :
70  error(executable+' is an invalid executable file name.', 1)
71  # Check input file
72  inputfn = os.path.join(datadir,"substruct","inputs","Cubo986.msh")
73  if not os.path.isfile(inputfn) :
74  error(inputfn+' is an invalid input file name.', 1)
75  # Put the arguments together
76  arguments = ' -mc '+inputfn
77  arguments = arguments + ' -p 2'
78  #NUMA aware Dohrman Assembly List thread work objects re-allocation.
79  arguments = arguments + ' -naDALora'
80  #NUMA aware Dohrman Assembly List thread work objects re-allocation threshold.
81  #arguments = arguments + ' -naDALorat 1835008' # 2/2MB(l2) + 6/8MB(l3)
82  #NUMA aware (node round-robin) Dohrman Assembly List thread work scheduling.
83  arguments = arguments + ' -naDALtws'
84  for rdtarg in rdtfiles_l :
85  arguments = arguments + ' ' + rdtarg[1] + ' ' + rdtarg[2]
86  # TODO: Add arguments to enforce output checking!
87  return rundir, executable+arguments
88 
89 # Limits for this test
90 limits = { "cpu" : (resource.RLIMIT_CPU, 3600, "Max CPU time in seconds"),
91 # "nofile": (resource.RLIMIT_NOFILE, 7, "The maximum number of open file descriptors for the current process."),
92 # "rss" : (resource.RLIMIT_RSS, 1024, "The maximum resident set size that should be made available to the process"),
93 # "fsize" : (resource.RLIMIT_FSIZE, 1, "Max size of a file which the process may create"),
94 # "data" : (resource.RLIMIT_DATA, 1024, "The maximum size (in bytes) of the process's heap"),
95 # "nproc" : (resource.RLIMIT_NPROC, 0, "The maximum number of processes the current process may create")
96  }
97 
98 # Set the rlimits of the chidren process (see limits above)
99 # TODO: Improve the handling of sandboxing limits
100 def setlimits():
101  print "Setting resource limit in child"
102  for k, v in limits.iteritems() :
103  resource.setrlimit(v[0], (v[1],v[1]))
104  #print k, " : ", v[0], " => ", v[1]
105 
106 # Sumarizes the RDT (Raw data table) results (generated by the run)
107 def sumarize_rdt_results(rundir) :
108  results = {}
109  # Compute average and confidence interval for each rdt file.
110  for f in rdtfiles_l :
111  k =f[0] # Step name
112  fn=f[2] # RDT file name
113  if summarize_results :
114  try:
115  rdtfn=os.path.join(rundir,fn)
116  rdt_d=rdt.read(rdtfn)
117  elapsed_list=rdt.get_column_values(rdt_d,"ELAPSED")
118  try:
119  av=stats.average(elapsed_list)
120  except stats.StatsError, e:
121  print "WARNING: Could not compute average for results at", fn, "(", e, ")"
122  av=0.0
123  try:
124  ci=stats.conf_int(elapsed_list, 95.0)
125  except stats.StatsError, e:
126  print "WARNING: Could not compute confidence interval for results at", fn, "(", e, ")"
127  ci=0.0
128  except rdt.RdtError, e:
129  print "WARNING: error when summarizing results for", fn, "(", e, ")"
130  av=0.0
131  ci=0.0
132  else :
133  av=0.0
134  ci=0.0
135  results[k]=(av,ci)
136  # erase time files
137  for arq in rdtfiles_l:
138  os.remove(arq[1])
139  return results
140 
141 # Sumarizes the RDT (Raw data table) files information
142 def sumarize_rdt_files(rundir) :
143  results = {}
144  for f in rdtfiles_l :
145  rdt_id = f[0] # Step name
146  rdt_fn = os.path.join(rundir,f[2]) # RDT file name
147  rdt_dsc = f[3] # Description
148  results[rdt_id] = (rdt_fn, rdt_dsc)
149  return results
150 
151 def short_description() : return "substructure -- cubo986.msh -- parallel -- different number of substructures and number of threads with Numa naDALora and naDALtws"
152 
153 # Execute the test.
154 def run_test(ntimes, nsub, thread):
155  rundir,cmd=setup_cmd()
156  print short_description()
157  print "CMD:",cmd
158  # substructures
159  cmd = cmd + " -nsub " + nsub
160  # threads
161  cmd = cmd + ' -nt_a ' + thread
162  cmd = cmd + ' -nt_d ' + thread
163  cmd = cmd + ' -nt_m ' + thread
164  cmd = cmd + ' -nt_sm ' + thread
165  #print cmd
166  args = shlex.split(cmd)
167  sout = subprocess.PIPE # redirect output (before: None)
168  #sout = None
169  serr = None
170  for i in range(ntimes) :
171  p = subprocess.Popen(args, preexec_fn=setlimits, stdout=sout, stderr=serr, cwd=rundir)
172  p.wait()
173  if (p.returncode != 0) :
174  return p.returncode, {}
175  #results = sumarize_rdt_files(rundir)
176  results = sumarize_rdt_results(rundir)
177  return 0, results
178 
179 # Functions for stand alone tests
180 def usage():
181  print "\nUsage: test.py -r [-h]\n"
182  print "\nARGUMENTS"
183  print "\t-r : Run the experiment."
184  print "\nDESCRIPTION"
185  print "\tExecute the substruct tool collecting statistics for the following steps:"
186  print "\t ", assfn[0], ": assembling the system (serial) -- results at", assfn[1]
187  print "\t ", tpzdohrassfn[0], ": assembling (ass part) the system (serial) -- results at", tpzdohrassfn[1]
188  print "\t ", tpzdohrdecfn[0], ": assembling (dec part) the system (serial) -- results at", tpzdohrdecfn[1]
189  print "\t ", crefn[0], ": creating the sytem (serial) -- results at", crefn[1]
190  print "\t ", solfn[0], ": solver (serial) -- results at", solfn[1]
191  print "\t ", totfn[0], ": total -- results at", totfn[1]
192  sys.exit(1)
193 
194 # Main - for stand alone tests only
195 if __name__ == "__main__":
196  import getopt
197  run=0
198  ntimes=1
199  # Process arguments
200  try :
201  opts, extra_args = getopt.getopt(sys.argv[1:], 'rn:h')
202  except getopt.GetoptError, e:
203  error(str(e), 1)
204  for f, v in opts:
205  if f == '-r': run=1
206  elif f == '-n': ntimes=int(v)
207  elif f == '-h': usage()
208 
209  subs = [ "4", "8", "12", "16", "20", "24", "28", "32", "36", "48", "64", "128"]
210  numthreads = [ "1" , "6", "12", "18", "24", "32", "48" , "64"]
211  # Run test
212  if run == 1:
213  for thr in numthreads:
214  print "# Results Summary"
215  print '{0:s}; {1:s}; '.format("nsub", "threads"),
216  for arq in rdtfiles_l:
217  print'{0:s}; {1:s};'.format(arq[0],"err_"+arq[0]),
218  for item in subs:
219  status,results = run_test(ntimes, item, thr)
220  #if status == 0: print "Execution [OK]"
221  if status != 0 : print "Execution [FAILED] (status = ", status, ")"
222  print '\n{0:s}; {1:s};'.format(item, thr ),
223  for k,v in results.iteritems() : print '{0:.2f}; {1:.2f};'.format(v[0], v[1]),
224  print "\n--------------------------------------------"
225  else:
226  print "WARNING: No options provided. (use -h for help)"
def error(message, status)
Definition: test.py:42
def short_description()
Definition: test.py:151
def average(vlist)
Definition: stats.py:45
def conf_int(vlist, conf_level)
Definition: stats.py:59
def run_test(ntimes, nsub, thread)
Definition: test.py:154
def sumarize_rdt_results(rundir)
Definition: test.py:107
def get_column_values(rdt_d, field)
Definition: rdt.py:70
def setup_cmd()
Definition: test.py:57
def read(filename)
Definition: rdt.py:46
def sumarize_rdt_files(rundir)
Definition: test.py:142