diff options
-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 |