#!/usr/bin/env python import os import platform import optparse # TODO argparse from python 2.7 on import subprocess import resource from datetime import datetime SCRIPT_VERSION="0.1" AUTHOR="Andreas Zwinkau " (KERNEL,HOSTNAME,KERNEL_VERSION,VERSION,ARCH,PROCESSOR) = platform.uname() LINUX_NAME, LINUX_VERSION, LINUX_CODENAME = platform.dist() BITSIZE = { "i686": 32, "x86_64": 64, "sparc64": 64, }.get(ARCH, "unspecified for "+ARCH) # assert spec dir for subdir in "benchspec config bin result".split(): assert os.path.isdir(subdir), "subdir missing: "+subdir for filename in "shrc README LICENSE MANIFEST".split(): assert os.path.isfile(filename), "file missing: "+filename def identify_suite(): """Which SPEC suite are we in?""" for line in file("README"): possibilities = ["SPEC CPU2000", "SPEC CPU2006", "SPEC OMP2001"] if line.startswith("---"): break for p in possibilities: if p in line: return p print "Error: Unknown SPEC suite (if at all)" exit(-1) SPEC_SUITE = identify_suite() parser = optparse.OptionParser(version=SCRIPT_VERSION, usage="Usage: %prog [options] [programs]") parser.add_option("--config-only", action="store_true", default=False, help="Just generate config file, but do not build or run") parser.add_option("--build-only", action="store_true", default=False, help="Just generate config file and build benchmark programs, but do not run") parser.add_option("--no-cpp", action="store_true", default=False, help="Exclude benchmark programs using C++") parser.add_option("--no-fortran", action="store_true", default=False, help="Exclude benchmark programs using Fortran") parser.add_option("--no-floating-point", action="store_true", default=False, help="Exclude CFP subset containing floating point-heavy benchmark programs") parser.add_option("--no-integer", action="store_true", default=False, help="Exclude CINT subset containing integer-heavy benchmark programs") parser.add_option("--no-medium", action="store_true", default=False, help="Exclude OMPM programs") parser.add_option("--no-large", action="store_true", default=False, help="Exclude OMPL programs") parser.add_option("-i", "--iterations", metavar="ITR", default=3, help="Evaluate ITR iterations per program, default=3") parser.add_option("--time-limit", metavar="TIMELIMIT", default=0, help="Set cpu time limit for each program run to TIMELIMIT seconds.") parser.add_option("--c-compiler", metavar="CC", default="gcc", help="Use CC to build benchmark programs, default=gcc") parser.add_option("--fortran-compiler", metavar="FC", default="gfortran", help="Use FC to build benchmark programs, default=gfortran") parser.add_option("--cpp-compiler", metavar="CXX", default="g++", help="Use CXX to build benchmark programs, default=g++") parser.add_option("--compiler-args", metavar="FLAGS", default="-O3", help="Append FLAGS to build benchmark programs for all compilers, default=-O3") parser.add_option("--c-compiler-args", metavar="CFLAGS", default="-march=native", help="Append CFLAGS to build benchmark programs for C compiler, default march=native") parser.add_option("--fortran-compiler-args", metavar="FFLAGS", default="", help="Append FFLAGS to build benchmark programs for Fortran compiler, default empty") parser.add_option("--cpp-compiler-args", metavar="CFLAGS", default="-march=native", help="Append CFLAGS to build benchmark programs for C++ compiler, default march=native") # http://www.spec.org/cpu2006/Docs/config.html _CONFIG_HEAD = """\ #### Automatically generated by spec.py script #### output_format = csv,html,raw,screen,config ignore_errors = yes test_sponsor = IPD Snelting tester_name = IPD Snelting company_name = Karlsruhe Institute of Technology KIT prepared_by = spec.py script ## just assuming: hw_fpu = Integrated sw_state = Multi-user """ class SigKill(Exception): def __init__(self, retcode, name): self.retcode = retcode self.name = name _EXIT_CODES = { -2: "keyboard interrupt", -3: "keyboard quit", -4: "illegal instruction", -6: "aborted", -8: "floating point exception", -9: "kill", -11: "segfault", -13: "broken pipe", -14: "timeout", -15: "termination", } def execute(cmd, env=None, timeout=0): """Execute a command and return stderr and/or stdout data""" preexec_fn = None if timeout > 0.0: def set_timeout(): resource.setrlimit(resource.RLIMIT_CPU, (timeout, timeout)) preexec_fn = set_timeout cmd = filter(lambda x: x, cmd.split(' ')) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn = preexec_fn, env=env) out, err = proc.communicate() try: for line in out.splitlines(): yield line except Exception, e: print "'%s' -> %s" % (c, e) if proc.returncode in _EXIT_CODES: raise SigKill(proc.returncode, _EXIT_CODES[proc.returncode]) elif proc.returncode < 0: # program aborted raise Exception(proc.returncode, cmd) def path_to_filesystem(path): for line in execute("stat -f ."): if "Type:" in line: i = line.index("Type:") return line[i+6:].strip() def _get_proc_info(path): """Extract data from proc files""" data = dict() for line in file(path): try: key, value = line.split(":") except ValueError: continue data[key.strip()] = value.strip() return data def get_mem_info(): """Return data about Memory as dict""" return _get_proc_info("/proc/meminfo") def get_cpu_info(): # TODO ignores multiple cpus """Return data about CPU as dict""" return _get_proc_info("/proc/cpuinfo") def get_compiler_version(compiler): """Get the version from a compiler executable""" try: d = execute(compiler+" --version") for line in d: return line except OSError: return "No compiler '%s' found." % compiler PORTABILITY_FLAGS = dict() PORTABILITY_FLAGS[("SPEC CPU2000", "Ubuntu", 32)] = """\ 176.gcc=default=default=default: CPORTABILITY = -std=gnu89 -fno-strict-aliasing notes003 = CPORTABILITY 176.gcc: -std=gnu89 -fno-strict-aliasing 186.crafty=default=default=default: CPORTABILITY = -DLINUX_i386 notes004 = CPORTABILITY 186.crafty: -DLINUX_i386 252.eon=default=default=default: CXXPORTABILITY = -DHAS_ERRLIST notes005 = CXXPORTABILITY 252.eon: -DHAS_ERRLIST 253.perlbmk=default=default=default: CPORTABILITY = -DSPEC_CPU2000_NEED_BOOL -DSPEC_CPU2000_LINUX_I386 notes006 = CPORTABILITY 253.perlbmk: -DSPEC_CPU2000_NEED_BOOL -DSPEC_CPU2000_LINUX_I386 254.gap=default=default=default: CPORTABILITY = -DSYS_HAS_SIGNAL_PROTO -DSYS_HAS_MALLOC_PROTO -DSYS_HAS_CALLOC_PROTO -DSYS_IS_USG -DSYS_HAS_IOCTL_PROTO -DSYS_HAS_TIME_PROTO notes007 = CPORTABILITY 254.gap: -DSYS_HAS_SIGNAL_PROTO -DSYS_HAS_MALLOC_PROTO -DSYS_HAS_CALLOC_PROTO -DSYS_IS_USG -DSYS_HAS_IOCTL_PROTO -DSYS_HAS_TIME_PROTO 255.vortex=default=default=default: CPORTABILITY = -fno-strict-aliasing notes008 = CPORTABILITY 255.vortex: -fno-strict-aliasing 187.facerec=default=default=default: EXTRA_FFLAGS= -I../src """ PORTABILITY_FLAGS[("SPEC CPU2000", "Ubuntu", 64)] = PORTABILITY_FLAGS[("SPEC CPU2000", "Ubuntu", 32)] PORTABILITY_FLAGS[("SPEC CPU2000", "debian", 32)] = PORTABILITY_FLAGS[("SPEC CPU2000", "Ubuntu", 32)] PORTABILITY_FLAGS[("SPEC CPU2000", "debian", 64)] = PORTABILITY_FLAGS[("SPEC CPU2000", "Ubuntu", 32)] PORTABILITY_FLAGS[("SPEC OMP2001", "Ubuntu", 32)] = """\ 310.wupwise_m=default=default=default: FPORTABILITY=-ffixed-form 312.swim_m=default=default=default: FPORTABILITY=-ffixed-form 314.mgrid_m=default=default=default: FPORTABILITY=-ffixed-form # no lastprivate error on i44pc50, needs extra download srcalt = intel 316.applu_m=default=default=default: FPORTABILITY=-ffixed-form 318.galgel_m=default=default=default: # fix infinite loop on i44pc49, needs extra download srcalt = dlamch FPORTABILITY=-ffixed-form -ffixed-line-length-80 324.apsi_m=default=default=default: FPORTABILITY=-ffixed-form 326.gafort_m=default=default=default: FPORTABILITY=-qsuffix=f=f90 328.fma3d_m=default=default=default: FPORTABILITY=-qsuffix=f=f90 """ PORTABILITY_FLAGS[("SPEC OMP2001", "debian", 64)] = """\ 310.wupwise_m=default=default=default: FPORTABILITY=-ffixed-form 312.swim_m=default=default=default: FPORTABILITY=-ffixed-form 314.mgrid_m=default=default=default: FPORTABILITY=-ffixed-form # no lastprivate error on i41s1, needs extra download # http://www.spec.org/omp2001/src.alt.m/ompm2001-mgrid-20071113.tar.gz srcalt = intel 316.applu_m=default=default=default: FPORTABILITY=-ffixed-form 318.galgel_m=default=default=default: FPORTABILITY=-ffixed-form -ffixed-line-length-80 324.apsi_m=default=default=default: FPORTABILITY=-ffixed-form 326.gafort_m=default=default=default: FPORTABILITY=-qsuffix=f=f90 328.fma3d_m=default=default=default: FPORTABILITY=-qsuffix=f=f90 """ PORTABILITY_FLAGS[("SPEC CPU2006", "Ubuntu", 32)] = """\ 400.perlbench=default=default=default: CPORTABILITY= -DSPEC_CPU_LINUX_IA32 403.gcc=default=default=default: CPORTABILITY= -DSPEC_CPU_LINUX_IA32 -fno-if-conversion -std=gnu89 462.libquantum=default=default=default: CPORTABILITY= -DSPEC_CPU_LINUX 483.xalancbmk=default=default=default: CXXPORTABILITY= -DSPEC_CPU_LINUX 481.wrf=default=default=default: CPORTABILITY = -DSPEC_CPU_CASE_FLAG -DSPEC_CPU_LINUX """ PORTABILITY_FLAGS[("SPEC CPU2006", "Ubuntu", 64)] = """\ default=base=default=default: PORTABILITY = -DSPEC_CPU_LP64 400.perlbench=default=default=default: CPORTABILITY = -DSPEC_CPU_LINUX_X64 462.libquantum=default=default=default: CPORTABILITY= -DSPEC_CPU_LINUX 483.xalancbmk=default=default=default: CXXPORTABILITY= -DSPEC_CPU_LINUX 481.wrf=default=default=default: CPORTABILITY = -DSPEC_CPU_CASE_FLAG -DSPEC_CPU_LINUX """ def get_portability(): """Get necessary portability flags""" contents = ["\n\n#### Portability Flags ####"] for (suite,os,bitsize),text in PORTABILITY_FLAGS.items(): if suite != SPEC_SUITE: continue if os != LINUX_NAME: continue if bitsize != BITSIZE: continue contents.append(text) return "\n".join(contents) BENCHMARK_PROPERTIES = [ ("SPEC CPU2000", "CINT", "164.gzip", "c"), ("SPEC CPU2000", "CINT", "175.vpr", "c"), ("SPEC CPU2000", "CINT", "176.gcc", "c"), ("SPEC CPU2000", "CINT", "181.mcf", "c"), ("SPEC CPU2000", "CINT", "186.crafty", "c"), ("SPEC CPU2000", "CINT", "197.parser", "c"), ("SPEC CPU2000", "CINT", "252.eon", "cpp"), ("SPEC CPU2000", "CINT", "253.perlbmk", "c"), ("SPEC CPU2000", "CINT", "254.gap", "c"), ("SPEC CPU2000", "CINT", "255.vortex", "c"), ("SPEC CPU2000", "CINT", "256.bzip2", "c"), ("SPEC CPU2000", "CINT", "300.twolf", "c"), ("SPEC CPU2000", "CFP", "168.wupwise", "fortran77"), ("SPEC CPU2000", "CFP", "171.swim", "fortran77"), ("SPEC CPU2000", "CFP", "172.mgrid", "fortran77"), ("SPEC CPU2000", "CFP", "173.applu", "fortran77"), ("SPEC CPU2000", "CFP", "177.mesa", "c"), ("SPEC CPU2000", "CFP", "178.galgel", "fortran90"), ("SPEC CPU2000", "CFP", "179.art", "c"), ("SPEC CPU2000", "CFP", "183.equake", "c"), ("SPEC CPU2000", "CFP", "187.facerec", "fortran90"), ("SPEC CPU2000", "CFP", "188.ammp", "c"), ("SPEC CPU2000", "CFP", "189.lucas", "fortran90"), ("SPEC CPU2000", "CFP", "191.fma3d", "fortran90"), ("SPEC CPU2000", "CFP", "200.sixtrack", "fortran77"), ("SPEC CPU2000", "CFP", "301.apsi", "fortran77"), ("SPEC OMP2001", "?", "310.wupwise_m", "?"), ("SPEC OMP2001", "?", "311.wupwise_l", "?"), ("SPEC OMP2001", "?", "312.swim_m", "?"), ("SPEC OMP2001", "?", "313.swim_l", "?"), ("SPEC OMP2001", "?", "314.mgrid_m", "?"), ("SPEC OMP2001", "?", "315.mgrid_l", "?"), ("SPEC OMP2001", "?", "316.applu_m", "?"), ("SPEC OMP2001", "?", "317.applu_l", "?"), ("SPEC OMP2001", "?", "318.galgel_m", "?"), ("SPEC OMP2001", "?", "330.art_m", "?"), ("SPEC OMP2001", "?", "331.art_l", "?"), ("SPEC OMP2001", "?", "320.equake_m", "?"), ("SPEC OMP2001", "?", "321.equake_l", "?"), ("SPEC OMP2001", "?", "332.ammp_m", "?"), ("SPEC OMP2001", "?", "328.fma3d_m", "?"), ("SPEC OMP2001", "?", "329.fma3d_l", "?"), ("SPEC OMP2001", "?", "324.apsi_m", "?"), ("SPEC OMP2001", "?", "325.apsi_l", "?"), ("SPEC OMP2001", "?", "326.gafort_m", "?"), ("SPEC OMP2001", "?", "327.gafort_l", "?"), ("SPEC CPU2006", "CINT", "400.perlbench", "c"), ("SPEC CPU2006", "CINT", "401.bzip2", "c"), ("SPEC CPU2006", "CINT", "403.gcc", "c"), ("SPEC CPU2006", "CINT", "429.mcf", "c"), ("SPEC CPU2006", "CINT", "445.gobmk", "c"), ("SPEC CPU2006", "CINT", "456.hmmer", "c"), ("SPEC CPU2006", "CINT", "458.sjeng", "c"), ("SPEC CPU2006", "CINT", "462.libquantum", "c"), ("SPEC CPU2006", "CINT", "464.h264ref", "c"), ("SPEC CPU2006", "CINT", "471.omnetpp", "cpp"), ("SPEC CPU2006", "CINT", "473.astar", "cpp"), ("SPEC CPU2006", "CINT", "483.xalancbmk", "cpp"), ("SPEC CPU2006", "CFP", "410.bwaves", "fortran"), ("SPEC CPU2006", "CFP", "416.gamess", "fortran"), ("SPEC CPU2006", "CFP", "433.milc", "c"), ("SPEC CPU2006", "CFP", "434.zeusmp", "fortran"), ("SPEC CPU2006", "CFP", "435.gromacs", "c,fortran"), ("SPEC CPU2006", "CFP", "436.cactusADM", "c,fortran"), ("SPEC CPU2006", "CFP", "437.leslie3d", "fortran"), ("SPEC CPU2006", "CFP", "444.namd", "cpp"), ("SPEC CPU2006", "CFP", "447.dealII", "cpp"), ("SPEC CPU2006", "CFP", "450.soplex", "cpp"), ("SPEC CPU2006", "CFP", "453.povray", "cpp"), ("SPEC CPU2006", "CFP", "454.calculix", "c,fortran"), ("SPEC CPU2006", "CFP", "459.GemsFDTD", "fortran"), ("SPEC CPU2006", "CFP", "465.tonto", "fortran"), ("SPEC CPU2006", "CFP", "470.lbm", "c"), ("SPEC CPU2006", "CFP", "481.wrf", "c,fortran"), ("SPEC CPU2006", "CFP", "482.sphinx3", "c"), ] def filter_progs(options,args): if args: programs = list() for progt in BENCHMARK_PROPERTIES: suite, subset, prog, langs = progt if prog in args: programs.append(progt) else: programs = BENCHMARK_PROPERTIES for suite, subset, prog, langs in programs: if suite != SPEC_SUITE: continue if options.no_cpp and "cpp" in langs: continue if options.no_fortran and "fortran" in langs: continue if options.no_floating_point and subset == "CFP": continue if options.no_integer and subset == "CINT": continue if options.no_medium and prog.endswith("_m"): continue if options.no_large and prog.endswith("_l"): continue yield prog def generate_spec_config(options): """Generate a config file for SPEC""" contents = [_CONFIG_HEAD] cpuinfo = get_cpu_info() meminfo = get_mem_info() if options.build_only: contents.append("action = build") else: contents.append("action = validate") # includes run contents.append("iterations = %d" % int(options.iterations)) if SPEC_SUITE != "SPEC CPU2006": contents.append("test_date = %s" % datetime.now()) contents.append("") contents.append("sw_os = %s %s %s" % (LINUX_NAME, LINUX_VERSION, LINUX_CODENAME)) contents.append("sw_compiler1 = %s" % get_compiler_version(options.c_compiler)) contents.append("sw_compiler2 = %s" % get_compiler_version(options.cpp_compiler)) contents.append("sw_compiler3 = %s" % get_compiler_version(options.fortran_compiler)) contents.append("sw_file = %s" % path_to_filesystem(".")) assert int(BITSIZE), "bitsize is "+BITSIZE contents.append("sw_base_ptrsize = %d-bit" % BITSIZE) contents.append("sw_peak_ptrsize = %d-bit" % BITSIZE) contents.append("") chips = (1+int(cpuinfo.get("processor", 0))) cores_per_chip = int(cpuinfo.get("cpu cores", cpuinfo.get("cpu cores", 1))) cores = cores_per_chip * chips if SPEC_SUITE == "SPEC CPU2006": contents.append("hw_cpu_name = %s" % cpuinfo["model name"]) contents.append("hw_ncores = %d" % cores) elif SPEC_SUITE == "SPEC CPU2000": contents.append("hw_model = %s" % cpuinfo["model name"]) contents.append("hw_ncpu = %d" % cores) contents.append("hw_cpu_mhz = %s" % cpuinfo.get("cpu MHz", "?")) contents.append("hw_nchips = %d" % chips) contents.append("hw_ncoresperchip = %d" % cores_per_chip) contents.append("hw_vendor = %s" % cpuinfo.get("vendor_id", "?")) contents.append("hw_memory = %s" % meminfo["MemTotal"]) contents.append("hw_pcache = %s" % cpuinfo.get("cache size", "?")) contents.append("") time_limit = int(options.time_limit) if time_limit != 0: contents.append("use_submit_for_speed = 1") contents.append("submit =ulimit -t %d ; $command" % time_limit) contents.append("") contents.append("CC = %s" % options.c_compiler) contents.append("CXX = %s" % options.cpp_compiler) contents.append("FC = %s" % options.fortran_compiler) contents.append("") contents.append("OPTIMIZE = %s" % options.compiler_args) contents.append("notes_comp_001 OPTIMIZE = %s" % options.compiler_args) contents.append("COPTIMIZE = %s" % options.c_compiler_args) contents.append("notes_comp_002 COPTIMIZE = %s" % options.c_compiler_args) contents.append("CXXOPTIMIZE = %s" % options.cpp_compiler_args) contents.append("notes_comp_003 CXXOPTIMIZE = %s" % options.cpp_compiler_args) contents.append("FOPTIMIZE = %s" % options.fortran_compiler_args) contents.append("notes_comp_004 FOPTIMIZE = %s" % options.fortran_compiler_args) contents.append(get_portability()) return "\n".join(contents) if __name__ == "__main__": (options, args) = parser.parse_args() conf = generate_spec_config(options) fh = open("config/generated.cfg", 'w') fh.write(conf) fh.close() if options.config_only: exit(0) progs = " ".join(filter_progs(options,args)) cmd = "env bash -l -c 'source shrc && runspec %s -c generated'" % progs exit(os.system(cmd))