summaryrefslogtreecommitdiff
path: root/benchmarks/CUDA/CP/driver
diff options
context:
space:
mode:
authorTor Aamodt <[email protected]>2010-07-15 18:09:46 -0800
committerTor Aamodt <[email protected]>2010-07-15 18:09:46 -0800
commit69f2911e04ffb1b19eef1fafb8c040af271f656e (patch)
tree231d3b6bdc3a202f7c255bfcf7bf2c36e32cee9e /benchmarks/CUDA/CP/driver
creating branch for adding support for CUDA 3.x and Fermi
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829]
Diffstat (limited to 'benchmarks/CUDA/CP/driver')
-rw-r--r--benchmarks/CUDA/CP/driver/__init__.py33
-rw-r--r--benchmarks/CUDA/CP/driver/actions.py109
-rw-r--r--benchmarks/CUDA/CP/driver/benchmark.py374
-rw-r--r--benchmarks/CUDA/CP/driver/futures.py14
-rw-r--r--benchmarks/CUDA/CP/driver/globals.py16
-rw-r--r--benchmarks/CUDA/CP/driver/options.py208
-rw-r--r--benchmarks/CUDA/CP/driver/process.py181
-rw-r--r--benchmarks/CUDA/CP/driver/text.py75
8 files changed, 1010 insertions, 0 deletions
diff --git a/benchmarks/CUDA/CP/driver/__init__.py b/benchmarks/CUDA/CP/driver/__init__.py
new file mode 100644
index 0000000..3b6c38a
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/__init__.py
@@ -0,0 +1,33 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+import sys
+import os
+from itertools import imap
+
+import globals
+import actions
+import options
+
+def run():
+ # Print a banner message
+ print "Parboil parallel benchmark suite, version 0.1"
+ print
+
+ # Global variable setup
+ root_path = os.getcwd()
+ python_path = (os.path.join(root_path,'common','python') +
+ ":" +
+ os.environ.get('PYTHONPATH',""))
+
+ globals.root = root_path
+ globals.benchmarks = benchmark.find_benchmarks()
+ globals.program_env = {'PARBOIL_ROOT':root_path,
+ 'PYTHONPATH':python_path,
+ }
+
+ # Parse options
+ act = options.parse_options(sys.argv)
+
+ # Perform the specified action
+ if act: act()
+
diff --git a/benchmarks/CUDA/CP/driver/actions.py b/benchmarks/CUDA/CP/driver/actions.py
new file mode 100644
index 0000000..8525028
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/actions.py
@@ -0,0 +1,109 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+# These are the main actions that the driver may take. The actions
+# call lower-level routines from the process or benchmark modules.
+
+import os
+from itertools import imap
+
+import process
+import benchmark
+import globals
+from text import format_columns
+
+def benchmark_iter():
+ """Iterate over the benchmarks in 'bmks'."""
+ # bmks is a dictionary from str to Future(Benchmark)
+ return imap(lambda x: x.get(), globals.benchmarks.itervalues())
+
+def list_benchmarks():
+ """List all benchmarks on standard output."""
+ print "Benchmarks:"
+ for bmk in benchmark_iter(): print " " + bmk.name
+
+def describe_benchmarks():
+ """Print descriptions of all benchmarks to standard output."""
+ for bmk in benchmark_iter(): describe_benchmark(bmk)
+
+def describe_benchmark(bmk):
+ """Print a description of one benchmark to standard output."""
+
+ print " " + bmk.name
+ print format_columns(bmk.describe(), 4)
+
+def lookup_benchmark(name):
+ """Find a benchmark, given its name. Returns None if no benchmark
+ is found with the given name or if the benchmark is invalid.
+ If the benchmark cannot be found, an error is printed."""
+ b = globals.benchmarks.get(name)
+ if b is not None:
+ bmk = b.get()
+ if bmk.invalid is None:
+ return bmk
+ else:
+ print "Error in benchmark:"
+ print str(bmk.invalid)
+ return None
+ else:
+ print "Cannot find benchmark"
+ return None
+
+def with_benchmark_named(name, action):
+ """Look up the benchmark named 'name'. If found, apply the action
+ to it. Otherwise, print an error message and return None."""
+
+ bmk = lookup_benchmark(name)
+ if bmk is not None: action(bmk)
+
+def compile_benchmark(bmk, version_name):
+ """Compile the benchmark 'bmk'."""
+ try: impl = bmk.impls[version_name]
+ except KeyError:
+ print "Cannot find benchmark version"
+ return
+
+ impl.build(bmk)
+
+def clean_benchmark(bmk, version_name=None):
+ """Remove the compiled code for one implementation of 'bmk'. If
+ no version is given, clean all versions."""
+
+ if version_name:
+ try: impl = bmk.impls[version_name]
+ except KeyError:
+ print "Cannot find benchmark version"
+ return
+
+ impl.clean(bmk)
+ else:
+ # Clean all versions
+ for impl in bmk.impls.itervalues():
+ impl.clean(bmk)
+
+def run_benchmark(bmk, version_name, input_name, check=True, extra_opts=[]):
+ """Run the benchmark 'bmk'."""
+ try: impl = bmk.impls[version_name]
+ except KeyError:
+ print "Cannot find benchmark version"
+ return
+
+ try: data = bmk.datas[input_name]
+ except KeyError:
+ print "Cannot find data set"
+ return
+
+ # Run the benchmark
+ success = impl.run(bmk, data, check, extra_opts=extra_opts)
+
+ if not success:
+ print "Run failed!"
+ return
+
+ # Verify the output
+ if check:
+ success = impl.check(bmk, data)
+
+ if not success:
+ print "Output checking tool detected a mismatch"
+ else:
+ print "Output was not checked for correctness"
diff --git a/benchmarks/CUDA/CP/driver/benchmark.py b/benchmarks/CUDA/CP/driver/benchmark.py
new file mode 100644
index 0000000..43d7852
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/benchmark.py
@@ -0,0 +1,374 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+import sys
+import os
+from os import path
+import re
+from itertools import imap, repeat, chain
+
+import globals
+import process
+from futures import Future
+
+class Benchmark(object):
+ """A benchmark.
+
+ If the benchmark is malformed or otherwise invalid, only the 'name' and
+ 'invalid' fields will be set. Otherwise all fields will be set.
+
+ Fields:
+ name The name of the benchmark. This is also the benchmark
+ directory name.
+ invalid None if the benchmark is valid; otherwise, an exception
+ describing why the benchmark is invalid.
+ path Full path of the benchmark directory.
+ descr A description of the benchmark.
+ impls A dictionary of benchmark source implementations.
+ datas A dictionary of data sets used to run the benchmark."""
+
+ def __init__(self, name, path = None, impls = [], datasets = [],
+ description=None, invalid=None):
+ self.name = name
+ self.invalid = invalid
+
+ if invalid is None:
+ self.path = path
+ self.impls = dict(imap(lambda i: (i.name, i), impls))
+ self.datas = dict(imap(lambda i: (i.name, i), datasets))
+ self.descr = description
+
+ def createFromName(name):
+ """Scan the benchmark directory for the benchmark named 'name'
+ and create a benchmark object for it."""
+ bmkpath = path.join(globals.root, 'benchmarks', name)
+ descr = process.read_description_file(bmkpath)
+
+ try:
+ # Scan implementations of the benchmark
+ impls = [BenchImpl.createFromName(name, impl)
+ for impl in process.scan_for_benchmark_versions(bmkpath)]
+
+ # Scan data sets of the benchmark
+ datas = [BenchDataset.createFromName(name, data)
+ for data in process.scan_for_benchmark_datasets(bmkpath)]
+
+ # If no exception occurred, the benchmark is valid
+ return Benchmark(name, bmkpath, impls, datas, descr)
+ except Exception, e:
+ return Benchmark(name, invalid=e)
+
+ createFromName = staticmethod(createFromName)
+
+ def describe(self):
+ """Return a string describing this benchmark."""
+
+ if self.invalid:
+ return "Error in benchmark:\n" + str(self.invalid)
+
+ if self.descr is None:
+ header = "Benchmark '" + self.name + "'"
+ else:
+ header = self.descr
+
+ impls = " ".join([impl.name for impl in self.impls.itervalues()])
+ datas = " ".join([data.name for data in self.datas.itervalues()])
+
+ return header + "\nVersions: " + impls + "\nData sets: " + datas
+
+ def instance_check(x):
+ if not isinstance(x, Benchmark):
+ raise TypeError, "argument must be an instance of Benchmark"
+
+ instance_check = staticmethod(instance_check)
+
+class BenchImpl(object):
+ """An implementation of a benchmark."""
+
+ def __init__(self, name, description=None):
+ if not isinstance(name, str):
+ raise TypeError, "name must be a string"
+
+ self.name = name
+ self.descr = description
+
+ def createFromName(name, impl):
+ """Scan the directory containing a benchmark implementation
+ and create a BenchImpl object from it."""
+
+ # Path to the implementation
+ impl_path = path.join(globals.root, 'benchmarks', name, 'src', impl)
+
+ # Get the description from a file, if provided
+ descr = process.read_description_file(impl_path)
+
+ return BenchImpl(impl, descr)
+
+ createFromName = staticmethod(createFromName)
+
+ def makefile(self, benchmark, target=None, action=None):
+ """Run this implementation's makefile."""
+
+ Benchmark.instance_check(benchmark)
+
+ def perform():
+ srcdir = path.join('src', self.name)
+ builddir = path.join('build', self.name)
+
+ env={'SRCDIR':srcdir,
+ 'BUILDDIR':builddir,
+ 'BIN':path.join(builddir,benchmark.name),
+ 'PARBOIL_ROOT':globals.root}
+
+ # Run the makefile to build the benchmark
+ return process.makefile(target=target,
+ action=action,
+ filepath=path.join(srcdir, "Makefile"),
+ env=env)
+
+ # Go to the benchmark directory before building
+ return process.with_path(benchmark.path, perform)
+
+ def build(self, benchmark):
+ """Build an executable of this benchmark implementation."""
+ return self.makefile(benchmark)
+
+ def isBuilt(self, benchmark):
+ """Determine whether the executable is up to date."""
+ return self.makefile(benchmark, action='q')
+
+ def clean(self, benchmark):
+ """Remove build files for this benchmark implementation."""
+ return self.makefile(benchmark, 'clean')
+
+ def run(self, benchmark, dataset, do_output=True, extra_opts=[]):
+ """Run this benchmark implementation.
+
+ Return True if the benchmark terminated normally or False
+ if there was an error."""
+
+ # Ensure that the benchmark has been built
+ if not self.isBuilt(benchmark):
+ rc = self.build(benchmark)
+
+ # Stop if 'make' failed
+ if not rc: return False
+
+ def perform():
+ # Run the program
+ exename = path.join('build', self.name, benchmark.name)
+ args = [exename] + extra_opts + dataset.getCommandLineArguments(do_output)
+ rc = process.spawnwaitv(exename, args)
+
+ # Program exited with error?
+ if rc != 0: return False
+ return True
+
+ return process.with_path(benchmark.path, perform)
+
+ def check(self, benchmark, dataset):
+ """Check the output from the last run of this benchmark
+ implementation.
+
+ Return True if the output checks successfully or False
+ otherwise."""
+
+ def perform():
+ output_file = dataset.getTemporaryOutputPath()
+ reference_file = dataset.getReferenceOutputPath()
+
+ compare = os.path.join('tools', 'compare-output')
+ rc = process.spawnwaitl(compare,
+ compare, reference_file, output_file)
+
+ # Program exited with error, or mismatch in output?
+ if rc != 0: return False
+ return True
+
+ return process.with_path(benchmark.path, perform)
+
+ def __str__(self):
+ return "<BenchImpl '" + self.name + "'>"
+
+class BenchDataset(object):
+ """Data sets for running a benchmark."""
+
+ def __init__(self, name, in_files=[], out_files=[], parameters=[],
+ description=None):
+ if not isinstance(name, str):
+ raise TypeError, "name must be a string"
+
+ self.name = name
+ self.inFiles = in_files
+ self.outFiles = out_files
+ self.parameters = parameters
+ self.descr = description
+
+ def createFromName(name, dset):
+ """Scan the directory containing a dataset
+ and create a BenchDataset object from it."""
+
+ # Identify the paths where files may be found
+ benchmark_path = path.join(globals.root, 'benchmarks', name)
+
+ if path.exists(path.join(benchmark_path, 'input')):
+ input_path = path.join(benchmark_path, 'input', dset)
+ else:
+ input_path = None
+
+ output_path = path.join(benchmark_path, 'output', dset)
+
+ # Look for input files
+
+ def check_default_input_files():
+ # This function is called to see if the input file set
+ # guessed by scanning the input directory can be used
+ if invalid_default_input_files:
+ raise ValueError, "Cannot infer command line when there are multiple input files in a data set\n(Fix by adding an input DESCRIPTION file)"
+
+ if input_path:
+ input_descr = process.read_description_file(input_path)
+ input_files = list(process.scan_for_files(input_path,
+ boring=['DESCRIPTION','.svn']))
+
+ # If more than one input file was found, cannot use the default
+ # input file list produced by scanning the directory
+ invalid_default_input_files = len(input_files) > 1
+ else:
+ # If there's no input directory, assume the benchmark
+ # takes no input
+ input_descr = None
+ input_files = []
+ invalid_default_input_files = False
+
+ # Read the text of the input description file
+ if input_descr is not None:
+ (parameters, input_files1, input_descr) = \
+ unpack_dataset_description(input_descr, input_files=None)
+
+ if input_files1 is None:
+ # No override vaule given; use the default
+ check_default_input_files()
+ else:
+ input_files = input_files1
+ else:
+ check_default_input_files()
+ parameters = []
+
+ # Look for output files
+ output_descr = process.read_description_file(output_path)
+ output_files = list(process.scan_for_files(output_path,
+ boring=['DESCRIPTION','.svn']))
+ if len(output_files) > 1:
+ raise ValueError, "Multiple output files not supported"
+
+ # Concatenate input and output descriptions
+ if input_descr and output_descr:
+ descr = input_descr + "\n\n" + output_descr
+ else:
+ descr = input_descr or output_descr
+
+ return BenchDataset(dset, input_files, output_files, parameters, descr)
+
+ createFromName = staticmethod(createFromName)
+
+ def getTemporaryOutputPath(self):
+ """Get the name of a file used to hold the output of a benchmark run.
+ This function should always return the same name if its parameters
+ are the same. The output path is not the path where the reference
+ output is stored."""
+
+ return path.join('run', self.name, self.outFiles[0])
+
+ def getReferenceOutputPath(self):
+ """Get the name of the reference file, to which the output of a
+ benchmark run should be compared."""
+
+ return path.join('output', self.name, self.outFiles[0])
+
+ def getCommandLineArguments(self, do_output=True):
+ """Get the command line arguments that should be passed to the
+ executable to run this data set. If 'output' is True, then
+ the executable will be passed flags to save its output to a file.
+
+ Directories to hold ouptut files are created if they do not exist."""
+ args = []
+
+ # Add arguments to pass input files to the benchmark
+ if self.inFiles:
+ in_files = ",".join([path.join('input', self.name, x)
+ for x in self.inFiles])
+ args.append("-i")
+ args.append(in_files)
+
+ # Add arguments to store the output somewhere, if output is
+ # desired
+ if do_output and self.outFiles:
+ if len(self.outFiles) != 1:
+ raise ValueError, "only one output file is supported"
+
+ out_path = self.getTemporaryOutputPath()
+ args.append("-o")
+ args.append(out_path)
+
+ # Ensure that a directory exists for the output
+ process.touch_directory(path.dirname(out_path))
+
+ args += self.parameters
+ return args
+
+ def __str__(self):
+ return "<BenchData '" + self.name + "'>"
+
+def unpack_dataset_description(descr, parameters=[], input_files=[]):
+ """Read information from the raw contents of a data set description
+ file. Optional 'parameters' and 'input_files' arguments may be
+ given, which will be retained unless overridden by the description
+ file."""
+ leftover = []
+ split_at_colon = re.compile(r"^\s*([a-zA-Z]+)\s*:(.*)$")
+
+ # Initialize these to default empty strings
+ parameter_text = None
+ input_file_text = None
+
+ # Scan the description line by line
+ for line in descr.split('\n'):
+ m = split_at_colon.match(line)
+ if m is None: continue
+
+ # This line appears to declare something that should be
+ # interpreted
+ keyword = m.group(1)
+ if keyword == "Parameters":
+ parameter_text = m.group(2)
+ elif keyword == "Inputs":
+ input_file_text = m.group(2)
+ # else, ignore the line
+
+ # Split the strings into (possibly) multiple arguments, discarding
+ # whitespace
+ if parameter_text is not None: parameters = parameter_text.split()
+ if input_file_text is not None: input_files = input_file_text.split()
+ return (parameters, input_files, descr)
+
+def find_benchmarks():
+ """Find benchmarks in the repository. The benchmarks are
+ identified, but their contents are not scanned immediately. A
+ dictionary is returned mapping benchmark names to futures
+ containing the benchmarks."""
+
+ if not globals.root:
+ raise ValueError, "root directory has not been set"
+
+ # Scan all benchmarks in the 'benchmarks' directory and
+ # lazily create benchmark objects.
+ db = {}
+ try:
+ for bmkname in process.scan_for_benchmarks(globals.root):
+ bmk = Future(lambda bmkname=bmkname: Benchmark.createFromName(bmkname))
+ db[bmkname] = bmk
+ except OSError, e:
+ sys.stdout.write("Benchmark directory not found!\n\n")
+ return {}
+
+ return db
diff --git a/benchmarks/CUDA/CP/driver/futures.py b/benchmarks/CUDA/CP/driver/futures.py
new file mode 100644
index 0000000..2e0b94b
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/futures.py
@@ -0,0 +1,14 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+class Future:
+ def __init__(self, thunk):
+ self.evaluated = 0
+ self.value = thunk
+
+ def get(self):
+ if self.evaluated:
+ return self.value
+ else:
+ self.value = self.value()
+ self.evaluated = 1
+ return self.value
diff --git a/benchmarks/CUDA/CP/driver/globals.py b/benchmarks/CUDA/CP/driver/globals.py
new file mode 100644
index 0000000..9e14c23
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/globals.py
@@ -0,0 +1,16 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+# This file holds global variables used by the driver.
+
+# Root directory of the repository (str)
+root = None
+
+# Benchmarks in the repository ({str:Future(Benchmark)})
+benchmarks = None
+
+# Environment variables to use when spawning subprograms ({str:str})
+program_env = None
+
+# True if verbose output is desired. This may be set during
+# option parsing.
+verbose = False
diff --git a/benchmarks/CUDA/CP/driver/options.py b/benchmarks/CUDA/CP/driver/options.py
new file mode 100644
index 0000000..c044ef8
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/options.py
@@ -0,0 +1,208 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+# This module takes care of parsing options for the Parboil driver.
+#
+# The main option parsing routine is parse_options(). Option parsing
+# may print messages and terminate the program, but should not cause
+# any other action to be taken.
+
+from sys import stdout
+from optparse import OptionParser
+
+import actions
+import globals
+
+def invalid_option_message(progname, cmd, args):
+ print "Unrecognized command '" + cmd + "'"
+ print "'" + progname + " help' for options"
+
+# Parsers for each mode. These take the command line as parameters
+# and return an OptionGetter.
+#
+# The 'help' field prints a help message.
+#
+# The 'run' field does the actual parsing. If there is an error in
+# the command line, it prints an error message and returns None;
+# otherwise, it returns an action which will carry out the commands.
+
+class OptionGetter:
+ def __init__(self, help, run):
+ self.help = help
+ self.run = run
+
+def help_options(progname, cmd, args):
+ help_string = "usage: " + progname + " help [COMMAND]\nWithout parameters: list commands\nWith a parameter: Get help on COMMAND\n"
+ get_help = lambda: stdout.write(help_string)
+
+ def run():
+ if args:
+ try: helpcmd = parse_mode_options[args[0]]
+ except KeyError:
+ print "No help available for unrecognized command '" + args[0] + "'"
+ return None
+
+ helpcmd(progname, cmd, args).help()
+ else:
+ print "Commands: "
+ print " help Display this help message"
+ print " list List benchmarks"
+ print " describe Show details on a benchmark"
+ print " clean Clean up generated files in a benchmark"
+ print " compile Compile a benchmark"
+ print " run Run a benchmark"
+ print ""
+ print "To get help on a command: " + progname + " help COMMAND"
+
+ return None
+
+ return OptionGetter(get_help, run)
+
+def list_options(progname, cmd, args):
+ help_string = "usage: " + progname + " list\nList available benchmarks\n"
+ get_help = lambda: stdout.write(help_string)
+
+ def run():
+ if args:
+ print "Unexpected parameter or option after 'list'"
+ return None
+ else:
+ return actions.list_benchmarks
+
+ return OptionGetter(get_help, run)
+
+def describe_options(progname, cmd, args):
+ usage_string = progname + " describe [BENCHMARK]\nWithout parameters: describe all benchmarks in detail\nWith a parameter: describe BENCHMARK in detail"
+ parser = OptionParser(usage=usage_string)
+
+ def run():
+ (opts, pos) = parser.parse_args(args)
+ if len(pos) > 1:
+ print "Too many parameters after 'describe'"
+ return None
+ elif len(pos) == 0:
+ return actions.describe_benchmarks
+ else:
+ bmkname = pos[0]
+ return lambda: actions.with_benchmark_named(bmkname,
+ actions.describe_benchmark)
+
+ return OptionGetter(parser.print_help, run)
+
+def clean_options(progname, cmd, args):
+ usage_string = progname + " clean BENCHMARK [VERSION]\nDelete the object code and executable of BENCHMARK version VERSION;\nif no version is given, remove the object code and executable of all versions"
+ parser = OptionParser(usage=usage_string)
+ parser.add_option('-v', "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="Produce verbose status messages")
+
+ def run():
+ (opts, pos) = parser.parse_args(args)
+ globals.verbose = opts.verbose
+
+ if len(pos) == 0:
+ print "Expecting one or two parameters after 'clean'"
+ return None
+ elif len(pos) == 1:
+ bmkname = pos[0]
+ return lambda: actions.with_benchmark_named(bmkname, actions.clean_benchmark)
+ elif len(pos) == 2:
+ bmkname = pos[0]
+ ver = pos[1]
+ return lambda: actions.with_benchmark_named(bmkname, lambda b: actions.clean_benchmark(b, ver))
+ else:
+ print "Too many parameters after 'clean'"
+ return None
+
+ return OptionGetter(parser.print_help, run)
+
+def compile_options(progname, cmd, args):
+ help_string = "usage :" + progname + " compile BENCHMARK VERSION\nCompile version VERSION of BENCHMARK"
+ parser = OptionParser(usage = help_string)
+ parser.add_option('-v', "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="Produce verbose status messages")
+
+ def run():
+ (opts, pos) = parser.parse_args(args)
+ globals.verbose = opts.verbose
+
+ if len(pos) != 2:
+ print "Expecting two parameters after 'compile'"
+ return None
+ else:
+ bmkname = pos[0]
+ ver = pos[1]
+ return lambda: actions.with_benchmark_named(bmkname, lambda b: actions.compile_benchmark(b, ver))
+
+ return OptionGetter(parser.print_help, run)
+
+def run_options(progname, cmd, args):
+ usage_string = progname + " run BENCHMARK VERSION INPUT\nRun version VERSION of BENCHMARK with data set INPUT"
+ parser = OptionParser(usage=usage_string)
+ parser.add_option('-C', "--no-check",
+ action="store_false", dest="check", default=True,
+ help="Skip the output check for this benchmark")
+ parser.add_option('-S', "--synchronize",
+ action="store_true", dest="synchronize", default=False,
+ help="Synchronize after GPU calls; necessary for accurate run time accounting on CUDA benchmarks")
+ parser.add_option('-v', "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="Produce verbose status messages")
+
+ def run():
+ (opts, pos) = parser.parse_args(args)
+ globals.verbose = opts.verbose
+ if len(pos) != 3:
+ print "Expecting three parameters after 'run'"
+ return None
+ else:
+ bmkname = pos[0]
+ ver = pos[1]
+ inp = pos[2]
+ ck=opts.check
+ extra_opts = []
+ if opts.synchronize:
+ extra_opts.append('-S')
+ return lambda: actions.with_benchmark_named(bmkname, lambda b: actions.run_benchmark(b, ver, inp, check=ck, extra_opts=extra_opts))
+
+ return OptionGetter(parser.print_help, run)
+
+# Dictionary from option name to function from command-line parameters
+# to pair of help thunk and option processor thunk
+parse_mode_options = {
+ 'help' : help_options,
+ '-h' : help_options,
+ '--help' : help_options,
+ 'list' : list_options,
+ 'describe' : describe_options,
+ 'clean' : clean_options,
+ 'compile' : compile_options,
+ 'run' : run_options
+ }
+
+def parse_options(args):
+ """Parse a list of command-line options. If there is an error in
+ the options, then the function will print a message and either call
+ sys.exit() or return None. If options were parsed successfully
+ then it will return a thunk which represents the action to take,
+ or None if no action need be taken.
+
+ Generally, the caller should call the return value, unless None is
+ returned."""
+ # Parse arguments; skip the program name
+ prog_name = args[0]
+
+ # Get the command name
+ try: cmd = args[1]
+ except IndexError: cmd = 'help'
+
+ # Dispatch
+ try: mode = parse_mode_options[cmd]
+ except KeyError:
+ invalid_option_message(prog_name, cmd, args[2:])
+ return
+
+ # Set up and run the option parser
+ return mode(prog_name, cmd, args[2:]).run()
+
+
diff --git a/benchmarks/CUDA/CP/driver/process.py b/benchmarks/CUDA/CP/driver/process.py
new file mode 100644
index 0000000..56e7e98
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/process.py
@@ -0,0 +1,181 @@
+# (c) 2007 The Board of Trustees of the University of Illinois.
+
+# Process-management and directory management routines are collected here.
+
+import os
+import os.path as path
+import stat
+from itertools import imap, ifilter, chain
+
+import globals
+
+def scan_for_files(topdir, directory=False, boring=[]):
+ """Scan the contents of the directory 'topdir'. If 'directory' is
+ True, return a sequence of all directories found in that directory;
+ otherwise, return a sequence of all files found in that directory.
+ Directories whose names are found in the 'boring' list are excluded."""
+
+ # Look for directories or regular files, depending on the 'directory'
+ # parameter
+ if directory: valid_test = path.isdir
+ else: valid_test = path.isfile
+
+ def interesting(fname):
+ # True if 'dirname' is not a boring name, and it is a directory
+ if fname in boring: return False
+
+ fpath = path.join(topdir, fname)
+ try: return valid_test(fpath)
+ except OSError: return False # Ignore file-not-found errors
+
+ if not path.isdir(topdir):
+ raise OSError, "Cannot access '" + str(topdir) + "' as a directory"
+
+ # Return names of all directories found
+ return ifilter(interesting, os.listdir(topdir))
+
+def scan_for_benchmarks(topdir):
+ """Scan subdirectories of the benchmark repository to find
+ benchmarks. Return a sequence containing all benchmark
+ directory names."""
+
+ return scan_for_files(path.join(topdir, "benchmarks"), True, boring=['_darcs','.svn'])
+
+def scan_for_benchmark_versions(bmkdir):
+ """Scan subdirectories of a benchmark directory 'bmkdir' to find
+ benchmark versions. Return a sequence containing all benchmark
+ version names."""
+
+ return scan_for_files(path.join(bmkdir, "src"), True, boring=['.svn'])
+
+def scan_for_benchmark_datasets(bmkdir):
+ """Scan subdirectories of a benchmark directory 'bmkdir' to find
+ data sets. Return a sequence containing all data set names."""
+
+ # Get input and output subdirectories
+ inp_dir = path.join(bmkdir, "input")
+ if path.exists(inp_dir):
+ inp_dirs = scan_for_files(path.join(bmkdir, "input"), True, boring=['.svn'])
+ else:
+ # Assume no input files are found because the benchmark
+ # doesn't need input
+ inp_dirs = []
+
+ out_dirs = scan_for_files(path.join(bmkdir, "output"), True, boring=['.svn'])
+
+ # Return the union of the dataset directories
+ return dict(imap(lambda x: (x, None), chain(inp_dirs, out_dirs))).keys()
+
+def read_description_file(dirpath):
+ """Read the contents of a file in 'dirpath' called DESCRIPTION,
+ if one exists. This returns the file text as a string, or None
+ if no description was found."""
+
+ descr_path = os.path.join(dirpath, 'DESCRIPTION')
+ if os.access(descr_path, os.R_OK):
+ descr_file = file(descr_path, 'r')
+ descr = descr_file.read()
+ descr_file.close()
+ return descr
+
+ # else, return None
+
+def touch_directory(dirpath):
+ """Ensures that the directory 'dirpath' and its parent directories
+ exist. If they do not exist, they will be created. It is an
+ error if the path exists but is not a directory."""
+ if path.isdir(dirpath):
+ return
+ elif path.exists(dirpath):
+ raise OSError, "Path exists but is not a directory"
+ else:
+ (head, tail) = path.split(dirpath)
+ if head: touch_directory(head)
+ os.mkdir(dirpath)
+
+def with_path(wd, action):
+ """Executes an action in a separate working directory. The action
+ should be a callable object."""
+ cwd = os.getcwd()
+ os.chdir(wd)
+ try: result = action()
+ finally: os.chdir(cwd)
+ return result
+
+def makefile(target=None, action=None, filepath=None, env={}):
+ """Run a makefile. An optional command, makefile path, and dictionary of
+ variables to define on the command line may be defined. The return code
+ value is the return code returned by the makefile.
+
+ If no action is given, 'make' is invoked. Returns True if make was
+ successful and False otherwise.
+
+ A 'q' action queries whether the target needs to be rebuilt. True is
+ returned if the target is up to date."""
+
+ args = ["make"]
+
+ if action is None:
+ def run():
+ rc = os.spawnvp(os.P_WAIT, "make", args)
+ return rc == 0
+ elif action in ['q']:
+ args.append('-q')
+
+ def run():
+ rc = os.spawnvp(os.P_WAIT, "make", args)
+ if rc == 0:
+ # Up-to-date
+ return True
+ elif rc == 1:
+ # Needs remake
+ return False
+ else:
+ # Error
+ return False
+ else:
+ raise ValueError, "invalid action"
+
+ # Pass the target as the second argument
+ if target: args.append(target)
+
+ # Pass the path the the makefile
+ if filepath:
+ args.append('-f')
+ args.append(filepath)
+
+ # Pass variables
+ for (k,v) in env.iteritems():
+ args.append(k + "=" + v)
+
+ # Print a status message, if running in verbose mode
+ if globals.verbose:
+
+ print "Running '" + " ".join(args) + "' in " + os.getcwd()
+
+ # Run the makefile and return result info
+ return run()
+
+def spawnwaitv(prog, args):
+ """Spawn a program and wait for it to complete. The program is
+ spawned in a modified environment."""
+
+ env = dict(os.environ)
+ env.update(globals.program_env)
+
+ # Print a status message if running in verbose mode
+ if globals.verbose:
+ print "Running '" + " ".join(args) + "' in " + os.getcwd()
+
+ # Check that the program is runnable
+ if not os.access(prog, os.X_OK):
+ raise OSError, "Cannot execute '" + prog + "'"
+
+ # Run the program
+ return os.spawnve(os.P_WAIT, prog, args, env)
+
+def spawnwaitl(prog, *argl):
+ """Spawn a program and wait for it to complete. The program is
+ spawned in a modified environment."""
+
+ return spawnwaitv(prog, argl)
diff --git a/benchmarks/CUDA/CP/driver/text.py b/benchmarks/CUDA/CP/driver/text.py
new file mode 100644
index 0000000..b8e1097
--- /dev/null
+++ b/benchmarks/CUDA/CP/driver/text.py
@@ -0,0 +1,75 @@
+#! /usr/bin/env python
+
+from itertools import imap
+import re
+
+TOKEN = re.compile(r"(?:^|(?<=\s))[^\s]+|(?:^|(?<!\s))[\s]+")
+
+COLUMNS=80
+
+class iscan:
+ """A scan iterator."""
+ def __init__(self, f, init, s):
+ self.f = f
+ self.s = s.__iter__()
+ self.current = init
+ self.begin = True
+
+ def next(self):
+ if self.begin:
+ self.begin = False
+ return self.current
+ else:
+ cur = self.f(self.current, self.s.next()) # raises StopIteration
+ self.current = cur
+ return cur
+
+ def __iter__(self): return self
+
+def format_columns(text, indent=0):
+ """Format the text to fit in 80 columns by inserting newlines. Spaces
+ are inserted at the beginning of each line to indent by 'indent'
+ columns."""
+
+ outls = []
+ for inl in text.split('\n'):
+ # Split the line into alternating space and non-space tokens
+ tokens = TOKEN.findall(inl)
+
+ # Empty line?
+ if not tokens:
+ outls.append("")
+ continue
+
+ # Use the spaces at the beginning of the line to determine
+ # the line's indentation
+ if tokens[0].isspace():
+ inl_indent = indent + len(tokens[0])
+ del tokens[0]
+ else:
+ inl_indent = indent
+
+ # Write tokens into the output
+ while tokens:
+ # Ignore whitespace at the beginning of the line
+ if tokens[0].isspace(): del tokens[0]
+
+ # Take as many tokens as possible without exceeding the line
+ # length; however, must take at least one token
+ n = 0
+ lengths = iscan(lambda n, t: n + len(t), inl_indent, tokens)
+ lengths.next()
+ for c in lengths:
+ if c > COLUMNS: break
+ n += 1
+ n = max(n, 1)
+
+ # Concatenate the tokens and prepend spaces for indentation
+ outls.append(' ' * inl_indent + "".join(tokens[:n]))
+
+ # Continue with tokens
+ tokens = tokens[n:]
+
+ return "\n".join(outls)
+
+