diff options
author | 2012-08-06 00:56:55 +0200 | |
---|---|---|
committer | 2012-08-06 01:02:22 +0200 | |
commit | f4ebe8fa598045dae33a1dc160d231c193f59004 (patch) | |
tree | 15b02da22026d27e72bf094fc733b1a4d341f72d | |
parent | Cleaned modules. (diff) | |
download | auto-numerical-bench-f4ebe8fa598045dae33a1dc160d231c193f59004.tar.gz auto-numerical-bench-f4ebe8fa598045dae33a1dc160d231c193f59004.tar.bz2 auto-numerical-bench-f4ebe8fa598045dae33a1dc160d231c193f59004.zip |
Input parser, initializations, code cleanup.0.2_beta4
The old parser has been removed. Now only xml input is supported.
xmlinput now has a class Parser. Module name and arguments are now
present in the configuration file. Informations can be retrived
separately from the file.
benchconfig initialization is now splitted in functions that are called
from within main.py. the same happens in benchprint. benchconfig now
explicitly defines all the variables.
In general, some clean up has been done and some warnings have been
suppressed.
-rwxr-xr-x | exec.py | 4 | ||||
-rw-r--r-- | numbench/benchchildren.py | 10 | ||||
-rw-r--r-- | numbench/benchconfig.py | 114 | ||||
-rw-r--r-- | numbench/benchprint.py | 79 | ||||
-rw-r--r-- | numbench/confinput/__init__.py | 11 | ||||
-rw-r--r-- | numbench/confinput/oldinput.py | 69 | ||||
-rw-r--r-- | numbench/confinput/xmlinput.py | 159 | ||||
-rw-r--r-- | numbench/main.py | 104 | ||||
-rw-r--r-- | numbench/report.py | 44 | ||||
-rw-r--r-- | numbench/reports/html.py | 6 | ||||
-rw-r--r-- | numbench/utils/benchutils.py | 18 | ||||
-rw-r--r-- | numbench/utils/envread.py | 4 | ||||
-rw-r--r-- | numbench/utils/portageutils.py | 30 | ||||
-rw-r--r-- | numbench/xmlinput.py | 170 |
14 files changed, 408 insertions, 414 deletions
@@ -18,4 +18,6 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -import numbench.main
\ No newline at end of file +#@PydevCodeAnalysisIgnore + +import numbench.main diff --git a/numbench/benchchildren.py b/numbench/benchchildren.py index 1686639..9f27979 100644 --- a/numbench/benchchildren.py +++ b/numbench/benchchildren.py @@ -15,16 +15,14 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -try: - copy = procs - del copy -except: + +if 'procs' not in locals(): procs = [] - + def terminate(): for p in procs: if p.poll() is None: p.kill() def append(proc): - procs.append(proc)
\ No newline at end of file + procs.append(proc) diff --git a/numbench/benchconfig.py b/numbench/benchconfig.py index e7cc62a..dc6e9b4 100644 --- a/numbench/benchconfig.py +++ b/numbench/benchconfig.py @@ -18,13 +18,77 @@ import sys, os, time, subprocess as sp from os.path import join as pjoin -if not locals().has_key('initialized'): - initialized = True - isroot = os.getuid() == 0 +# Arguments +arguments = None +inputfile = None +clean = None +imageformat = None + +# Directories +curdir = None +scriptdir = None +btldir = None +libdir = None + +# Storage directories +basedir = None +testsdir = None +rootsdir = None +pkgsdir = None +reportdir = None +logdir = None + +# Module +module = None +modulename = None +moduleargs = None + +# Other +isroot = not os.getuid() +tests = None + + +def parseArguments(): + global arguments, inputfile, clean, imageformat, basedir + + arguments = [] + clean = False + imageformat = 'svg' + + + skipargs = 0 + for i, a in enumerate(sys.argv[1:], 1): + if skipargs > 0: + skipargs -= 1 + continue + + if a[0] != '-': + inputfile = os.path.realpath(a) + continue + + if a in ('-d', '--directory'): + basedir = pjoin(curdir, sys.argv[i + 1]) + skipargs += 1 + continue + + if a in ('-c', '--clean'): + clean = True + continue + + if a in ('-i', '--imageformat'): + imageformat = sys.argv[i + 1] + skipargs += 1 + continue + + arguments.append(a) + + + +def setDirs(): + global curdir, scriptdir, btldir, libdir, basedir + global testsdir, rootsdir, pkgsdir, reportdir, logdir - modulename = sys.argv[1] - inputfile = os.path.realpath(sys.argv[2]) # Script directories curdir = os.path.abspath('.') @@ -43,42 +107,15 @@ if not locals().has_key('initialized'): else: libdir = 'usr/' + libdir - # Parse arguments - passargs = [] - skipargs = 0 - for i,a in enumerate(sys.argv[3:], 3): - if skipargs > 0: - skipargs -= 1 - continue - - if a in ('-d', '--directory'): - basedir = pjoin(curdir, sys.argv[i+1]) - skipargs += 1 - continue - - if a in ('-c', '--clean'): - clean = True - continue - - if a in ('-i', '--imageformat'): - imageformat = sys.argv[i+1] - skipargs += 1 - continue - - passargs.append(a) - - # Clean flag - if not locals().has_key('clean'): - clean = False - - # Image format - if not locals().has_key('imageformat'): - imageformat = 'svg' - # Storage directories - if not locals().has_key('basedir'): + if basedir is None: + if modulename is None: + raise RuntimeError("Module is not defined") + basedirb = pjoin(os.environ['HOME'], '.numbench') \ + '/numbench_' + modulename + '_' + time.strftime('%Y-%m-%d') + + # Find suitable base directory if os.path.exists(basedirb): n = 1 while True: @@ -92,4 +129,3 @@ if not locals().has_key('initialized'): testsdir, rootsdir, pkgsdir, reportdir, logdir = tuple([pjoin(basedir, i) \ for i in ('tests', 'roots', 'packages', 'report', 'log')]) - diff --git a/numbench/benchprint.py b/numbench/benchprint.py index 0cbd0b6..8ccd0e8 100644 --- a/numbench/benchprint.py +++ b/numbench/benchprint.py @@ -15,46 +15,43 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -try: - needsinitialization = not initialized -except NameError: - needsinitialization = True - - -if needsinitialization: - import benchconfig as cfg - from utils import benchutils as bu - from os.path import dirname, join as pjoin - - class _Print: - def __init__(self, logfile, maxlevel=10): - self._level = 0 - self._maxlevel = maxlevel - self._logfile = logfile - - def __call__(self, arg='', end='\n'): - printstr = str(arg) + end - if self._level > 0: - printstr = (self._level-1)*" " + "-- " + printstr - - # Print to logfile - bu.mkdir(dirname(self._logfile)) - logfile = file(self._logfile, 'a') - print >> logfile, printstr, - logfile.close() - - # Print to terminal - if self._level <= self._maxlevel: - print printstr, - - def up(self, n=1): - self._level = max(self._level-n, 0) - - def down(self, n=1): - self._level = max(self._level+n, 0) - - # Initialize main Print object ("static") - Print = _Print(pjoin(cfg.logdir, 'main.log'), 3) +import benchconfig as cfg +from utils import benchutils as bu +from os.path import dirname, join as pjoin + +class _Print: + def __init__(self, logfile, maxlevel=10): + self._level = 0 + self._maxlevel = maxlevel + self._logfile = logfile + + def __call__(self, arg='', end='\n'): + printstr = str(arg) + end + if self._level > 0: + printstr = (self._level - 1) * " " + "-- " + printstr + + # Print to logfile + bu.mkdir(dirname(self._logfile)) + logfile = file(self._logfile, 'a') + print >> logfile, printstr, + logfile.close() + + # Print to terminal + if self._level <= self._maxlevel: + print printstr, + + def up(self, n=1): + self._level = max(self._level - n, 0) + + def down(self, n=1): + self._level = max(self._level + n, 0) + +# Uninitialized object (wait for argument parsing, directories lookup,... ) +Print = None + +def initializePrint(): + global Print + Print = _Print(pjoin(cfg.logdir, 'main.log'), 3) -initialized = True + return Print diff --git a/numbench/confinput/__init__.py b/numbench/confinput/__init__.py deleted file mode 100644 index 4fbee33..0000000 --- a/numbench/confinput/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from os.path import basename - -def parseInput(fname): - term = basename(fname).rsplit('.')[-1] - - if term.lower() == 'xml': - import xmlinput as parser - else: - import oldinput as parser - - return parser.parseConf(fname)
\ No newline at end of file diff --git a/numbench/confinput/oldinput.py b/numbench/confinput/oldinput.py deleted file mode 100644 index 8d903c0..0000000 --- a/numbench/confinput/oldinput.py +++ /dev/null @@ -1,69 +0,0 @@ -def readEnvFile(fname): - """Reads a bash file with void environment and returns the environment - at the end of the execution.""" - proc = sp.Popen('. '+fname+' &> /dev/null; env', \ - shell=True, stdout=sp.PIPE, env={}) - lines = proc.stdout.read().split('\n')[:-1] - env = dict([l.split('=', 1) for l in lines]) - - for k in ('SHLVL', 'PWD', '_'): - if env.has_key(k): - del env[k] - return env - -def parseConf(fname): - input = file(fname).read() - - tests = {} - for line in input.split('\n'): - line = line.strip() - spl = [i.strip() for i in shlex.split(line)] - if len(spl) < 2: - continue - if line[0] == '#': - continue - env = {} - skip = [] - change = {} - descr = None - fileenv = {} - - # Interpret arguments - for var in spl[2:]: - - # if begins with '-': skip implementation - if var[0] == '-': - skip.append(var[1:]) - - # if key:value, substitute pkg-config dependency - elif ':' in var and not '=' in var: - c_0, c_1 = var.split(':', 1) - change[c_0] = c_1 - - # if descr|text set description (for future use) - elif var[:6] == 'descr|': - descr = var[6:] - - # if @file: read bash script and set env - elif var[0] == '@': - fileenvNew = readEnvFile(pjoin(cfg.curdir, var[1:])) - fileenv = dict( fileenv.items() + fileenvNew.items() ) - del fileenvNew - - # Otherwise, assume key=value syntax - else: - e_0, e_1 = var.split('=', 1) - env[e_0] = e_1 - - # Set environment (argument overrides bash file) - env = dict( fileenv.items() + env.items() ) - - try: - # Insert test - avail = available_packages(spl[1])[-1] - tests[spl[0]] = {'package':avail , 'emergeenv':env, 'skip':skip, \ - 'requires':change, 'descr':descr} - except: - # Or trigger an non-fatal error - sys.stderr.write('Error: package ' + spl[1] + ' not found\n') - return tests
\ No newline at end of file diff --git a/numbench/confinput/xmlinput.py b/numbench/confinput/xmlinput.py deleted file mode 100644 index cb82e5c..0000000 --- a/numbench/confinput/xmlinput.py +++ /dev/null @@ -1,159 +0,0 @@ -import xml.dom.minidom -import sys, os, portage, types -import subprocess as sp -from os.path import join as pjoin, dirname as pdirname, realpath as prealpath - -from .. import benchconfig as cfg -from ..utils import portageutils as pu - - -def readFile(fs): - result = {} - - # If fs is a filename, open it - if type(fs) != types.FileType: - fs = file(pjoin(cfg.curdir, fs)) - - # Read line by line - for l in fs.readlines(): - try: - k,v = l.split('=', 1) - result[k.strip()] = v.strip() - except: - pass - - return result - - -def readScript(fname): - fname = pjoin(cfg.curdir, fname) - - # Execute script with void environment - proc = sp.Popen('. ' + fname + ' &> /dev/null; env', shell=True, - stdout=sp.PIPE, env={}) - result = readFile(proc.stdout) - - # Remove useless variables - for k in ('SHLVL', 'PWD', '_'): - if result.has_key(k): - del result[k] - return result - -def getEnvFromNode(node, envName): - envs = node.getElementsByTagName(envName) - - # Check number of envs - if len(envs) > 1: - errstr = "Error: no more than one " + envName + " element is allowed!" - raise Exception(errstr) - elif len(envs) < 1: - return {} - - e = envs[0] - - # Check attribute "append" - if (e.attributes.has_key('append')): - append = e.attributes['append'].value == '1' - else: - append = False - - if append: - env = os.environ - else: - env = {} - - # Check attribute script - # the script is run with a void environment - if (e.attributes.has_key('script')): - for k,v in readScript(e.getAttribute('script')).items(): - env[k] = v - - # Check attribute file - # the file must contain lines with key=value pairs (each line one pair) - if (e.attributes.has_key('file')): - for k,v in readFile(e.getAttribute('file')).items(): - env[k] = v - - # Get Variables - for v in e.getElementsByTagName('var'): - envname = v.getAttribute('name') - envvalue = v.firstChild.data - env[envname] = envvalue - - return env - - -def parseConf(fname): - testNodes = xml.dom.minidom.parse(fname).getElementsByTagName('test') - - tests = {} - - for t in testNodes: - tid = t.getAttribute('id') - - # Get description - descr = None - if len(t.getElementsByTagName('descr')) != 0: - descr = t.getElementsByTagName('descr')[0].firstChild.data - - # Get package - pkg = portage.catpkgsplit( - t.getElementsByTagName('pkg')[0].firstChild.data) - normPkg = pu.normalize_cpv(pkg) - - # Skip implementations - skip = [] - skipre = [] - for s in t.getElementsByTagName('skip'): - if not s.hasAttribute('type') or s.getAttribute('type') == 'glob': - skip.append(s.firstChild.data) - elif s.getAttribute('type') == 'regexp': - skipre.append(s.firstChild.data) - else: - sys.stderr.write('Error in configuration file: skip type ' \ - + s.getAttribute('type') + ' not supported') - - # Requirements - requires = {} - for i in t.getElementsByTagName('required'): - requires[i.getAttribute('name').strip()] = i.firstChild.data.strip() - - # Environments - dependenv = getEnvFromNode(t, 'dependenv') - emergeenv = getEnvFromNode(t, 'emergeenv') - compileenv = getEnvFromNode(t, 'compileenv') - runenv = getEnvFromNode(t, 'runenv') - - # Adjust PATH - if compileenv.has_key('PATH'): - compileenv['PATH'] += ':' + os.environ['PATH'] - else: - compileenv['PATH'] = os.environ['PATH'] - - if runenv.has_key('PATH'): - runenv['PATH'] += ':' + os.environ['PATH'] - else: - runenv['PATH'] = os.environ['PATH'] - - # Build test dictionary - tests[tid] = dict( - descr = descr, - package = pkg, - normalizedPackage = normPkg, - skip = skip, - skipre = skipre, - requires = requires, - - dependenv = dependenv, - emergeenv = emergeenv, - compileenv = compileenv, - runenv = runenv, - - pkgdir = pjoin(cfg.pkgsdir, tid), - archive = pjoin(cfg.pkgsdir, tid, normPkg+'.tbz2'), - root = pjoin(cfg.rootsdir, tid), - testdir = pjoin(cfg.testsdir, tid), - logdir = pjoin(cfg.logdir, tid) - ) - - return tests diff --git a/numbench/main.py b/numbench/main.py index bbd9b1f..3b22701 100644 --- a/numbench/main.py +++ b/numbench/main.py @@ -26,7 +26,7 @@ def close(*args): benchchildren.terminate() Print._level = 0 Print() - Print(80*'-') + Print(80 * '-') Print("INTERRUPT TRIGGERED") Print("Exiting") exit(0) @@ -39,21 +39,31 @@ def print_usage(): def print_help(): - print "Usage: numbench module conffile [options]" + print "Usage: numbench conffile [options]" print " numbench [ -h | --help ]" print " numbench module [ -h | --help ]" print print "Options:" - print " [ -h | --help ] - Display an help message" + print " [ -h | --help ] - Displays an help message." + print + print " [ -d | --directory] dir - Stores the data in the given directory." + print " If not given, a directory in ~/.numbench is chosen." + print + print " [ -c | --clean] - Removes the temporary data." + print + print " [ -i | --imageformat] format - Selects the given format for the" + print " resulting images. Available are png, svg, eps, ps, pdf." + print " Default is svg." print print "Modules:" print " blas - Test BLAS implementations" print " cblas - Test CBLAS implementations" print " lapack - Test LAPACK implementations" - #print " scalapack - Test the ScaLAPACK library" + print " lapacke - Test LAPACK implementations" + print " scalapack - Test the ScaLAPACK library" #print " blas_accuracy - Test BLAS implementations for accuracy" #print " lapack_accuracy - Test LAPACK implementations for accuracy" - #print " fftw - Test the FFTW library" + print " fftw - Test the FFTW library" #print " metis - Test the METIS tools" print print "More information about a module is available through the command:" @@ -61,7 +71,7 @@ def print_help(): def loadModule(modulename): - tmp = __import__('numbench.modules.'+modulename, fromlist = ['Module']) + tmp = __import__('numbench.modules.' + modulename, fromlist=['Module']) # try: # tmp = __import__('numbench.modules.'+modulename, fromlist = ['Module']) # except ImportError as e: @@ -75,15 +85,16 @@ def loadModule(modulename): ## PRINT HELP IF NEEDED # If no argument or '-h' is given, print the help -if len(sys.argv) < 3 or sys.argv[1] in ('-h', '--help'): +if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'): print_help() exit(0) # If requested, print the module help -if sys.argv[2] in ('-h', '--help'): - tmp = loadModule(sys.argv[1]) - tmp.Module.printHelp() - exit(0) +# TODO: print module's help +#if sys.argv[2] in ('-h', '--help'): +# tmp = loadModule(sys.argv[1]) +# tmp.Module.printHelp() +# exit(0) ## BEGIN THE TRUE SCRIPT @@ -93,26 +104,43 @@ import re from fnmatch import fnmatch from os.path import join as pjoin -import benchconfig as cfg, confinput, report +import benchconfig as cfg +from xmlinput import Parser from utils import envread, benchutils as bu, portageutils as pu -from benchprint import Print +import benchprint +## Set-up the run configuration -# Parse the configuration file +# Parse the arguments +cfg.parseArguments() + +# Start configuration parser if not os.path.exists(cfg.inputfile): sys.stderr.write("File not found: " + cfg.inputfile) print_usage() exit(1) -cfg.tests = confinput.parseInput(cfg.inputfile) +parser = Parser(cfg.inputfile) + +# Get module name and arguments +cfg.modulename = parser.getModuleName() +cfg.moduleargs = parser.getModuleArguments() + +# Set-up directories +cfg.setDirs() + +# Get test cases +cfg.tests = parser.getTestCases() + +# Initialize print system +Print = benchprint.initializePrint() # Import the module -mod = loadModule(cfg.modulename).Module(cfg.passargs) -cfg.mod = mod +cfg.module = loadModule(cfg.modulename).Module(cfg.moduleargs) -# Write summary +## Write summary Print._level = 0 -Print(80*'=') +Print(80 * '=') Print("The following tests will be run:") Print("-------------------------------") Print() @@ -126,25 +154,26 @@ for tname, ttest in cfg.tests.items(): if len(ttest['dependenv']) != 0: Print(" - Dependencies emerge environment: " + \ - ' '.join([n+'="'+v+'"' for n,v in ttest['dependenv'].items()])) + ' '.join([n + '="' + v + '"' for n, v in ttest['dependenv'].items()])) if len(ttest['emergeenv']) != 0: Print(" - Emerge environment: " + \ - ' '.join([n+'="'+v+'"' for n,v in ttest['emergeenv'].items()])) + ' '.join([n + '="' + v + '"' for n, v in ttest['emergeenv'].items()])) if len(ttest['compileenv']) != 0: Print(" - Suite compile-time environment: " + \ - ' '.join([n+'="'+v+'"' for n,v in ttest['compileenv'].items()])) + ' '.join([n + '="' + v + '"' for n, v in ttest['compileenv'].items()])) if len(ttest['runenv']) != 0: Print(" - Suite run-time environment: " + \ - ' '.join([n+'="'+v+'"' for n,v in ttest['runenv'].items()])) + ' '.join([n + '="' + v + '"' for n, v in ttest['runenv'].items()])) if len(ttest['skip']) != 0: Print(" - Skip implementations: " + ' '.join(ttest['skip'])) if len(ttest['skipre']) != 0: - Print(" - Skip implementations (regular expressions): " + ' '.join(ttest['skipre'])) + Print(" - Skip implementations (regular expressions): " + \ + ' '.join(ttest['skipre'])) if len(ttest['requires']) != 0: Print(" - Pkg-config requirements substitutions:", '') @@ -153,7 +182,7 @@ for tname, ttest in cfg.tests.items(): Print() Print() -Print(80*'=') +Print(80 * '=') Print() Print("The script is located in the directory " + cfg.scriptdir) Print("The script is run from the directory " + os.path.realpath('.')) @@ -163,8 +192,8 @@ Print("The results will be available in the directory " + cfg.reportdir) Print() -# Main iteration -for tn,(name,test) in enumerate(cfg.tests.items(),1): +## Main iteration +for tn, (name, test) in enumerate(cfg.tests.items(), 1): Print._level = 0 Print("BEGIN TEST %i - %s" % (tn, name)) @@ -198,22 +227,22 @@ for tn,(name,test) in enumerate(cfg.tests.items(),1): # Find implementations impls = [] - for i in mod.getImplementations(test): + for i in cfg.module.getImplementations(test): skip = False - + for s in test['skip']: if fnmatch(i, s): skip = True break - + for s in test['skipre']: if re.search(s, i) != None: skip = True break - + if not skip: impls.append(i) - + test['implementations'] = impls # Automatically add environment @@ -227,7 +256,7 @@ for tn,(name,test) in enumerate(cfg.tests.items(),1): # Run the test suite Print("Testing " + impl) Print.down() - test['results'][impl] = mod.runTest(test, impl) + test['results'][impl] = cfg.module.runTest(test, impl) Print.up() # All implementations tested @@ -235,7 +264,10 @@ for tn,(name,test) in enumerate(cfg.tests.items(),1): print +## End of execution + # Save the results +import report report.saveReport() # Clean up the directories @@ -251,12 +283,12 @@ exit(0) Print._level = 0 Print() # Print instructions -for name,test in cfg.tests.items(): +for name, test in cfg.tests.items(): if not test['emergesuccess']: continue printstr = "Instructions for " + name + ":" Print(printstr) - Print(len(printstr)*'-') + Print(len(printstr) * '-') Print.down() Print("# PKGDIR=" + test['pkgdir'] + " emerge -K '=" + \ test['normalizedPackage'] + "'") @@ -264,7 +296,7 @@ for name,test in cfg.tests.items(): for impl in test['implementations']: Print("Implementation " + impl + ":") Print.down() - mod.instructionsFor(impl) + cfg.module.instructionsFor(impl) Print.up() except: pass diff --git a/numbench/report.py b/numbench/report.py index 5f834db..e0de31a 100644 --- a/numbench/report.py +++ b/numbench/report.py @@ -42,26 +42,26 @@ class Plotter: return else: self.plot = conf['type'] - + # Labels self.xlabel = conf.has_key('xlabel') and conf['xlabel'] or '' self.ylabel = conf.has_key('ylabel') and conf['ylabel'] or '' - + # Initialize markers markers = ('-', '--', 'v', '^', 'o', 's', 'p', 'h', '*', '+', 'x', 'D') colors = ('k', 'r', 'g', 'b', 'c') - self.linestyles = tuple([c+m for m in markers for c in colors]) + self.linestyles = tuple([c + m for m in markers for c in colors]) self.curstyle = 0 - + # Open figure - plt.figure(figsize=(12,9), dpi=300) - - + plt.figure(figsize=(12, 9), dpi=300) + + def addPlot(self, x, y, label): style = self.linestyles[self.curstyle] - self.curstyle = (self.curstyle+1) % len(self.linestyles) + self.curstyle = (self.curstyle + 1) % len(self.linestyles) self.plotf(x, y, style, label=label, hold=True) - + def savePlot(self, fname): plt.legend(loc='best') plt.xlabel(self.xlabel) @@ -69,7 +69,7 @@ class Plotter: plt.grid(True) plt.savefig(fname, format=cfg.imageformat, \ bbox_inches='tight', transparent=True) - + def saveReport(): @@ -90,26 +90,26 @@ def saveReport(): htmlfname = pjoin(cfg.reportdir, 'index.html') html = HTMLreport(htmlfname) - for operation in cfg.mod.getTests(): - + for operation in cfg.module.getTests(): + # Begin plot - p = Plotter(cfg.mod.reportConf()) - - for tid,test in cfg.tests.items(): + p = Plotter(cfg.module.reportConf()) + + for tid, test in cfg.tests.items(): if test.has_key('implementations'): for impl in test['implementations']: - + implres = test['results'][impl] if implres and implres.has_key(operation): resultsFile = implres[operation] - x,y = np.loadtxt(resultsFile, unpack=True) - p.addPlot(x, y, tid+'/'+impl) + x, y = np.loadtxt(resultsFile, unpack=True) + p.addPlot(x, y, tid + '/' + impl) - imgpath = pjoin('images', operation+'.'+cfg.imageformat) + imgpath = pjoin('images', operation + '.' + cfg.imageformat) fname = pjoin(cfg.reportdir, imgpath) p.savePlot(fname) html.addFig(testdescr[operation], image=imgpath) - + # Copy logs and input file copytree(cfg.logdir, pjoin(cfg.reportdir, 'log')) fcopy(cfg.inputfile, pjoin(cfg.reportdir, basename(cfg.inputfile))); @@ -120,13 +120,13 @@ def saveReport(): # Initialize module +# Import matplotlib and use 'Agg' as backend try: - if not locals().has_key('initialized'): + if 'initialized' not in locals(): initialized = True import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt - import numpy as np with_images = True except ImportError: sys.stderr.write('Error: matplotlib and numpy are needed' + \ diff --git a/numbench/reports/html.py b/numbench/reports/html.py index 227de57..5a45c35 100644 --- a/numbench/reports/html.py +++ b/numbench/reports/html.py @@ -22,8 +22,10 @@ from xml.sax.saxutils import escape as xmlescape from .. import benchconfig as cfg class ReportFile: - def __init__(self, fname, title='Benchmarks report', \ - inputfile=pjoin(cfg.reportdir, basename(cfg.inputfile))): + def __init__(self, fname, title='Benchmarks report', inputfile=None): + if inputfile is None: + inputfile = pjoin(cfg.reportdir, basename(cfg.inputfile)) + self.fname = fname self.content = """ <html> diff --git a/numbench/utils/benchutils.py b/numbench/utils/benchutils.py index 1018d72..5a58e35 100644 --- a/numbench/utils/benchutils.py +++ b/numbench/utils/benchutils.py @@ -15,25 +15,25 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # -import os, sys, shutil, string, random +import os, shutil, string, random import subprocess as sp __all__ = ['mkdir', 'tmpfile', 'run_cmd'] -def mkdir(dir): - if not os.path.exists(dir): - os.makedirs(dir) +def mkdir(directory): + if not os.path.exists(directory): + os.makedirs(directory) -def rmdir(dir): - if os.path.isdir(dir): - shutil.rmtree(dir, True) +def rmdir(directory): + if os.path.isdir(directory): + shutil.rmtree(directory, True) -def tmpfile(dir="/var/tmp"): +def tmpfile(directory="/var/tmp"): """Returns the path of a free temporary file within the given directory.""" chars = string.letters + string.digits while True: - fname = os.path.join(dir, random.sample(chars, 10)) + fname = os.path.join(directory, random.sample(chars, 10)) if not os.path.exists(fname): return fname diff --git a/numbench/utils/envread.py b/numbench/utils/envread.py index 126f225..0d7d756 100644 --- a/numbench/utils/envread.py +++ b/numbench/utils/envread.py @@ -17,7 +17,7 @@ # import os, shlex from os.path import isfile, join as pjoin -from ..benchconfig import libdir +from .. import benchconfig as cfg def transformPaths(root, value): paths = value.split(':') @@ -33,7 +33,7 @@ def transformPaths(root, value): def envread(test): # Set default paths path = pjoin(test['root'], 'bin') + ':' + pjoin(test['root'], 'usr/bin') - libpath = pjoin(test['root'], libdir) + libpath = pjoin(test['root'], cfg.libdir) addenv = dict( PATH=path, LIBRARY_PATH=libpath, LD_LIBRARY_PATH=libpath ) # Merge environment diff --git a/numbench/utils/portageutils.py b/numbench/utils/portageutils.py index 6fa864a..8775d42 100644 --- a/numbench/utils/portageutils.py +++ b/numbench/utils/portageutils.py @@ -17,10 +17,12 @@ # import commands as cmd import subprocess as sp -import os, portage, shlex +import os, shlex from os.path import join as pjoin, dirname import benchutils as bu +from portage import catpkgsplit as cps #@UnresolvedImport + class InstallException(Exception): def __init__(self, package, command, logfile): self.package = package @@ -55,7 +57,7 @@ def _getEnv(root='/', envAdds={}): denv['INCLUDE_PATH'] += ':' + os.environ['INCLUDE_PATH'] # Adds - for k,v in envAdds.items(): + for k, v in envAdds.items(): denv[k] = v return denv @@ -67,13 +69,13 @@ def availablePackages(pattern): No test for keywords or mask is performed. The function just returns every matching pattern in the portage tree and installed overlays. """ - return [portage.catpkgsplit(l) \ + return [cps(l) for l in cmd.getoutput('equery -q list -po ' + pattern).split()] def normalize_cpv(cpv): if type(cpv) == type(''): try: - cpv_ = portage.catpkgsplit(cpv) + cpv_ = cps(cpv) cpv_[-1] cpv = cpv_ except: @@ -86,16 +88,16 @@ def normalize_cpv(cpv): def getDependencies(package, env={}, split=False): pkg = normalize_cpv(package) - cmd = ['emerge', '--ignore-default-opts', '='+pkg, '-poq'] + cmd = ['emerge', '--ignore-default-opts', '=' + pkg, '-poq'] proc = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE, env=env) - output = proc.communicate()[0] + output = proc.communicate()[0] if proc.returncode != 0: return [] lines = output.strip().split('\n') if not lines[0]: return [] if split: - return [portage.catpkgsplit(shlex.split(l.strip())[-1]) for l in lines] + return [cps(shlex.split(l.strip())[-1]) for l in lines] else: return [shlex.split(l.strip())[-1] for l in lines] @@ -107,7 +109,7 @@ def installDependencies(test): # Retrieve dependencies deps = getDependencies(test['package'], denv, False) - for i,d in enumerate(deps): + for i, d in enumerate(deps): logfile = pjoin(test['logdir'], 'emergedep_%i.log' % i) installPackage(test, package=d, env=test['dependenv'], logfile=logfile) @@ -160,13 +162,13 @@ def installPackage(test, package=None, env=None, logfile=None): # In case of error, print the whole emerge command raise InstallException(pkg, ' '.join(cmd), logfile) - fout.write('\n\n' + 80*'#' + '\n\n') + fout.write('\n\n' + 80 * '#' + '\n\n') # Unpack package onto root - archive = pjoin(test['pkgdir'], pkg+'.tbz2') + archive = pjoin(test['pkgdir'], pkg + '.tbz2') bu.mkdir(test['root']) tarcmd = ['tar', 'xjvf', archive, '-C', test['root']] - fout.write(' '.join(tarcmd) + '\n' + 80*'-' + '\n') + fout.write(' '.join(tarcmd) + '\n' + 80 * '-' + '\n') p = sp.Popen(tarcmd, stdout=fout, stderr=sp.STDOUT) p.wait() if p.returncode != 0: @@ -175,9 +177,3 @@ def installPackage(test, package=None, env=None, logfile=None): # Close, return fout.close() - -if __name__ == '__main__': - # Just a test - from pprint import pprint - - pprint(get_dependencies('sci-libs/blas-reference-3.3.1-r1')) diff --git a/numbench/xmlinput.py b/numbench/xmlinput.py new file mode 100644 index 0000000..62f8289 --- /dev/null +++ b/numbench/xmlinput.py @@ -0,0 +1,170 @@ +import xml.dom.minidom +import sys, os, portage, types, shlex, subprocess as sp +from os.path import join as pjoin + +import benchconfig as cfg +from utils import portageutils as pu + +class Parser: + def __init__(self, fname): + self._dom = xml.dom.minidom.parse(fname) + + def getModuleName(self): + opTag = self._dom.getElementsByTagName('operations')[0] + return opTag.getAttribute('module') + + def getModuleArguments(self): + opTag = self._dom.getElementsByTagName('operations')[0] + return shlex.split(opTag.firstChild.data) + + def getTestCases(self): + testNodes = self._dom.getElementsByTagName('case') + + tests = {} + + for t in testNodes: + tid = t.getAttribute('id') + + # Get description + descr = None + if len(t.getElementsByTagName('descr')) != 0: + descr = t.getElementsByTagName('descr')[0].firstChild.data + + # Get package + pkg = portage.catpkgsplit(#@UndefinedVariable + t.getElementsByTagName('pkg')[0].firstChild.data) + normPkg = pu.normalize_cpv(pkg) + + # Skip implementations + skip = [] + skipre = [] + for s in t.getElementsByTagName('skip'): + if not s.hasAttribute('type') or s.getAttribute('type') == 'glob': + skip.append(s.firstChild.data) + elif s.getAttribute('type') == 'regexp': + skipre.append(s.firstChild.data) + else: + sys.stderr.write('Error in configuration file: skip type ' \ + + s.getAttribute('type') + ' not supported') + + # Requirements + requires = {} + for i in t.getElementsByTagName('required'): + requires[i.getAttribute('name').strip()] = i.firstChild.data.strip() + + # Environments + dependenv = self._getEnvFromNode(t, 'dependenv') + emergeenv = self._getEnvFromNode(t, 'emergeenv') + compileenv = self._getEnvFromNode(t, 'compileenv') + runenv = self._getEnvFromNode(t, 'runenv') + + # Adjust PATH + if compileenv.has_key('PATH'): + compileenv['PATH'] += ':' + os.environ['PATH'] + else: + compileenv['PATH'] = os.environ['PATH'] + + if runenv.has_key('PATH'): + runenv['PATH'] += ':' + os.environ['PATH'] + else: + runenv['PATH'] = os.environ['PATH'] + + # Build test dictionary + tests[tid] = dict( + descr=descr, + package=pkg, + normalizedPackage=normPkg, + skip=skip, + skipre=skipre, + requires=requires, + + dependenv=dependenv, + emergeenv=emergeenv, + compileenv=compileenv, + runenv=runenv, + + pkgdir=pjoin(cfg.pkgsdir, tid), + archive=pjoin(cfg.pkgsdir, tid, normPkg + '.tbz2'), + root=pjoin(cfg.rootsdir, tid), + testdir=pjoin(cfg.testsdir, tid), + logdir=pjoin(cfg.logdir, tid) + ) + + return tests + + @staticmethod + def _readFile(fs): + result = {} + + # If fs is a filename, open it + if type(fs) != types.FileType: + fs = file(pjoin(cfg.curdir, fs)) + + # Read line by line + for l in fs.readlines(): + try: + k, v = l.split('=', 1) + result[k.strip()] = v.strip() + except: + pass + + return result + + @classmethod + def _readScript(cls, fname): + fname = pjoin(cfg.curdir, fname) + + # Execute script with void environment + proc = sp.Popen('. ' + fname + ' &> /dev/null; env', shell=True, + stdout=sp.PIPE, env={}) + result = cls._readFile(proc.stdout) + + # Remove useless variables + for k in ('SHLVL', 'PWD', '_'): + if result.has_key(k): + del result[k] + return result + + @classmethod + def _getEnvFromNode(cls, node, envName): + envs = node.getElementsByTagName(envName) + + # Check number of envs + if len(envs) > 1: + errstr = "Error: no more than one " + envName + " element is allowed!" + raise Exception(errstr) + elif len(envs) < 1: + return {} + + e = envs[0] + + # Check attribute "append" + if (e.attributes.has_key('append')): + append = e.attributes['append'].value == '1' + else: + append = False + + if append: + env = os.environ + else: + env = {} + + # Check attribute script + # the script is run with a void environment + if (e.attributes.has_key('script')): + for k, v in cls._readScript(e.getAttribute('script')).items(): + env[k] = v + + # Check attribute file + # the file must contain lines with key=value pairs (each line one pair) + if (e.attributes.has_key('file')): + for k, v in cls._readFile(e.getAttribute('file')).items(): + env[k] = v + + # Get Variables + for v in e.getElementsByTagName('var'): + envname = v.getAttribute('name') + envvalue = v.firstChild.data + env[envname] = envvalue + + return env |