| Index: tools/skpbench/skpbench.py
|
| diff --git a/tools/skpbench/skpbench.py b/tools/skpbench/skpbench.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..f547003573695138d798ebb099caed3cbd105fd8
|
| --- /dev/null
|
| +++ b/tools/skpbench/skpbench.py
|
| @@ -0,0 +1,176 @@
|
| +#!/usr/bin/env python
|
| +
|
| +# Copyright 2016 Google Inc.
|
| +#
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +from __future__ import print_function
|
| +from _benchresult import BenchResult
|
| +from argparse import ArgumentParser
|
| +from os import path
|
| +from queue import Queue
|
| +from threading import Thread
|
| +import collections
|
| +import glob
|
| +import math
|
| +import re
|
| +import subprocess
|
| +import sys
|
| +
|
| +__argparse = ArgumentParser(description="""
|
| +
|
| +Executes the skpbench binary with various configs and skps.
|
| +
|
| +Also monitors the output in order to filter out and re-run results that have an
|
| +unacceptable stddev.
|
| +
|
| +""")
|
| +
|
| +__argparse.add_argument('-p', '--path',
|
| + help='directory to execute ./skpbench from')
|
| +__argparse.add_argument('-m', '--max-stddev',
|
| + type=float, default=4,
|
| + help='initial max allowable relative standard deviation')
|
| +__argparse.add_argument('-x', '--suffix',
|
| + help='suffix to append on config (e.g. "_before", "_after")')
|
| +__argparse.add_argument('-w','--write-path',
|
| + help='directory to save .png proofs to disk.')
|
| +__argparse.add_argument('-v','--verbosity',
|
| + type=int, default=0, help='level of verbosity (0=none to 5=debug)')
|
| +__argparse.add_argument('-n', '--samples',
|
| + type=int, help='number of samples to collect for each bench')
|
| +__argparse.add_argument('-d', '--sample-ms',
|
| + type=int, help='duration of each sample')
|
| +__argparse.add_argument('--fps',
|
| + action='store_true', help='use fps instead of ms')
|
| +__argparse.add_argument('-c', '--config',
|
| + default='gpu', help='comma- or space-separated list of GPU configs')
|
| +__argparse.add_argument('skps',
|
| + nargs='+',
|
| + help='.skp files or directories to expand for .skp files')
|
| +
|
| +FLAGS = __argparse.parse_args()
|
| +
|
| +
|
| +class StddevException(Exception):
|
| + pass
|
| +
|
| +class Message:
|
| + READLINE = 0,
|
| + EXIT = 1
|
| + def __init__(self, message, value=None):
|
| + self.message = message
|
| + self.value = value
|
| +
|
| +class SKPBench(Thread):
|
| + ARGV = ['skpbench', '--verbosity', str(FLAGS.verbosity)]
|
| + if FLAGS.path:
|
| + ARGV[0] = path.join(FLAGS.path, ARGV[0])
|
| + if FLAGS.samples:
|
| + ARGV.extend(['--samples', str(FLAGS.samples)])
|
| + if FLAGS.sample_ms:
|
| + ARGV.extend(['--sampleMs', str(FLAGS.sample_ms)])
|
| + if FLAGS.fps:
|
| + ARGV.extend(['--fps', 'true'])
|
| +
|
| + @classmethod
|
| + def print_header(cls):
|
| + subprocess.call(cls.ARGV + ['--samples', '0'])
|
| +
|
| + def __init__(self, skp, config, max_stddev, best_result=None):
|
| + self.skp = skp
|
| + self.config = config
|
| + self.max_stddev = max_stddev
|
| + self.best_result = best_result
|
| + self._queue = Queue()
|
| + Thread.__init__(self)
|
| +
|
| + def execute(self):
|
| + self.start()
|
| + while True:
|
| + message = self._queue.get()
|
| + if message.message == Message.READLINE:
|
| + result = BenchResult.match(message.value)
|
| + if result:
|
| + self.__process_result(result)
|
| + else:
|
| + print(message.value)
|
| + sys.stdout.flush()
|
| + continue
|
| + if message.message == Message.EXIT:
|
| + self.join()
|
| + break
|
| +
|
| + def __process_result(self, result):
|
| + if not self.best_result or result.stddev <= self.best_result.stddev:
|
| + self.best_result = result
|
| + elif FLAGS.verbosity >= 1:
|
| + print('NOTE: reusing previous result for %s/%s with lower stddev '
|
| + '(%s%% instead of %s%%).' %
|
| + (result.config, result.bench, self.best_result.stddev,
|
| + result.stddev), file=sys.stderr)
|
| + if self.max_stddev and self.best_result.stddev > self.max_stddev:
|
| + raise StddevException()
|
| + self.best_result.print_values(config_suffix=FLAGS.suffix)
|
| +
|
| + def run(self):
|
| + """Called on the background thread.
|
| +
|
| + Launches and reads output from an skpbench process.
|
| +
|
| + """
|
| + commandline = self.ARGV + ['--config', self.config,
|
| + '--skp', self.skp,
|
| + '--suppressHeader', 'true']
|
| + if (FLAGS.write_path):
|
| + pngfile = path.join(FLAGS.write_path, self.config,
|
| + path.basename(self.skp) + '.png')
|
| + commandline.extend(['--png', pngfile])
|
| + if (FLAGS.verbosity >= 3):
|
| + print(' '.join(commandline), file=sys.stderr)
|
| + proc = subprocess.Popen(commandline, stdout=subprocess.PIPE)
|
| + for line in iter(proc.stdout.readline, b''):
|
| + self._queue.put(Message(Message.READLINE, line.decode('utf-8').rstrip()))
|
| + proc.wait()
|
| + self._queue.put(Message(Message.EXIT, proc.returncode))
|
| +
|
| +
|
| +def main():
|
| + SKPBench.print_header()
|
| +
|
| + # Delimiter is "," or " ", skip if nested inside parens (e.g. gpu(a=b,c=d)).
|
| + DELIMITER = r'[, ](?!(?:[^(]*\([^)]*\))*[^()]*\))'
|
| + configs = re.split(DELIMITER, FLAGS.config)
|
| +
|
| + skps = list()
|
| + for skp in FLAGS.skps:
|
| + if (path.isdir(skp)):
|
| + skps.extend(glob.iglob(path.join(skp, '*.skp')))
|
| + else:
|
| + skps.append(skp)
|
| +
|
| + benches = collections.deque([(skp, config, FLAGS.max_stddev)
|
| + for skp in skps
|
| + for config in configs])
|
| + while benches:
|
| + benchargs = benches.popleft()
|
| + skpbench = SKPBench(*benchargs)
|
| + try:
|
| + skpbench.execute()
|
| +
|
| + except StddevException:
|
| + retry_max_stddev = skpbench.max_stddev * math.sqrt(2)
|
| + if FLAGS.verbosity >= 1:
|
| + print('NOTE: stddev too high for %s/%s (%s%%; max=%.2f%%). '
|
| + 'Re-queuing with max=%.2f%%.' %
|
| + (skpbench.best_result.config, skpbench.best_result.bench,
|
| + skpbench.best_result.stddev, skpbench.max_stddev,
|
| + retry_max_stddev),
|
| + file=sys.stderr)
|
| + benches.append((skpbench.skp, skpbench.config, retry_max_stddev,
|
| + skpbench.best_result))
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + main()
|
|
|