summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Arteaga <andyspiros@gmail.com>2012-10-16 12:20:45 +0200
committerAndrea Arteaga <andyspiros@gmail.com>2012-10-16 12:20:45 +0200
commit3d746fa02f581b1421e52f0352b120467fd3467d (patch)
tree4fabffd4430bd89eca881830ec52ba5e143b73e6
parentUpdated LAPACK main program. Updated labels. Updated sample for LAPACK. (diff)
downloadauto-numerical-bench-3d746fa02f581b1421e52f0352b120467fd3467d.tar.gz
auto-numerical-bench-3d746fa02f581b1421e52f0352b120467fd3467d.tar.bz2
auto-numerical-bench-3d746fa02f581b1421e52f0352b120467fd3467d.zip
Added and tested module lapackAccuracy.
-rw-r--r--btl/generic_bench/accuracy.hpp94
-rw-r--r--btl/generic_bench/timers/LinuxTimer.hpp66
-rw-r--r--btl/libs/LAPACK/accuracy.cpp89
-rw-r--r--numbench/modules/__init__.py3
-rw-r--r--numbench/modules/internal/btlBase.py8
-rw-r--r--numbench/modules/internal/lapackAccuracyBase.py64
-rw-r--r--numbench/modules/lapackAccuracy.py28
-rw-r--r--numbench/utils/btl.py118
8 files changed, 408 insertions, 62 deletions
diff --git a/btl/generic_bench/accuracy.hpp b/btl/generic_bench/accuracy.hpp
new file mode 100644
index 0000000..eb3265f
--- /dev/null
+++ b/btl/generic_bench/accuracy.hpp
@@ -0,0 +1,94 @@
+//=====================================================
+// Copyright (C) 2012 Andrea Arteaga <andyspiros@gmail.com>
+//=====================================================
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+#ifndef ACCURACY_HPP
+#define ACCURACY_HPP
+
+#include "timers/LinuxTimer.hpp"
+
+#include <string>
+#include <vector>
+#include <cmath>
+
+template<class Action>
+void bench_accuracy (int size_min, int size_max, int nb_point,
+ bool silent = false)
+{
+ std::string filename = "accuracy_"+Action::name()+".dat";
+
+ if (!silent)
+ std::cout << "starting " << filename << std::endl;
+
+ // Initialization vectors
+ std::vector<double> errors(nb_point);
+ std::vector<double> devs(nb_point);
+ std::vector<int> sizes(nb_point);
+
+ // Initialization timer
+ LinuxTimer timer;
+
+ // Log-distributed sizes
+ size_lin_log(nb_point, size_min, size_max, sizes);
+
+ // Loop on sizes
+ for (int i = nb_point-1; i >= 0; --i) {
+ if (!silent)
+ std::cout << " " << "size = " << sizes[i] << ", " << std::flush;
+
+ // Initialize action with given size
+ Action action(sizes[i]);
+
+ int repetitions = 0;
+ double average = 0., stddev = 0., e;
+
+ // Perform time loop and store average and standard deviation
+ timer.start();
+ do {
+ e = action.getResidual();
+
+ average += e;
+ stddev += e*e;
+ ++repetitions;
+
+ } while(timer.elapsed() < 1.);
+
+ // Compute average and standard deviation
+ average /= repetitions;
+ stddev = std::sqrt(stddev/repetitions - average*average);
+
+ errors[i] = average;
+ devs[i] = stddev;
+
+ // Output
+ if (!silent)
+ std::cout << "average = " << average << ", stddev = " << stddev
+ << std::endl;
+ }
+
+ // Dump the result
+ if (!silent) {
+ std::ofstream outfile(filename.c_str());
+
+ for (int i = 0; i < nb_point; ++i)
+ outfile << sizes[i] << " " << errors[i] << " " << devs[i] << "\n";
+
+ outfile.close();
+
+ }
+}
+
+#endif // ACCURACY_HPP
diff --git a/btl/generic_bench/timers/LinuxTimer.hpp b/btl/generic_bench/timers/LinuxTimer.hpp
new file mode 100644
index 0000000..65bba8c
--- /dev/null
+++ b/btl/generic_bench/timers/LinuxTimer.hpp
@@ -0,0 +1,66 @@
+//=====================================================
+// Copyright (C) 2012 Andrea Arteaga <andyspiros@gmail.com>
+//=====================================================
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+#ifndef LINUXTIMER_HPP
+#define LINUXTIMER_HPP
+
+#include <sys/time.h>
+
+class LinuxTimer
+{
+public:
+ LinuxTimer() : ZERO(0.) { }
+
+ void start()
+ {
+ t = walltime(&ZERO);
+ }
+
+ double elapsed()
+ {
+ return walltime(&t);
+ }
+
+private:
+ double t;
+
+ const double ZERO;
+
+ static double walltime(const double *t0) {
+ double mic;
+ double time;
+ double mega = 0.000001;
+ struct timeval tp;
+ struct timezone tzp;
+ static long base_sec = 0;
+ static long base_usec = 0;
+
+ (void) gettimeofday(&tp, &tzp);
+ if (base_sec == 0){
+ base_sec = tp.tv_sec;
+ base_usec = tp.tv_usec;
+ }
+
+ time = (double)(tp.tv_sec - base_sec);
+ mic = (double)(tp.tv_usec - base_usec);
+ time = (time + mic * mega) - *t0;
+ return(time);
+ }
+};
+
+
+#endif // LINUXTIMER_HPP
diff --git a/btl/libs/LAPACK/accuracy.cpp b/btl/libs/LAPACK/accuracy.cpp
new file mode 100644
index 0000000..6aa7d23
--- /dev/null
+++ b/btl/libs/LAPACK/accuracy.cpp
@@ -0,0 +1,89 @@
+//=====================================================
+// Copyright (C) 2012 Andrea Arteaga <andyspiros@gmail.com>
+//=====================================================
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+
+#include <string>
+#include <iostream>
+
+// Include the numeric interface
+#ifdef NI_LAPACK
+# define NI_FORTRAN
+#endif
+
+#include "NumericInterface.hpp"
+
+typedef NumericInterface<double> Interface;
+
+// Include the BTL
+#include "utilities.h"
+#include "bench.hh"
+#include "accuracy.hpp"
+
+// Include the operations
+#include "actionsLAPACK.hpp"
+
+
+using namespace std;
+
+BTL_MAIN;
+
+int main(int argv, char **argc)
+{
+ bool
+ do_GeneralSolve=false, do_LeastSquaresSolve=false,
+
+ do_LUdecomp=false, do_Choleskydecomp=false, do_QRdecomp=false
+ ;
+
+ int N = 100;
+
+
+ for (int i = 1; i < argv; ++i) {
+ std::string arg = argc[i];
+
+ if (arg == "GeneralSolve") do_GeneralSolve = true;
+ else if (arg == "LeastSquaresSolve") do_LeastSquaresSolve = true;
+
+ else if (arg == "LUdecomp") do_LUdecomp= true;
+ else if (arg == "Choleskydecomp") do_Choleskydecomp= true;
+ else if (arg == "QRdecomp") do_QRdecomp= true;
+
+ // Check switch -N
+ else if (arg[0] == '-' && arg[1] == 'N') {
+ if (arg[2] != '\0')
+ N = atoi(arg.c_str()+2);
+ else
+ N = atoi(argc[++i]);
+ }
+ }
+
+ if (do_GeneralSolve)
+ bench_accuracy<Action_GeneralSolve<Interface> >(MIN_MM,MAX_MM, N);
+ if (do_LeastSquaresSolve)
+ bench_accuracy<Action_LeastSquaresSolve<Interface> >(MIN_MM,MAX_MM, N);
+
+ if(do_LUdecomp)
+ bench_accuracy<Action_LUdecomp<Interface> >(MIN_MM,MAX_MM, N);
+ if(do_Choleskydecomp)
+ bench_accuracy<Action_Choleskydecomp<Interface> >(MIN_MM,MAX_MM, N);
+ if(do_QRdecomp)
+ bench_accuracy<Action_QRdecomp<Interface> >(MIN_MM,MAX_MM, N);
+
+
+ return 0;
+}
+
diff --git a/numbench/modules/__init__.py b/numbench/modules/__init__.py
index 5b7cd3c..a734d3b 100644
--- a/numbench/modules/__init__.py
+++ b/numbench/modules/__init__.py
@@ -25,7 +25,8 @@ modnames = [
'lapack',
'lapacke',
'scalapack',
- 'fftw'
+ 'fftw',
+ 'lapackAccuracy'
]
diff --git a/numbench/modules/internal/btlBase.py b/numbench/modules/internal/btlBase.py
index 6b9fea1..edd2a50 100644
--- a/numbench/modules/internal/btlBase.py
+++ b/numbench/modules/internal/btlBase.py
@@ -24,9 +24,13 @@ def reportConf(*args):
def runTest(self, test, btlconfig):
+ fnameprefix = btlconfig.get('fnameprefix', 'bench')
+
+ fname = lambda j : fnameprefix + '_' + j + '_' + self.libname + '.dat'
+
# Check if results already exist
- tmpres = dict( \
- [(i, pjoin(btlconfig['testdir'], 'bench_'+i+'_'+self.libname+'.dat')) \
+ tmpres = dict(\
+ [(i, pjoin(btlconfig['testdir'], fname(i))) \
for i in btlconfig['tests']])
if all([exists(i) for i in tmpres.values()]):
diff --git a/numbench/modules/internal/lapackAccuracyBase.py b/numbench/modules/internal/lapackAccuracyBase.py
new file mode 100644
index 0000000..6a72a32
--- /dev/null
+++ b/numbench/modules/internal/lapackAccuracyBase.py
@@ -0,0 +1,64 @@
+#=====================================================
+# Copyright (C) 2012 Andrea Arteaga <andyspiros@gmail.com>
+#=====================================================
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+import numbench.utils.btl as btl
+import numbench.utils.alternatives as alt
+import btlBase
+from os.path import join as pjoin
+
+
+availableTests = ('GeneralSolve', 'LeastSquaresSolve',
+ 'LUdecomp', 'Choleskydecomp', 'QRdecomp')
+defaultTests = ('GeneralSolve', 'LUdecomp', 'Choleskydecomp')
+
+
+def init(self, args):
+ self.tests = btl.selectTests(availableTests, args)
+ if len(self.tests) == 0:
+ self.tests = defaultTests
+
+
+def getImplementations(self, test):
+ return alt.getImplementations(test['root'], self.libname)
+
+
+def runTest(self, test, implementation):
+ # Set up btlconfig
+ btlconfig = dict (
+ source='libs/LAPACK/accuracy.cpp',
+ exe=pjoin(test['testdir'], implementation, 'test'),
+ logdir=pjoin(test['logdir'], implementation),
+ testdir=pjoin(test['testdir'], implementation),
+ btlincludes=('libs/LAPACK',),
+ defines=("NI_NAME=" + self.libname, "NI_" + self.libname.upper()),
+ flags=alt.getFlags(test, self.libname, implementation),
+ tests = self.tests,
+ fnameprefix = 'accuracy'
+ )
+
+ return btlBase.runTest(self, test, btlconfig)
+
+getTests = btlBase.getTests
+reportConf = btlBase.reportConf
+
+def reportConf(*args):
+ return dict(
+ xscale='log',
+ yscale='log',
+ xlabel='size',
+ ylabel='relative error'
+ )
diff --git a/numbench/modules/lapackAccuracy.py b/numbench/modules/lapackAccuracy.py
new file mode 100644
index 0000000..ad805a9
--- /dev/null
+++ b/numbench/modules/lapackAccuracy.py
@@ -0,0 +1,28 @@
+#=====================================================
+# Copyright (C) 2012 Andrea Arteaga <andyspiros@gmail.com>
+#=====================================================
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+import internal.lapackAccuracyBase as base
+
+class Module:
+ libname = 'lapack'
+ descr = 'Accuracy test module for LAPACK implementations'
+
+ __init__ = base.init
+ getImplementations = base.getImplementations
+ runTest = base.runTest
+ getTests = base.getTests
+ reportConf = base.reportConf
diff --git a/numbench/utils/btl.py b/numbench/utils/btl.py
index cc0a7fe..9888e14 100644
--- a/numbench/utils/btl.py
+++ b/numbench/utils/btl.py
@@ -30,32 +30,32 @@ btldefines = ('NDEBUG',)
def compileTest(test, btlconfig):
-
+
# Include directories
includes = [pjoin(cfg.btldir, i) for i in btlincludes]
if btlconfig.has_key('btlincludes'):
includes += [pjoin(cfg.btldir, i) for i in btlconfig['btlincludes']]
if btlconfig.has_key('includes'):
includes += btlconfig['includes']
-
+
# Linked libraries
libraries = list(btllibraries)
if btlconfig.has_key('libraries'):
libraries += btlconfig['libraries']
-
+
# Library directories
libdirs = [pjoin(test['root'], cfg.libdir)]
if btlconfig.has_key('libdirs'):
libdirs += btlconfig['libdirs']
-
+
# Defined preprocessor macros
defines = list(btldefines)
if btlconfig.has_key('defines'):
defines += btlconfig['defines']
-
+
# Other flags
flags = []
-
+
# Interpret flags
interpret = shlex.split(bu.run_cmd(['portageq', 'envvar', 'CXXFLAGS']))
if btlconfig.has_key('flags'):
@@ -71,81 +71,81 @@ def compileTest(test, btlconfig):
else:
flags.append(flag)
del interpret
-
-
+
+
# Set compile-time environment
compileenv = test['compileenv'].copy()
-
+
if compileenv.has_key('INCLUDE_PATH'):
compileenv['INCLUDE_PATH'] += ':' + ':'.join(includes)
else:
compileenv['INCLUDE_PATH'] = ':'.join(includes)
-
+
libenv = ':'.join(libdirs)
if compileenv.has_key('LIBRARY_PATH'):
compileenv['LIBRARY_PATH'] += ':' + libenv
else:
compileenv['LIBRARY_PATH'] = libenv
-
+
if compileenv.has_key('LD_LIBRARY_PATH'):
compileenv['LD_LIBRARY_PATH'] += ':' + libenv
else:
compileenv['LD_LIBRARY_PATH'] = libenv
-
+
pathenv = ':'.join([pjoin(test['root'], l) for l in ('bin', 'usr/bin')])
if compileenv.has_key('PATH'):
compileenv['PATH'] += pathenv
else:
compileenv['PATH'] = pathenv
-
+
# Set run-time environment
runenv = test['runenv'].copy()
-
+
if runenv.has_key('LD_LIBRARY_PATH'):
runenv['LD_LIBRARY_PATH'] += ':' + libenv
else:
runenv['LD_LIBRARY_PATH'] = libenv
-
+
pathenv = ':'.join([pjoin(test['root'], l) for l in ('bin', 'usr/bin')])
if runenv.has_key('PATH'):
runenv['PATH'] += pathenv
else:
runenv['PATH'] = pathenv
-
+
btlconfig['runenv'] = runenv
-
-
+
+
# Set C++ compiler
cxx = '/usr/bin/g++'
-
+
portageq_cxx = bu.run_cmd(['portageq', 'envvar', 'CXX'])
if portageq_cxx.strip() != "":
cxx = portageq_cxx
del portageq_cxx
-
+
if btlconfig.has_key('CXX'):
cxx = btlconfig['CXX']
-
+
if compileenv.has_key('CXX'):
cxx = compileenv['CXX']
-
-
+
+
# Form command-line arguments
args = [cxx, pjoin(cfg.btldir, btlconfig['source']), '-o', btlconfig['exe']]
- args += ['-I'+I for I in includes]
- args += ['-l'+l for l in libraries]
- args += ['-L'+L for L in libdirs]
- args += ['-D'+D for D in defines]
+ args += ['-I' + I for I in includes]
+ args += ['-l' + l for l in libraries]
+ args += ['-L' + L for L in libdirs]
+ args += ['-D' + D for D in defines]
args += flags
-
+
# Open logfile and write environment
bu.mkdir(btlconfig['logdir'])
logfile = pjoin(btlconfig['logdir'], "btlCompile.log")
logfs = file(logfile, 'w')
- logfs.write('\n'.join([n+'='+v for n,v in compileenv.items()]))
- logfs.write(3*'\n' + ' '.join(args) + 3*'\n')
+ logfs.write('\n'.join([n + '=' + v for n, v in compileenv.items()]))
+ logfs.write(3 * '\n' + ' '.join(args) + 3 * '\n')
logfs.flush()
-
+
# Execute compilation
bu.mkdir(dirname(btlconfig['exe']))
proc = sp.Popen(args, stdout=logfs, stderr=sp.STDOUT, env=compileenv)
@@ -156,7 +156,7 @@ def compileTest(test, btlconfig):
logfs.write("\n\n<<< Compilation terminated successfully >>>")
else:
logfs.write("\n\n<<< Compilation failed >>>")
-
+
# Close, return
logfs.close()
return retcode
@@ -167,30 +167,30 @@ def runTest(test, btlconfig):
runenv = btlconfig['runenv']
if not runenv.has_key('BTL_CONFIG'):
runenv['BTL_CONFIG'] = '--real'
-
+
# Check linking
logfs = file(pjoin(btlconfig['logdir'], 'btlLinking.log'), 'w')
sp.Popen(['ldd', '-v', btlconfig['exe']], stdout=logfs, env=runenv).wait()
logfs.close()
-
-
+
+
# Prepare arguments
args = (btlconfig['exe'],) + tuple(btlconfig['tests'])
if btlconfig.has_key('preargs'):
args = tuple(btlconfig['preargs']) + args
if btlconfig.has_key('postargs'):
args = args + tuple(btlconfig['postargs'])
-
+
# Open log
logfs = file(pjoin(btlconfig['logdir'], "btlRun.log"), 'w')
- logfs.write('\n'.join([n+'='+v for n,v in runenv.items()]))
- logfs.write(3*'\n' + ' '.join(args) + 3*'\n')
+ logfs.write('\n'.join([n + '=' + v for n, v in runenv.items()]))
+ logfs.write(3 * '\n' + ' '.join(args) + 3 * '\n')
logfs.flush()
-
+
# Error log
errfname = pjoin(btlconfig['logdir'], "btlRun.err")
errfs = file(errfname, 'w')
-
+
# Open pipe
try:
proc = sp.Popen(args, bufsize=1, stdout=sp.PIPE, stderr=errfs, \
@@ -200,36 +200,36 @@ def runTest(test, btlconfig):
Print('Execution failed to start')
Print('Command line: ' + ' '.join(args))
return -1, None
-
-
+
+
result = {}
-
+
# Interpret output
Print('Begin execution')
while True:
# Use regexps to see which operation is benchmarked now
linere = \
- r'.*/bench.hh \[[0-9]*?] : starting (bench_(.*)_[a-zA-Z0-9]*.dat)'
+ r'.*starting ([a-zA-Z]*_(.*)_[a-zA-Z0-9]*.dat)'
operation = None
while operation is None:
line = proc.stdout.readline()
if not line:
break
-
+
try:
resfile, operation = re.match(linere, line).groups()
logfs.write(line)
except:
pass
-
+
# Check is program is terminated
if operation is None:
break
-
+
result[operation] = pjoin(btlconfig['testdir'], resfile)
Print(operation + " -> " + resfile)
-
-
+
+
# Many different sizes for each operation test
Print.down()
cur = 0
@@ -243,7 +243,7 @@ def runTest(test, btlconfig):
return 1, None
logfs.write(outline)
logfs.flush()
-
+
# Interpret line
outline = outline.strip()
try:
@@ -253,25 +253,25 @@ def runTest(test, btlconfig):
except:
cur += 1
Print(outline)
-
-
+
+
Print.up()
proc.wait()
Print("Execution finished with return code " + str(proc.returncode))
-
+
# Close logs
logfs.close()
errp = errfs.tell()
errfs.close()
if errp == 0:
os.unlink(errfname)
-
-
+
+
# Close, return
logfs.close()
return proc.returncode, result
-
-
-
+
+
+
def selectTests(availableTests, args):
- return tuple([i for i in availableTests if i in args])
+ return tuple([i for i in availableTests if i in args])