csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Copyright 2016 Google Inc. |
| 4 | # |
| 5 | # Use of this source code is governed by a BSD-style license that can be |
| 6 | # found in the LICENSE file. |
| 7 | |
| 8 | from __future__ import print_function |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 9 | from _adb import Adb |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 10 | from _benchresult import BenchResult |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 11 | from _hardware import HardwareException, Hardware |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 12 | from argparse import ArgumentParser |
csmartdalton | 5745d79 | 2016-09-22 12:37:21 -0700 | [diff] [blame] | 13 | from multiprocessing import Queue |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 14 | from threading import Thread, Timer |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 15 | import collections |
| 16 | import glob |
| 17 | import math |
| 18 | import re |
| 19 | import subprocess |
| 20 | import sys |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 21 | import time |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 22 | |
csmartdalton | bf41fa8 | 2016-09-23 11:36:11 -0700 | [diff] [blame] | 23 | __argparse = ArgumentParser(description=""" |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 24 | |
| 25 | Executes the skpbench binary with various configs and skps. |
| 26 | |
| 27 | Also monitors the output in order to filter out and re-run results that have an |
| 28 | unacceptable stddev. |
| 29 | |
csmartdalton | bf41fa8 | 2016-09-23 11:36:11 -0700 | [diff] [blame] | 30 | """) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 31 | |
csmartdalton | 2087dda | 2016-11-09 16:34:53 -0500 | [diff] [blame] | 32 | __argparse.add_argument('skpbench', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 33 | help="path to the skpbench binary") |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 34 | __argparse.add_argument('--adb', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 35 | action='store_true', help="execute skpbench over adb") |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 36 | __argparse.add_argument('--adb_binary', default='adb', |
| 37 | help="The name of the adb binary to use.") |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 38 | __argparse.add_argument('-s', '--device-serial', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 39 | help="if using adb, ID of the specific device to target " |
| 40 | "(only required if more than 1 device is attached)") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 41 | __argparse.add_argument('-m', '--max-stddev', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 42 | type=float, default=4, |
| 43 | help="initial max allowable relative standard deviation") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 44 | __argparse.add_argument('-x', '--suffix', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 45 | help="suffix to append on config (e.g. '_before', '_after')") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 46 | __argparse.add_argument('-w','--write-path', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 47 | help="directory to save .png proofs to disk.") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 48 | __argparse.add_argument('-v','--verbosity', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 49 | type=int, default=1, help="level of verbosity (0=none to 5=debug)") |
csmartdalton | 037adf3 | 2016-09-28 13:56:01 -0700 | [diff] [blame] | 50 | __argparse.add_argument('-d', '--duration', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 51 | type=int, help="number of milliseconds to run each benchmark") |
csmartdalton | 037adf3 | 2016-09-28 13:56:01 -0700 | [diff] [blame] | 52 | __argparse.add_argument('-l', '--sample-ms', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 53 | type=int, help="duration of a sample (minimum)") |
csmartdalton | c6618dd | 2016-10-05 08:42:03 -0700 | [diff] [blame] | 54 | __argparse.add_argument('--gpu', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 55 | action='store_true', |
| 56 | help="perform timing on the gpu clock instead of cpu (gpu work only)") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 57 | __argparse.add_argument('--fps', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 58 | action='store_true', help="use fps instead of ms") |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 59 | __argparse.add_argument('--pr', |
| 60 | help="comma- or space-separated list of GPU path renderers, including: " |
Robert Phillips | 84fd1c2 | 2021-03-23 13:18:36 -0400 | [diff] [blame] | 61 | "[[~]all [~]default [~]dashline [~]msaa [~]aaconvex " |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 62 | "[~]aalinearizing [~]small [~]tess]") |
Chris Dalton | a8fbeba | 2019-03-30 00:31:23 -0600 | [diff] [blame] | 63 | __argparse.add_argument('--cc', |
| 64 | action='store_true', help="allow coverage counting shortcuts to render paths") |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 65 | __argparse.add_argument('--nocache', |
| 66 | action='store_true', help="disable caching of path mask textures") |
Chris Dalton | 9278f10 | 2020-09-24 11:42:47 -0600 | [diff] [blame] | 67 | __argparse.add_argument('--allPathsVolatile', |
| 68 | action='store_true', |
| 69 | help="Causes all GPU paths to be processed as if 'setIsVolatile' had been called.") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 70 | __argparse.add_argument('-c', '--config', |
Brian Salomon | 50f66d8 | 2017-03-17 14:32:05 -0400 | [diff] [blame] | 71 | default='gl', help="comma- or space-separated list of GPU configs") |
csmartdalton | 49df770 | 2016-11-10 10:36:28 -0500 | [diff] [blame] | 72 | __argparse.add_argument('-a', '--resultsfile', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 73 | help="optional file to append results into") |
Robert Phillips | 9619c49 | 2018-05-31 08:12:33 -0400 | [diff] [blame] | 74 | __argparse.add_argument('--ddl', |
| 75 | action='store_true', help="record the skp into DDLs before rendering") |
Nathaniel Nifong | ba4c308 | 2021-02-09 08:58:00 -0500 | [diff] [blame] | 76 | __argparse.add_argument('--lock-clocks', |
| 77 | action='store_true', help="Put device in benchmarking mode (locked clocks, no other processes)") |
| 78 | __argparse.add_argument('--clock-speed', |
| 79 | type=float, default=66.0, help="A number between 0 and 100 indicating how fast to lock the CPU and GPU clock." |
| 80 | "Valid speeds are chosen from their respective available frequencies list.") |
Adlai Holler | e5c379d | 2020-05-18 10:21:53 -0400 | [diff] [blame] | 81 | __argparse.add_argument('--ddlNumRecordingThreads', |
Robert Phillips | 9619c49 | 2018-05-31 08:12:33 -0400 | [diff] [blame] | 82 | type=int, default=0, |
Adlai Holler | e5c379d | 2020-05-18 10:21:53 -0400 | [diff] [blame] | 83 | help="number of DDL recording threads (0=num_cores)") |
Robert Phillips | 9619c49 | 2018-05-31 08:12:33 -0400 | [diff] [blame] | 84 | __argparse.add_argument('--ddlTilingWidthHeight', |
| 85 | type=int, default=0, help="number of tiles along one edge when in DDL mode") |
Adlai Holler | d37a085 | 2021-04-22 11:08:12 -0400 | [diff] [blame] | 86 | __argparse.add_argument('--dontReduceOpsTaskSplitting', |
| 87 | action='store_true', help="don't reorder GPU tasks to reduce render target swaps") |
Robert Phillips | d5506cb | 2018-06-26 08:49:38 -0400 | [diff] [blame] | 88 | __argparse.add_argument('--gpuThreads', |
| 89 | type=int, default=-1, |
| 90 | help="Create this many extra threads to assist with GPU work, including" |
| 91 | " software path rendering. Defaults to two.") |
Chris Dalton | 9278f10 | 2020-09-24 11:42:47 -0600 | [diff] [blame] | 92 | __argparse.add_argument('--internalSamples', |
| 93 | type=int, default=-1, |
Chris Dalton | 57ab06c | 2021-04-22 12:57:28 -0600 | [diff] [blame] | 94 | help="Number of samples for internal draws that use MSAA.") |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 95 | __argparse.add_argument('srcs', |
Kevin Lubick | 9c2249f | 2016-11-10 14:19:00 -0500 | [diff] [blame] | 96 | nargs='+', |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 97 | help=".skp files or directories to expand for .skp files, and/or .svg files") |
Adlai Holler | 53a65b2 | 2021-04-19 11:04:21 -0400 | [diff] [blame] | 98 | __argparse.add_argument('--gpuResourceCacheLimit', |
| 99 | type=int, default=-1, |
| 100 | help="Maximum number of bytes to use for budgeted GPU resources.") |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 101 | |
| 102 | FLAGS = __argparse.parse_args() |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 103 | if FLAGS.adb: |
| 104 | import _adb_path as _path |
Kevin Lubick | cccaef1 | 2017-10-13 08:15:09 -0400 | [diff] [blame] | 105 | _path.init(FLAGS.device_serial, FLAGS.adb_binary) |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 106 | else: |
| 107 | import _os_path as _path |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 108 | |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 109 | def dump_commandline_if_verbose(commandline): |
csmartdalton | e4fd078 | 2016-11-09 08:41:23 -0800 | [diff] [blame] | 110 | if FLAGS.verbosity >= 5: |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 111 | quoted = ['\'%s\'' % re.sub(r'([\\\'])', r'\\\1', x) for x in commandline] |
| 112 | print(' '.join(quoted), file=sys.stderr) |
| 113 | |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 114 | |
| 115 | class StddevException(Exception): |
| 116 | pass |
| 117 | |
| 118 | class Message: |
| 119 | READLINE = 0, |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 120 | POLL_HARDWARE = 1, |
| 121 | EXIT = 2 |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 122 | def __init__(self, message, value=None): |
| 123 | self.message = message |
| 124 | self.value = value |
| 125 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 126 | class SubprocessMonitor(Thread): |
| 127 | def __init__(self, queue, proc): |
| 128 | self._queue = queue |
| 129 | self._proc = proc |
| 130 | Thread.__init__(self) |
| 131 | |
| 132 | def run(self): |
csmartdalton | bf41fa8 | 2016-09-23 11:36:11 -0700 | [diff] [blame] | 133 | """Runs on the background thread.""" |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 134 | for line in iter(self._proc.stdout.readline, b''): |
| 135 | self._queue.put(Message(Message.READLINE, line.decode('utf-8').rstrip())) |
| 136 | self._queue.put(Message(Message.EXIT)) |
| 137 | |
| 138 | class SKPBench: |
csmartdalton | 2087dda | 2016-11-09 16:34:53 -0500 | [diff] [blame] | 139 | ARGV = [FLAGS.skpbench, '--verbosity', str(FLAGS.verbosity)] |
csmartdalton | 037adf3 | 2016-09-28 13:56:01 -0700 | [diff] [blame] | 140 | if FLAGS.duration: |
| 141 | ARGV.extend(['--duration', str(FLAGS.duration)]) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 142 | if FLAGS.sample_ms: |
| 143 | ARGV.extend(['--sampleMs', str(FLAGS.sample_ms)]) |
csmartdalton | c6618dd | 2016-10-05 08:42:03 -0700 | [diff] [blame] | 144 | if FLAGS.gpu: |
| 145 | ARGV.extend(['--gpuClock', 'true']) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 146 | if FLAGS.fps: |
| 147 | ARGV.extend(['--fps', 'true']) |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 148 | if FLAGS.pr: |
| 149 | ARGV.extend(['--pr'] + re.split(r'[ ,]', FLAGS.pr)) |
Chris Dalton | a8fbeba | 2019-03-30 00:31:23 -0600 | [diff] [blame] | 150 | if FLAGS.cc: |
| 151 | ARGV.extend(['--cc', 'true']) |
Chris Dalton | acb549f | 2017-10-19 14:11:58 -0600 | [diff] [blame] | 152 | if FLAGS.nocache: |
| 153 | ARGV.extend(['--cachePathMasks', 'false']) |
Chris Dalton | 9278f10 | 2020-09-24 11:42:47 -0600 | [diff] [blame] | 154 | if FLAGS.allPathsVolatile: |
| 155 | ARGV.extend(['--allPathsVolatile', 'true']) |
Robert Phillips | d5506cb | 2018-06-26 08:49:38 -0400 | [diff] [blame] | 156 | if FLAGS.gpuThreads != -1: |
| 157 | ARGV.extend(['--gpuThreads', str(FLAGS.gpuThreads)]) |
Chris Dalton | 9278f10 | 2020-09-24 11:42:47 -0600 | [diff] [blame] | 158 | if FLAGS.internalSamples != -1: |
| 159 | ARGV.extend(['--internalSamples', str(FLAGS.internalSamples)]) |
Robert Phillips | 9619c49 | 2018-05-31 08:12:33 -0400 | [diff] [blame] | 160 | |
| 161 | # DDL parameters |
| 162 | if FLAGS.ddl: |
| 163 | ARGV.extend(['--ddl', 'true']) |
Adlai Holler | e5c379d | 2020-05-18 10:21:53 -0400 | [diff] [blame] | 164 | if FLAGS.ddlNumRecordingThreads: |
| 165 | ARGV.extend(['--ddlNumRecordingThreads', |
| 166 | str(FLAGS.ddlNumRecordingThreads)]) |
Robert Phillips | 9619c49 | 2018-05-31 08:12:33 -0400 | [diff] [blame] | 167 | if FLAGS.ddlTilingWidthHeight: |
| 168 | ARGV.extend(['--ddlTilingWidthHeight', str(FLAGS.ddlTilingWidthHeight)]) |
| 169 | |
Adlai Holler | d37a085 | 2021-04-22 11:08:12 -0400 | [diff] [blame] | 170 | if FLAGS.dontReduceOpsTaskSplitting: |
| 171 | ARGV.extend(['--dontReduceOpsTaskSplitting']) |
Adlai Holler | 7942619 | 2021-02-12 12:17:20 -0500 | [diff] [blame] | 172 | |
Adlai Holler | 53a65b2 | 2021-04-19 11:04:21 -0400 | [diff] [blame] | 173 | if FLAGS.gpuResourceCacheLimit: |
| 174 | ARGV.extend(['--gpuResourceCacheLimit', str(FLAGS.gpuResourceCacheLimit)]) |
| 175 | |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 176 | if FLAGS.adb: |
| 177 | if FLAGS.device_serial is None: |
Kevin Lubick | cccaef1 | 2017-10-13 08:15:09 -0400 | [diff] [blame] | 178 | ARGV[:0] = [FLAGS.adb_binary, 'shell'] |
csmartdalton | 0262b5c | 2016-09-19 12:04:56 -0700 | [diff] [blame] | 179 | else: |
Kevin Lubick | cccaef1 | 2017-10-13 08:15:09 -0400 | [diff] [blame] | 180 | ARGV[:0] = [FLAGS.adb_binary, '-s', FLAGS.device_serial, 'shell'] |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 181 | |
| 182 | @classmethod |
csmartdalton | 49df770 | 2016-11-10 10:36:28 -0500 | [diff] [blame] | 183 | def get_header(cls, outfile=sys.stdout): |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 184 | commandline = cls.ARGV + ['--duration', '0'] |
| 185 | dump_commandline_if_verbose(commandline) |
Kevin Lubick | 6068769 | 2022-05-18 09:49:35 -0400 | [diff] [blame] | 186 | out = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8') |
csmartdalton | 49df770 | 2016-11-10 10:36:28 -0500 | [diff] [blame] | 187 | return out.rstrip() |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 188 | |
| 189 | @classmethod |
Brian Salomon | 50f66d8 | 2017-03-17 14:32:05 -0400 | [diff] [blame] | 190 | def run_warmup(cls, warmup_time, config): |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 191 | if not warmup_time: |
| 192 | return |
csmartdalton | 310d72c | 2016-10-18 09:19:50 -0700 | [diff] [blame] | 193 | print('running %i second warmup...' % warmup_time, file=sys.stderr) |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 194 | commandline = cls.ARGV + ['--duration', str(warmup_time * 1000), |
Brian Salomon | 50f66d8 | 2017-03-17 14:32:05 -0400 | [diff] [blame] | 195 | '--config', config, |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 196 | '--src', 'warmup'] |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 197 | dump_commandline_if_verbose(commandline) |
Kevin Lubick | 6068769 | 2022-05-18 09:49:35 -0400 | [diff] [blame] | 198 | output = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8') |
csmartdalton | f2b024d | 2016-11-09 13:25:23 -0800 | [diff] [blame] | 199 | |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 200 | # validate the warmup run output. |
Kevin Lubick | 6068769 | 2022-05-18 09:49:35 -0400 | [diff] [blame] | 201 | for line in output.split('\n'): |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 202 | match = BenchResult.match(line.rstrip()) |
| 203 | if match and match.bench == 'warmup': |
| 204 | return |
| 205 | raise Exception('Invalid warmup output:\n%s' % output) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 206 | |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 207 | def __init__(self, src, config, max_stddev, best_result=None): |
| 208 | self.src = src |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 209 | self.config = config |
| 210 | self.max_stddev = max_stddev |
| 211 | self.best_result = best_result |
| 212 | self._queue = Queue() |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 213 | self._proc = None |
| 214 | self._monitor = None |
| 215 | self._hw_poll_timer = None |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 216 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 217 | def __enter__(self): |
| 218 | return self |
| 219 | |
| 220 | def __exit__(self, exception_type, exception_value, traceback): |
| 221 | if self._proc: |
| 222 | self.terminate() |
| 223 | if self._hw_poll_timer: |
| 224 | self._hw_poll_timer.cancel() |
| 225 | |
| 226 | def execute(self, hardware): |
| 227 | hardware.sanity_check() |
| 228 | self._schedule_hardware_poll() |
| 229 | |
| 230 | commandline = self.ARGV + ['--config', self.config, |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 231 | '--src', self.src, |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 232 | '--suppressHeader', 'true'] |
| 233 | if FLAGS.write_path: |
| 234 | pngfile = _path.join(FLAGS.write_path, self.config, |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 235 | _path.basename(self.src) + '.png') |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 236 | commandline.extend(['--png', pngfile]) |
csmartdalton | 5772eaa | 2016-10-11 18:28:54 -0700 | [diff] [blame] | 237 | dump_commandline_if_verbose(commandline) |
csmartdalton | f2b024d | 2016-11-09 13:25:23 -0800 | [diff] [blame] | 238 | self._proc = subprocess.Popen(commandline, stdout=subprocess.PIPE, |
| 239 | stderr=subprocess.STDOUT) |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 240 | self._monitor = SubprocessMonitor(self._queue, self._proc) |
| 241 | self._monitor.start() |
| 242 | |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 243 | while True: |
| 244 | message = self._queue.get() |
| 245 | if message.message == Message.READLINE: |
| 246 | result = BenchResult.match(message.value) |
| 247 | if result: |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 248 | hardware.sanity_check() |
| 249 | self._process_result(result) |
csmartdalton | f2b024d | 2016-11-09 13:25:23 -0800 | [diff] [blame] | 250 | elif hardware.filter_line(message.value): |
csmartdalton | 310d72c | 2016-10-18 09:19:50 -0700 | [diff] [blame] | 251 | print(message.value, file=sys.stderr) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 252 | continue |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 253 | if message.message == Message.POLL_HARDWARE: |
| 254 | hardware.sanity_check() |
| 255 | self._schedule_hardware_poll() |
| 256 | continue |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 257 | if message.message == Message.EXIT: |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 258 | self._monitor.join() |
| 259 | self._proc.wait() |
| 260 | if self._proc.returncode != 0: |
| 261 | raise Exception("skpbench exited with nonzero exit code %i" % |
| 262 | self._proc.returncode) |
| 263 | self._proc = None |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 264 | break |
| 265 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 266 | def _schedule_hardware_poll(self): |
| 267 | if self._hw_poll_timer: |
| 268 | self._hw_poll_timer.cancel() |
| 269 | self._hw_poll_timer = \ |
| 270 | Timer(1, lambda: self._queue.put(Message(Message.POLL_HARDWARE))) |
| 271 | self._hw_poll_timer.start() |
| 272 | |
| 273 | def _process_result(self, result): |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 274 | if not self.best_result or result.stddev <= self.best_result.stddev: |
| 275 | self.best_result = result |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 276 | elif FLAGS.verbosity >= 2: |
| 277 | print("reusing previous result for %s/%s with lower stddev " |
| 278 | "(%s%% instead of %s%%)." % |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 279 | (result.config, result.bench, self.best_result.stddev, |
| 280 | result.stddev), file=sys.stderr) |
| 281 | if self.max_stddev and self.best_result.stddev > self.max_stddev: |
| 282 | raise StddevException() |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 283 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 284 | def terminate(self): |
| 285 | if self._proc: |
csmartdalton | c6618dd | 2016-10-05 08:42:03 -0700 | [diff] [blame] | 286 | self._proc.terminate() |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 287 | self._monitor.join() |
| 288 | self._proc.wait() |
| 289 | self._proc = None |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 290 | |
csmartdalton | 49df770 | 2016-11-10 10:36:28 -0500 | [diff] [blame] | 291 | def emit_result(line, resultsfile=None): |
| 292 | print(line) |
| 293 | sys.stdout.flush() |
| 294 | if resultsfile: |
| 295 | print(line, file=resultsfile) |
| 296 | resultsfile.flush() |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 297 | |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 298 | def run_benchmarks(configs, srcs, hardware, resultsfile=None): |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 299 | hasheader = False |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 300 | benches = collections.deque([(src, config, FLAGS.max_stddev) |
| 301 | for src in srcs |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 302 | for config in configs]) |
| 303 | while benches: |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 304 | try: |
| 305 | with hardware: |
Brian Salomon | 50f66d8 | 2017-03-17 14:32:05 -0400 | [diff] [blame] | 306 | SKPBench.run_warmup(hardware.warmup_time, configs[0]) |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 307 | if not hasheader: |
| 308 | emit_result(SKPBench.get_header(), resultsfile) |
| 309 | hasheader = True |
| 310 | while benches: |
| 311 | benchargs = benches.popleft() |
| 312 | with SKPBench(*benchargs) as skpbench: |
| 313 | try: |
| 314 | skpbench.execute(hardware) |
| 315 | if skpbench.best_result: |
| 316 | emit_result(skpbench.best_result.format(FLAGS.suffix), |
| 317 | resultsfile) |
| 318 | else: |
| 319 | print("WARNING: no result for %s with config %s" % |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 320 | (skpbench.src, skpbench.config), file=sys.stderr) |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 321 | |
| 322 | except StddevException: |
| 323 | retry_max_stddev = skpbench.max_stddev * math.sqrt(2) |
| 324 | if FLAGS.verbosity >= 1: |
| 325 | print("stddev is too high for %s/%s (%s%%, max=%.2f%%), " |
| 326 | "re-queuing with max=%.2f%%." % |
| 327 | (skpbench.best_result.config, skpbench.best_result.bench, |
| 328 | skpbench.best_result.stddev, skpbench.max_stddev, |
| 329 | retry_max_stddev), |
| 330 | file=sys.stderr) |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 331 | benches.append((skpbench.src, skpbench.config, retry_max_stddev, |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 332 | skpbench.best_result)) |
| 333 | |
| 334 | except HardwareException as exception: |
| 335 | skpbench.terminate() |
| 336 | if FLAGS.verbosity >= 4: |
| 337 | hardware.print_debug_diagnostics() |
| 338 | if FLAGS.verbosity >= 1: |
Chris Dalton | 49b7ed3 | 2017-10-23 17:19:37 -0600 | [diff] [blame] | 339 | print("%s; rebooting and taking a %i second nap..." % |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 340 | (exception.message, exception.sleeptime), file=sys.stderr) |
| 341 | benches.appendleft(benchargs) # retry the same bench next time. |
| 342 | raise # wake hw up from benchmarking mode before the nap. |
| 343 | |
| 344 | except HardwareException as exception: |
| 345 | time.sleep(exception.sleeptime) |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 346 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 347 | def main(): |
| 348 | # Delimiter is ',' or ' ', skip if nested inside parens (e.g. gpu(a=b,c=d)). |
| 349 | DELIMITER = r'[, ](?!(?:[^(]*\([^)]*\))*[^()]*\))' |
| 350 | configs = re.split(DELIMITER, FLAGS.config) |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 351 | srcs = _path.find_skps(FLAGS.srcs) |
Nathaniel Nifong | f7cf794 | 2019-09-11 14:00:20 -0400 | [diff] [blame] | 352 | assert srcs |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 353 | |
Nathaniel Nifong | ba4c308 | 2021-02-09 08:58:00 -0500 | [diff] [blame] | 354 | |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 355 | if FLAGS.adb: |
Kevin Lubick | cccaef1 | 2017-10-13 08:15:09 -0400 | [diff] [blame] | 356 | adb = Adb(FLAGS.device_serial, FLAGS.adb_binary, |
| 357 | echo=(FLAGS.verbosity >= 5)) |
Nathaniel Nifong | ba4c308 | 2021-02-09 08:58:00 -0500 | [diff] [blame] | 358 | from _hardware_android import HardwareAndroid |
| 359 | |
csmartdalton | e4fd078 | 2016-11-09 08:41:23 -0800 | [diff] [blame] | 360 | model = adb.check('getprop ro.product.model').strip() |
csmartdalton | bf41fa8 | 2016-09-23 11:36:11 -0700 | [diff] [blame] | 361 | if model == 'Pixel C': |
| 362 | from _hardware_pixel_c import HardwarePixelC |
| 363 | hardware = HardwarePixelC(adb) |
Herb Derby | 4c3486e | 2020-10-05 11:20:43 -0400 | [diff] [blame] | 364 | elif model == 'Pixel' or model == "Pixel XL": |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 365 | from _hardware_pixel import HardwarePixel |
| 366 | hardware = HardwarePixel(adb) |
Chris Dalton | 117d972 | 2018-04-27 17:10:39 -0600 | [diff] [blame] | 367 | elif model == 'Pixel 2': |
| 368 | from _hardware_pixel2 import HardwarePixel2 |
| 369 | hardware = HardwarePixel2(adb) |
csmartdalton | 310d72c | 2016-10-18 09:19:50 -0700 | [diff] [blame] | 370 | elif model == 'Nexus 6P': |
| 371 | from _hardware_nexus_6p import HardwareNexus6P |
| 372 | hardware = HardwareNexus6P(adb) |
Chris Dalton | 9278f10 | 2020-09-24 11:42:47 -0600 | [diff] [blame] | 373 | else: |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 374 | print("WARNING: %s: don't know how to monitor this hardware; results " |
| 375 | "may be unreliable." % model, file=sys.stderr) |
| 376 | hardware = HardwareAndroid(adb) |
Nathaniel Nifong | ba4c308 | 2021-02-09 08:58:00 -0500 | [diff] [blame] | 377 | |
| 378 | if FLAGS.lock_clocks: |
| 379 | hardware.__enter__() |
| 380 | print("Entered benchmarking mode, not running benchmarks. Reboot to restore."); |
| 381 | return; |
| 382 | |
| 383 | if FLAGS.clock_speed: |
| 384 | hardware.setDesiredClock(FLAGS.clock_speed) |
csmartdalton | d7a9db6 | 2016-09-22 05:10:02 -0700 | [diff] [blame] | 385 | else: |
| 386 | hardware = Hardware() |
| 387 | |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 388 | if FLAGS.resultsfile: |
| 389 | with open(FLAGS.resultsfile, mode='a+') as resultsfile: |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 390 | run_benchmarks(configs, srcs, hardware, resultsfile=resultsfile) |
Chris Dalton | 34d9055 | 2017-10-20 09:58:32 -0600 | [diff] [blame] | 391 | else: |
Chris Dalton | a4f5ce0 | 2018-06-26 10:13:06 -0600 | [diff] [blame] | 392 | run_benchmarks(configs, srcs, hardware) |
csmartdalton | 4b5179b | 2016-09-19 11:03:58 -0700 | [diff] [blame] | 393 | |
| 394 | |
| 395 | if __name__ == '__main__': |
| 396 | main() |