xref: /aosp_15_r20/external/igt-gpu-tools/scripts/media-bench.pl (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker#! /usr/bin/perl
2*d83cc019SAndroid Build Coastguard Worker#
3*d83cc019SAndroid Build Coastguard Worker# Copyright © 2017 Intel Corporation
4*d83cc019SAndroid Build Coastguard Worker#
5*d83cc019SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
6*d83cc019SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"),
7*d83cc019SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation
8*d83cc019SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*d83cc019SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the
10*d83cc019SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions:
11*d83cc019SAndroid Build Coastguard Worker#
12*d83cc019SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next
13*d83cc019SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the
14*d83cc019SAndroid Build Coastguard Worker# Software.
15*d83cc019SAndroid Build Coastguard Worker#
16*d83cc019SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*d83cc019SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*d83cc019SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*d83cc019SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*d83cc019SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*d83cc019SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*d83cc019SAndroid Build Coastguard Worker# IN THE SOFTWARE.
23*d83cc019SAndroid Build Coastguard Worker#
24*d83cc019SAndroid Build Coastguard Worker
25*d83cc019SAndroid Build Coastguard Workeruse strict;
26*d83cc019SAndroid Build Coastguard Workeruse warnings;
27*d83cc019SAndroid Build Coastguard Workeruse 5.010;
28*d83cc019SAndroid Build Coastguard Worker
29*d83cc019SAndroid Build Coastguard Workeruse Getopt::Std;
30*d83cc019SAndroid Build Coastguard Worker
31*d83cc019SAndroid Build Coastguard Workerchomp(my $igt_root = `pwd -P`);
32*d83cc019SAndroid Build Coastguard Workermy $wsim = "$igt_root/benchmarks/gem_wsim";
33*d83cc019SAndroid Build Coastguard Workermy $wrk_root = "$igt_root/benchmarks/wsim";
34*d83cc019SAndroid Build Coastguard Workermy $tracepl = "$igt_root/scripts/trace.pl";
35*d83cc019SAndroid Build Coastguard Workermy $tolerance = 0.01;
36*d83cc019SAndroid Build Coastguard Workermy $client_target_s = 10;
37*d83cc019SAndroid Build Coastguard Workermy $idle_tolerance_pct = 2.0;
38*d83cc019SAndroid Build Coastguard Workermy $verbose = 0;
39*d83cc019SAndroid Build Coastguard Workermy $gt2 = 0;
40*d83cc019SAndroid Build Coastguard Workermy $show_cmds = 0;
41*d83cc019SAndroid Build Coastguard Workermy $realtime_target = 0;
42*d83cc019SAndroid Build Coastguard Workermy $wps_target = 0;
43*d83cc019SAndroid Build Coastguard Workermy $wps_target_param = 0;
44*d83cc019SAndroid Build Coastguard Workermy $multi_mode = 0;
45*d83cc019SAndroid Build Coastguard Workermy @multi_workloads;
46*d83cc019SAndroid Build Coastguard Workermy $w_direct;
47*d83cc019SAndroid Build Coastguard Workermy $balancer;
48*d83cc019SAndroid Build Coastguard Workermy $nop;
49*d83cc019SAndroid Build Coastguard Workermy %opts;
50*d83cc019SAndroid Build Coastguard Worker
51*d83cc019SAndroid Build Coastguard Workermy @balancers = ( 'rr', 'rand', 'qd', 'qdr', 'qdavg', 'rt', 'rtr', 'rtavg',
52*d83cc019SAndroid Build Coastguard Worker		  'context', 'busy', 'busy-avg', 'i915' );
53*d83cc019SAndroid Build Coastguard Workermy %bal_skip_H = ( 'rr' => 1, 'rand' => 1, 'context' => 1, , 'busy' => 1,
54*d83cc019SAndroid Build Coastguard Worker		   'busy-avg' => 1, 'i915' => 1 );
55*d83cc019SAndroid Build Coastguard Workermy %bal_skip_R = ( 'i915' => 1 );
56*d83cc019SAndroid Build Coastguard Workermy %bal_skip_G = ( 'i915' => 1 );
57*d83cc019SAndroid Build Coastguard Worker
58*d83cc019SAndroid Build Coastguard Workermy @workloads = (
59*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_17i7.wsim',
60*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_19.wsim',
61*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_4k12u7.wsim',
62*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_fhd26u7.wsim',
63*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_hd01.wsim',
64*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_hd06mp2.wsim',
65*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_hd12.wsim',
66*d83cc019SAndroid Build Coastguard Worker	'media_load_balance_hd17i4.wsim',
67*d83cc019SAndroid Build Coastguard Worker	'media_1n2_480p.wsim',
68*d83cc019SAndroid Build Coastguard Worker	'media_1n3_480p.wsim',
69*d83cc019SAndroid Build Coastguard Worker	'media_1n4_480p.wsim',
70*d83cc019SAndroid Build Coastguard Worker	'media_1n5_480p.wsim',
71*d83cc019SAndroid Build Coastguard Worker	'media_1n2_asy.wsim',
72*d83cc019SAndroid Build Coastguard Worker	'media_1n3_asy.wsim',
73*d83cc019SAndroid Build Coastguard Worker	'media_1n4_asy.wsim',
74*d83cc019SAndroid Build Coastguard Worker	'media_1n5_asy.wsim',
75*d83cc019SAndroid Build Coastguard Worker	'media_mfe2_480p.wsim',
76*d83cc019SAndroid Build Coastguard Worker	'media_mfe3_480p.wsim',
77*d83cc019SAndroid Build Coastguard Worker	'media_mfe4_480p.wsim',
78*d83cc019SAndroid Build Coastguard Worker	'media_nn_1080p.wsim',
79*d83cc019SAndroid Build Coastguard Worker	'media_nn_480p.wsim',
80*d83cc019SAndroid Build Coastguard Worker    );
81*d83cc019SAndroid Build Coastguard Worker
82*d83cc019SAndroid Build Coastguard Workersub show_cmd
83*d83cc019SAndroid Build Coastguard Worker{
84*d83cc019SAndroid Build Coastguard Worker	my ($cmd) = @_;
85*d83cc019SAndroid Build Coastguard Worker
86*d83cc019SAndroid Build Coastguard Worker	say "\n+++ $cmd" if $show_cmds;
87*d83cc019SAndroid Build Coastguard Worker}
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Workersub calibrate_nop
90*d83cc019SAndroid Build Coastguard Worker{
91*d83cc019SAndroid Build Coastguard Worker	my ($delay, $nop);
92*d83cc019SAndroid Build Coastguard Worker	my $cmd = "$wsim";
93*d83cc019SAndroid Build Coastguard Worker
94*d83cc019SAndroid Build Coastguard Worker	show_cmd($cmd);
95*d83cc019SAndroid Build Coastguard Worker	open WSIM, "$cmd |" or die;
96*d83cc019SAndroid Build Coastguard Worker	while (<WSIM>) {
97*d83cc019SAndroid Build Coastguard Worker		chomp;
98*d83cc019SAndroid Build Coastguard Worker		if (/Nop calibration for (\d+)us delay is (\d+)./) {
99*d83cc019SAndroid Build Coastguard Worker			$delay = $1;
100*d83cc019SAndroid Build Coastguard Worker			$nop = $2;
101*d83cc019SAndroid Build Coastguard Worker		}
102*d83cc019SAndroid Build Coastguard Worker
103*d83cc019SAndroid Build Coastguard Worker	}
104*d83cc019SAndroid Build Coastguard Worker	close WSIM;
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker	die unless $nop;
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker	return $nop
109*d83cc019SAndroid Build Coastguard Worker}
110*d83cc019SAndroid Build Coastguard Worker
111*d83cc019SAndroid Build Coastguard Workersub can_balance_workload
112*d83cc019SAndroid Build Coastguard Worker{
113*d83cc019SAndroid Build Coastguard Worker	my ($wrk) = @_;
114*d83cc019SAndroid Build Coastguard Worker	my $res = 0;
115*d83cc019SAndroid Build Coastguard Worker
116*d83cc019SAndroid Build Coastguard Worker	open WRK, "$wrk_root/$wrk" or die;
117*d83cc019SAndroid Build Coastguard Worker	while (<WRK>) {
118*d83cc019SAndroid Build Coastguard Worker		chomp;
119*d83cc019SAndroid Build Coastguard Worker		if (/\.VCS\./) {
120*d83cc019SAndroid Build Coastguard Worker			$res = 1;
121*d83cc019SAndroid Build Coastguard Worker			last;
122*d83cc019SAndroid Build Coastguard Worker		}
123*d83cc019SAndroid Build Coastguard Worker	}
124*d83cc019SAndroid Build Coastguard Worker	close WRK;
125*d83cc019SAndroid Build Coastguard Worker
126*d83cc019SAndroid Build Coastguard Worker	return $res;
127*d83cc019SAndroid Build Coastguard Worker}
128*d83cc019SAndroid Build Coastguard Worker
129*d83cc019SAndroid Build Coastguard Workersub add_wps_arg
130*d83cc019SAndroid Build Coastguard Worker{
131*d83cc019SAndroid Build Coastguard Worker	my (@args) = @_;
132*d83cc019SAndroid Build Coastguard Worker	my $period;
133*d83cc019SAndroid Build Coastguard Worker
134*d83cc019SAndroid Build Coastguard Worker	return @args if $realtime_target <= 0;
135*d83cc019SAndroid Build Coastguard Worker
136*d83cc019SAndroid Build Coastguard Worker	$period = int(1000000 / $realtime_target);
137*d83cc019SAndroid Build Coastguard Worker	push @args, '-a';
138*d83cc019SAndroid Build Coastguard Worker	push @args, 'p.$period';
139*d83cc019SAndroid Build Coastguard Worker
140*d83cc019SAndroid Build Coastguard Worker	return @args;
141*d83cc019SAndroid Build Coastguard Worker}
142*d83cc019SAndroid Build Coastguard Worker
143*d83cc019SAndroid Build Coastguard Workersub run_workload
144*d83cc019SAndroid Build Coastguard Worker{
145*d83cc019SAndroid Build Coastguard Worker	my (@args) = @_;
146*d83cc019SAndroid Build Coastguard Worker	my ($time, $wps, $cmd);
147*d83cc019SAndroid Build Coastguard Worker	my @ret;
148*d83cc019SAndroid Build Coastguard Worker
149*d83cc019SAndroid Build Coastguard Worker	@args = add_wps_arg(@args);
150*d83cc019SAndroid Build Coastguard Worker	push @args, '-2' if $gt2;
151*d83cc019SAndroid Build Coastguard Worker
152*d83cc019SAndroid Build Coastguard Worker	unshift @args, $wsim;
153*d83cc019SAndroid Build Coastguard Worker	$cmd = join ' ', @args;
154*d83cc019SAndroid Build Coastguard Worker	show_cmd($cmd);
155*d83cc019SAndroid Build Coastguard Worker
156*d83cc019SAndroid Build Coastguard Worker	open WSIM, "$cmd |" or die;
157*d83cc019SAndroid Build Coastguard Worker	while (<WSIM>) {
158*d83cc019SAndroid Build Coastguard Worker		chomp;
159*d83cc019SAndroid Build Coastguard Worker		if (/^(\d+\.\d+)s elapsed \((\d+\.?\d+) workloads\/s\)$/) {
160*d83cc019SAndroid Build Coastguard Worker			$time = $1;
161*d83cc019SAndroid Build Coastguard Worker			$wps = $2;
162*d83cc019SAndroid Build Coastguard Worker		} elsif (/(\d+)\: \d+\.\d+s elapsed \(\d+ cycles, (\d+\.?\d+) workloads\/s\)/) {
163*d83cc019SAndroid Build Coastguard Worker			$ret[$1] = $2;
164*d83cc019SAndroid Build Coastguard Worker		}
165*d83cc019SAndroid Build Coastguard Worker	}
166*d83cc019SAndroid Build Coastguard Worker	close WSIM;
167*d83cc019SAndroid Build Coastguard Worker
168*d83cc019SAndroid Build Coastguard Worker	return ($time, $wps, \@ret);
169*d83cc019SAndroid Build Coastguard Worker}
170*d83cc019SAndroid Build Coastguard Worker
171*d83cc019SAndroid Build Coastguard Workersub dump_cmd
172*d83cc019SAndroid Build Coastguard Worker{
173*d83cc019SAndroid Build Coastguard Worker	my ($cmd, $file) = @_;
174*d83cc019SAndroid Build Coastguard Worker
175*d83cc019SAndroid Build Coastguard Worker	show_cmd("$cmd > $file");
176*d83cc019SAndroid Build Coastguard Worker
177*d83cc019SAndroid Build Coastguard Worker	open FOUT, '>', $file or die;
178*d83cc019SAndroid Build Coastguard Worker	open TIN, "$cmd |" or die;
179*d83cc019SAndroid Build Coastguard Worker	while (<TIN>) {
180*d83cc019SAndroid Build Coastguard Worker		print FOUT $_;
181*d83cc019SAndroid Build Coastguard Worker	}
182*d83cc019SAndroid Build Coastguard Worker	close TIN;
183*d83cc019SAndroid Build Coastguard Worker	close FOUT;
184*d83cc019SAndroid Build Coastguard Worker}
185*d83cc019SAndroid Build Coastguard Worker
186*d83cc019SAndroid Build Coastguard Workersub trace_workload
187*d83cc019SAndroid Build Coastguard Worker{
188*d83cc019SAndroid Build Coastguard Worker	my ($wrk, $b, $r, $c) = @_;
189*d83cc019SAndroid Build Coastguard Worker	my @args = ($tracepl, '--trace', $wsim, '-q', '-n', $nop, '-r', $r, '-c', $c);
190*d83cc019SAndroid Build Coastguard Worker	my $min_batches = 16 + $r * $c / 2;
191*d83cc019SAndroid Build Coastguard Worker	my @skip_engine;
192*d83cc019SAndroid Build Coastguard Worker	my %engines;
193*d83cc019SAndroid Build Coastguard Worker	my ($cmd, $file);
194*d83cc019SAndroid Build Coastguard Worker
195*d83cc019SAndroid Build Coastguard Worker	push @args, '-2' if $gt2;
196*d83cc019SAndroid Build Coastguard Worker
197*d83cc019SAndroid Build Coastguard Worker	unless ($b eq '<none>') {
198*d83cc019SAndroid Build Coastguard Worker		push @args, '-R';
199*d83cc019SAndroid Build Coastguard Worker		push @args, split /\s+/, $b;
200*d83cc019SAndroid Build Coastguard Worker	}
201*d83cc019SAndroid Build Coastguard Worker
202*d83cc019SAndroid Build Coastguard Worker	if (defined $w_direct) {
203*d83cc019SAndroid Build Coastguard Worker		push @args, split /\s+/, $wrk;
204*d83cc019SAndroid Build Coastguard Worker	} else {
205*d83cc019SAndroid Build Coastguard Worker		push @args, '-w';
206*d83cc019SAndroid Build Coastguard Worker		push @args, $wrk_root . '/' . $wrk;
207*d83cc019SAndroid Build Coastguard Worker	}
208*d83cc019SAndroid Build Coastguard Worker
209*d83cc019SAndroid Build Coastguard Worker	show_cmd(join ' ', @args);
210*d83cc019SAndroid Build Coastguard Worker	if (-e 'perf.data') {
211*d83cc019SAndroid Build Coastguard Worker		unlink 'perf.data' or die;
212*d83cc019SAndroid Build Coastguard Worker	}
213*d83cc019SAndroid Build Coastguard Worker	system(@args) == 0 or die;
214*d83cc019SAndroid Build Coastguard Worker
215*d83cc019SAndroid Build Coastguard Worker	$cmd = "perf script | $tracepl";
216*d83cc019SAndroid Build Coastguard Worker	show_cmd($cmd);
217*d83cc019SAndroid Build Coastguard Worker	open CMD, "$cmd |" or die;
218*d83cc019SAndroid Build Coastguard Worker	while (<CMD>) {
219*d83cc019SAndroid Build Coastguard Worker		chomp;
220*d83cc019SAndroid Build Coastguard Worker		if (/Ring(\S+): (\d+) batches.*?(\d+\.?\d+)% idle,/) {
221*d83cc019SAndroid Build Coastguard Worker			if ($2 >= $min_batches) {
222*d83cc019SAndroid Build Coastguard Worker				$engines{$1} = $3;
223*d83cc019SAndroid Build Coastguard Worker			} else {
224*d83cc019SAndroid Build Coastguard Worker				push @skip_engine, $1;
225*d83cc019SAndroid Build Coastguard Worker			}
226*d83cc019SAndroid Build Coastguard Worker		} elsif (/GPU: (\d+\.?\d+)% idle/) {
227*d83cc019SAndroid Build Coastguard Worker			$engines{'gpu'} = $1;
228*d83cc019SAndroid Build Coastguard Worker		}
229*d83cc019SAndroid Build Coastguard Worker	}
230*d83cc019SAndroid Build Coastguard Worker	close CMD;
231*d83cc019SAndroid Build Coastguard Worker
232*d83cc019SAndroid Build Coastguard Worker	$wrk =~ s/$wrk_root//g;
233*d83cc019SAndroid Build Coastguard Worker	$wrk =~ s/\.wsim//g;
234*d83cc019SAndroid Build Coastguard Worker	$wrk =~ s/-w/W/g;
235*d83cc019SAndroid Build Coastguard Worker	$wrk =~ s/[ -]/_/g;
236*d83cc019SAndroid Build Coastguard Worker	$wrk =~ s/\//-/g;
237*d83cc019SAndroid Build Coastguard Worker	$b =~ s/[ <>]/_/g;
238*d83cc019SAndroid Build Coastguard Worker	$file = "${wrk}_${b}_-r${r}_-c${c}";
239*d83cc019SAndroid Build Coastguard Worker
240*d83cc019SAndroid Build Coastguard Worker	dump_cmd('perf script', "${file}.trace");
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker	$cmd = "perf script | $tracepl --html -x ctxsave -s -c ";
243*d83cc019SAndroid Build Coastguard Worker	$cmd .= join ' ', map("-i $_", @skip_engine);
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker	dump_cmd($cmd, "${file}.html");
246*d83cc019SAndroid Build Coastguard Worker
247*d83cc019SAndroid Build Coastguard Worker	return \%engines;
248*d83cc019SAndroid Build Coastguard Worker}
249*d83cc019SAndroid Build Coastguard Worker
250*d83cc019SAndroid Build Coastguard Workersub calibrate_workload
251*d83cc019SAndroid Build Coastguard Worker{
252*d83cc019SAndroid Build Coastguard Worker	my ($wrk) = @_;
253*d83cc019SAndroid Build Coastguard Worker	my $tol = $tolerance;
254*d83cc019SAndroid Build Coastguard Worker	my $loops = 0;
255*d83cc019SAndroid Build Coastguard Worker	my $error;
256*d83cc019SAndroid Build Coastguard Worker	my $r;
257*d83cc019SAndroid Build Coastguard Worker
258*d83cc019SAndroid Build Coastguard Worker	$r = $realtime_target > 0 ? $realtime_target * $client_target_s : 23;
259*d83cc019SAndroid Build Coastguard Worker	for (;;) {
260*d83cc019SAndroid Build Coastguard Worker		my @args = ('-n', $nop, '-r', $r);
261*d83cc019SAndroid Build Coastguard Worker		my ($time, $wps);
262*d83cc019SAndroid Build Coastguard Worker
263*d83cc019SAndroid Build Coastguard Worker		if (defined $w_direct) {
264*d83cc019SAndroid Build Coastguard Worker			push @args, split /\s+/, $wrk;
265*d83cc019SAndroid Build Coastguard Worker		} else {
266*d83cc019SAndroid Build Coastguard Worker			push @args, '-w';
267*d83cc019SAndroid Build Coastguard Worker			push @args, $wrk_root . '/' . $wrk;
268*d83cc019SAndroid Build Coastguard Worker		}
269*d83cc019SAndroid Build Coastguard Worker
270*d83cc019SAndroid Build Coastguard Worker		($time, $wps) = run_workload(@args);
271*d83cc019SAndroid Build Coastguard Worker
272*d83cc019SAndroid Build Coastguard Worker		$wps = $r / $time if $w_direct;
273*d83cc019SAndroid Build Coastguard Worker		$error = abs($time - $client_target_s) / $client_target_s;
274*d83cc019SAndroid Build Coastguard Worker
275*d83cc019SAndroid Build Coastguard Worker		last if $error <= $tol;
276*d83cc019SAndroid Build Coastguard Worker
277*d83cc019SAndroid Build Coastguard Worker		$r = int($wps * $client_target_s);
278*d83cc019SAndroid Build Coastguard Worker		$loops = $loops + 1;
279*d83cc019SAndroid Build Coastguard Worker		if ($loops >= 3) {
280*d83cc019SAndroid Build Coastguard Worker			$tol = $tol * (1.2 + ($tol));
281*d83cc019SAndroid Build Coastguard Worker			$loops = 0;
282*d83cc019SAndroid Build Coastguard Worker		}
283*d83cc019SAndroid Build Coastguard Worker		last if $tol > 0.2;
284*d83cc019SAndroid Build Coastguard Worker	}
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker	return ($r, $error);
287*d83cc019SAndroid Build Coastguard Worker}
288*d83cc019SAndroid Build Coastguard Worker
289*d83cc019SAndroid Build Coastguard Workersub find_saturation_point
290*d83cc019SAndroid Build Coastguard Worker{
291*d83cc019SAndroid Build Coastguard Worker	my ($wrk, $rr, $verbose, @args) = @_;
292*d83cc019SAndroid Build Coastguard Worker	my ($last_wps, $c, $swps, $wwps);
293*d83cc019SAndroid Build Coastguard Worker	my $target = $realtime_target > 0 ? $realtime_target : $wps_target;
294*d83cc019SAndroid Build Coastguard Worker	my $r = $rr;
295*d83cc019SAndroid Build Coastguard Worker	my $wcnt;
296*d83cc019SAndroid Build Coastguard Worker	my $maxc;
297*d83cc019SAndroid Build Coastguard Worker	my $max = 0;
298*d83cc019SAndroid Build Coastguard Worker
299*d83cc019SAndroid Build Coastguard Worker	push @args, '-v' if $multi_mode and $w_direct;
300*d83cc019SAndroid Build Coastguard Worker
301*d83cc019SAndroid Build Coastguard Worker	if (defined $w_direct) {
302*d83cc019SAndroid Build Coastguard Worker		push @args, split /\s+/, $wrk;
303*d83cc019SAndroid Build Coastguard Worker		$wcnt = () = $wrk =~ /-[wW]/gi;
304*d83cc019SAndroid Build Coastguard Worker
305*d83cc019SAndroid Build Coastguard Worker	} else {
306*d83cc019SAndroid Build Coastguard Worker		push @args, '-w';
307*d83cc019SAndroid Build Coastguard Worker		push @args, $wrk_root . '/' . $wrk;
308*d83cc019SAndroid Build Coastguard Worker		$wcnt = 1;
309*d83cc019SAndroid Build Coastguard Worker	}
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker	for ($c = 1; ; $c = $c + 1) {
312*d83cc019SAndroid Build Coastguard Worker		my ($time, $wps);
313*d83cc019SAndroid Build Coastguard Worker		my @args_ = (@args, ('-r', $r, '-c', $c));
314*d83cc019SAndroid Build Coastguard Worker
315*d83cc019SAndroid Build Coastguard Worker		($time, $wps, $wwps) = run_workload(@args_);
316*d83cc019SAndroid Build Coastguard Worker
317*d83cc019SAndroid Build Coastguard Worker		say "        $c clients is $wps wps." if $verbose;
318*d83cc019SAndroid Build Coastguard Worker
319*d83cc019SAndroid Build Coastguard Worker		if ($c > 1) {
320*d83cc019SAndroid Build Coastguard Worker			my $delta;
321*d83cc019SAndroid Build Coastguard Worker
322*d83cc019SAndroid Build Coastguard Worker			if ($target <= 0) {
323*d83cc019SAndroid Build Coastguard Worker				if ($wps > $max) {
324*d83cc019SAndroid Build Coastguard Worker					$max = $wps;
325*d83cc019SAndroid Build Coastguard Worker					$maxc = $c;
326*d83cc019SAndroid Build Coastguard Worker				}
327*d83cc019SAndroid Build Coastguard Worker				$delta = ($wps - $last_wps) / $last_wps;
328*d83cc019SAndroid Build Coastguard Worker				if ($delta > 0) {
329*d83cc019SAndroid Build Coastguard Worker					last if $delta < $tolerance;
330*d83cc019SAndroid Build Coastguard Worker				} else {
331*d83cc019SAndroid Build Coastguard Worker					$delta = ($wps - $max) / $max;
332*d83cc019SAndroid Build Coastguard Worker					last if abs($delta) >= $tolerance;
333*d83cc019SAndroid Build Coastguard Worker				}
334*d83cc019SAndroid Build Coastguard Worker			} else {
335*d83cc019SAndroid Build Coastguard Worker				$delta = ($wps / $c - $target) / $target;
336*d83cc019SAndroid Build Coastguard Worker				last if $delta < 0 and abs($delta) >= $tolerance;
337*d83cc019SAndroid Build Coastguard Worker			}
338*d83cc019SAndroid Build Coastguard Worker			$r = int($rr * ($client_target_s / $time));
339*d83cc019SAndroid Build Coastguard Worker		} elsif ($c == 1) {
340*d83cc019SAndroid Build Coastguard Worker			$swps = $wps;
341*d83cc019SAndroid Build Coastguard Worker			return ($c, $wps, $swps, $wwps) if $wcnt > 1 or
342*d83cc019SAndroid Build Coastguard Worker							   $multi_mode or
343*d83cc019SAndroid Build Coastguard Worker							   ($wps_target_param < 0 and
344*d83cc019SAndroid Build Coastguard Worker							    $wps_target == 0);
345*d83cc019SAndroid Build Coastguard Worker		}
346*d83cc019SAndroid Build Coastguard Worker
347*d83cc019SAndroid Build Coastguard Worker		$last_wps = $wps;
348*d83cc019SAndroid Build Coastguard Worker	}
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker	if ($target <= 0) {
351*d83cc019SAndroid Build Coastguard Worker		return ($maxc, $max, $swps, $wwps);
352*d83cc019SAndroid Build Coastguard Worker	} else {
353*d83cc019SAndroid Build Coastguard Worker		return ($c - 1, $last_wps, $swps, $wwps);
354*d83cc019SAndroid Build Coastguard Worker	}
355*d83cc019SAndroid Build Coastguard Worker}
356*d83cc019SAndroid Build Coastguard Worker
357*d83cc019SAndroid Build Coastguard Workergetopts('hv2xmn:b:W:B:r:t:i:R:T:w:', \%opts);
358*d83cc019SAndroid Build Coastguard Worker
359*d83cc019SAndroid Build Coastguard Workerif (defined $opts{'h'}) {
360*d83cc019SAndroid Build Coastguard Worker	print <<ENDHELP;
361*d83cc019SAndroid Build Coastguard WorkerSupported options:
362*d83cc019SAndroid Build Coastguard Worker
363*d83cc019SAndroid Build Coastguard Worker  -h          Help text.
364*d83cc019SAndroid Build Coastguard Worker  -v          Be verbose.
365*d83cc019SAndroid Build Coastguard Worker  -x          Show external commands.
366*d83cc019SAndroid Build Coastguard Worker  -2          Run gem_wsim in GT2 mode.
367*d83cc019SAndroid Build Coastguard Worker  -n num      Nop calibration.
368*d83cc019SAndroid Build Coastguard Worker  -b str      Balancer to pre-select.
369*d83cc019SAndroid Build Coastguard Worker              Skips balancer auto-selection.
370*d83cc019SAndroid Build Coastguard Worker              Passed straight the gem_wsim so use like -b "-b qd -R"
371*d83cc019SAndroid Build Coastguard Worker  -W a,b,c    Override the default list of workloads.
372*d83cc019SAndroid Build Coastguard Worker  -B a,b,c    Override the default list of balancers.
373*d83cc019SAndroid Build Coastguard Worker  -r sec      Target workload duration.
374*d83cc019SAndroid Build Coastguard Worker  -t pct      Calibration tolerance.
375*d83cc019SAndroid Build Coastguard Worker  -i pct      Engine idleness tolerance.
376*d83cc019SAndroid Build Coastguard Worker  -R wps      Run workloads in the real-time mode at wps rate.
377*d83cc019SAndroid Build Coastguard Worker  -T wps      Calibrate up to wps/client target instead of GPU saturation.
378*d83cc019SAndroid Build Coastguard Worker              Negative values set the target based on the single client
379*d83cc019SAndroid Build Coastguard Worker              performance where target = single-client-wps / -N.
380*d83cc019SAndroid Build Coastguard Worker  -w str      Pass-through to gem_wsim. Overrides normal workload selection.
381*d83cc019SAndroid Build Coastguard Worker  -m          Multi-workload mode. All selected workloads will be run in
382*d83cc019SAndroid Build Coastguard Worker              parallel and overal score will be relative to when run
383*d83cc019SAndroid Build Coastguard Worker              individually.
384*d83cc019SAndroid Build Coastguard WorkerENDHELP
385*d83cc019SAndroid Build Coastguard Worker	exit 0;
386*d83cc019SAndroid Build Coastguard Worker}
387*d83cc019SAndroid Build Coastguard Worker
388*d83cc019SAndroid Build Coastguard Worker$verbose = 1 if defined $opts{'v'};
389*d83cc019SAndroid Build Coastguard Worker$gt2 = 1 if defined $opts{'2'};
390*d83cc019SAndroid Build Coastguard Worker$show_cmds = 1 if defined $opts{'x'};
391*d83cc019SAndroid Build Coastguard Worker$multi_mode = 1 if defined $opts{'m'};
392*d83cc019SAndroid Build Coastguard Workerif (defined $opts{'b'}) {
393*d83cc019SAndroid Build Coastguard Worker	die unless substr($opts{'b'}, 0, 2) eq '-b';
394*d83cc019SAndroid Build Coastguard Worker	$balancer = $opts{'b'};
395*d83cc019SAndroid Build Coastguard Worker}
396*d83cc019SAndroid Build Coastguard Workerif (defined $opts{'B'}) {
397*d83cc019SAndroid Build Coastguard Worker	@balancers = split /,/, $opts{'B'};
398*d83cc019SAndroid Build Coastguard Worker} else {
399*d83cc019SAndroid Build Coastguard Worker	unshift @balancers, '';
400*d83cc019SAndroid Build Coastguard Worker}
401*d83cc019SAndroid Build Coastguard Worker@workloads = split /,/, $opts{'W'} if defined $opts{'W'};
402*d83cc019SAndroid Build Coastguard Worker$client_target_s = $opts{'r'} if defined $opts{'r'};
403*d83cc019SAndroid Build Coastguard Worker$tolerance = $opts{'t'} / 100.0 if defined $opts{'t'};
404*d83cc019SAndroid Build Coastguard Worker$idle_tolerance_pct = $opts{'i'} if defined $opts{'i'};
405*d83cc019SAndroid Build Coastguard Worker$realtime_target = $opts{'R'} if defined $opts{'R'};
406*d83cc019SAndroid Build Coastguard Worker$wps_target = $opts{'T'} if defined $opts{'T'};
407*d83cc019SAndroid Build Coastguard Worker$wps_target_param = $wps_target;
408*d83cc019SAndroid Build Coastguard Worker$w_direct = $opts{'w'} if defined $opts{'w'};
409*d83cc019SAndroid Build Coastguard Worker
410*d83cc019SAndroid Build Coastguard Workerif ($multi_mode) {
411*d83cc019SAndroid Build Coastguard Worker	die if $w_direct; # Not supported
412*d83cc019SAndroid Build Coastguard Worker	@multi_workloads = @workloads;
413*d83cc019SAndroid Build Coastguard Worker}
414*d83cc019SAndroid Build Coastguard Worker
415*d83cc019SAndroid Build Coastguard Worker@workloads = ($w_direct) if defined $w_direct;
416*d83cc019SAndroid Build Coastguard Worker
417*d83cc019SAndroid Build Coastguard Workersay "Workloads:";
418*d83cc019SAndroid Build Coastguard Workerprint map { "  $_\n" } @workloads;
419*d83cc019SAndroid Build Coastguard Workerprint "Balancers: ";
420*d83cc019SAndroid Build Coastguard Workersay map { "$_," } @balancers;
421*d83cc019SAndroid Build Coastguard Workersay "Target workload duration is ${client_target_s}s.";
422*d83cc019SAndroid Build Coastguard Workersay "Calibration tolerance is $tolerance.";
423*d83cc019SAndroid Build Coastguard Workersay "Real-time mode at ${realtime_target} wps." if $realtime_target > 0;
424*d83cc019SAndroid Build Coastguard Workersay "Wps target is ${wps_target} wps." if $wps_target > 0;
425*d83cc019SAndroid Build Coastguard Workersay "Multi-workload mode." if $multi_mode;
426*d83cc019SAndroid Build Coastguard Worker$nop = $opts{'n'};
427*d83cc019SAndroid Build Coastguard Worker$nop = calibrate_nop() unless $nop;
428*d83cc019SAndroid Build Coastguard Workersay "Nop calibration is $nop.";
429*d83cc019SAndroid Build Coastguard Worker
430*d83cc019SAndroid Build Coastguard Workergoto VERIFY if defined $balancer;
431*d83cc019SAndroid Build Coastguard Worker
432*d83cc019SAndroid Build Coastguard Workermy (%best_bal, %best_bid);
433*d83cc019SAndroid Build Coastguard Workermy %results;
434*d83cc019SAndroid Build Coastguard Workermy %scores;
435*d83cc019SAndroid Build Coastguard Workermy %wscores;
436*d83cc019SAndroid Build Coastguard Workermy %cscores;
437*d83cc019SAndroid Build Coastguard Workermy %cwscores;
438*d83cc019SAndroid Build Coastguard Workermy %mscores;
439*d83cc019SAndroid Build Coastguard Workermy %mwscores;
440*d83cc019SAndroid Build Coastguard Worker
441*d83cc019SAndroid Build Coastguard Workersub add_points
442*d83cc019SAndroid Build Coastguard Worker{
443*d83cc019SAndroid Build Coastguard Worker	my ($wps, $scores, $wscores) = @_;
444*d83cc019SAndroid Build Coastguard Worker	my ($min, $max, $spread);
445*d83cc019SAndroid Build Coastguard Worker	my @sorted;
446*d83cc019SAndroid Build Coastguard Worker
447*d83cc019SAndroid Build Coastguard Worker	@sorted = sort { $b <=> $a } values %{$wps};
448*d83cc019SAndroid Build Coastguard Worker	$max = $sorted[0];
449*d83cc019SAndroid Build Coastguard Worker	$min = $sorted[-1];
450*d83cc019SAndroid Build Coastguard Worker	$spread = $max - $min;
451*d83cc019SAndroid Build Coastguard Worker	die if $spread < 0;
452*d83cc019SAndroid Build Coastguard Worker
453*d83cc019SAndroid Build Coastguard Worker	foreach my $w (keys %{$wps}) {
454*d83cc019SAndroid Build Coastguard Worker		my ($score, $wscore);
455*d83cc019SAndroid Build Coastguard Worker
456*d83cc019SAndroid Build Coastguard Worker		unless (exists $scores->{$w}) {
457*d83cc019SAndroid Build Coastguard Worker			$scores->{$w} = 0;
458*d83cc019SAndroid Build Coastguard Worker			$wscores->{$w} = 0;
459*d83cc019SAndroid Build Coastguard Worker		}
460*d83cc019SAndroid Build Coastguard Worker
461*d83cc019SAndroid Build Coastguard Worker		$score = $wps->{$w} / $max;
462*d83cc019SAndroid Build Coastguard Worker		$scores->{$w} = $scores->{$w} + $score;
463*d83cc019SAndroid Build Coastguard Worker		$wscore = $score * $spread / $max;
464*d83cc019SAndroid Build Coastguard Worker		$wscores->{$w} = $wscores->{$w} + $wscore;
465*d83cc019SAndroid Build Coastguard Worker	}
466*d83cc019SAndroid Build Coastguard Worker}
467*d83cc019SAndroid Build Coastguard Worker
468*d83cc019SAndroid Build Coastguard Workermy @saturation_workloads = $multi_mode ? @multi_workloads : @workloads;
469*d83cc019SAndroid Build Coastguard Workermy %allwps;
470*d83cc019SAndroid Build Coastguard Workermy $widx = 0;
471*d83cc019SAndroid Build Coastguard Worker
472*d83cc019SAndroid Build Coastguard Workerpush @saturation_workloads, '-w ' . join ' -w ', map("$wrk_root/$_", @workloads)
473*d83cc019SAndroid Build Coastguard Worker     if $multi_mode;
474*d83cc019SAndroid Build Coastguard Worker
475*d83cc019SAndroid Build Coastguard Workerforeach my $wrk (@saturation_workloads) {
476*d83cc019SAndroid Build Coastguard Worker	my @args = ( "-n $nop");
477*d83cc019SAndroid Build Coastguard Worker	my ($r, $error, $should_b, $best);
478*d83cc019SAndroid Build Coastguard Worker	my (%wps, %cwps, %mwps);
479*d83cc019SAndroid Build Coastguard Worker	my @sorted;
480*d83cc019SAndroid Build Coastguard Worker	my $range;
481*d83cc019SAndroid Build Coastguard Worker
482*d83cc019SAndroid Build Coastguard Worker	$w_direct = $wrk if $multi_mode and $widx == $#saturation_workloads;
483*d83cc019SAndroid Build Coastguard Worker
484*d83cc019SAndroid Build Coastguard Worker	$should_b = 1;
485*d83cc019SAndroid Build Coastguard Worker	$should_b = can_balance_workload($wrk) unless defined $w_direct;
486*d83cc019SAndroid Build Coastguard Worker
487*d83cc019SAndroid Build Coastguard Worker	print "\nEvaluating '$wrk'...";
488*d83cc019SAndroid Build Coastguard Worker
489*d83cc019SAndroid Build Coastguard Worker	($r, $error) = calibrate_workload($wrk);
490*d83cc019SAndroid Build Coastguard Worker	say " ${client_target_s}s is $r workloads. (error=$error)";
491*d83cc019SAndroid Build Coastguard Worker
492*d83cc019SAndroid Build Coastguard Worker	say "  Finding saturation points for '$wrk'...";
493*d83cc019SAndroid Build Coastguard Worker
494*d83cc019SAndroid Build Coastguard Worker	BAL: foreach my $bal (@balancers) {
495*d83cc019SAndroid Build Coastguard Worker		GBAL: foreach my $G ('', '-G', '-d', '-G -d') {
496*d83cc019SAndroid Build Coastguard Worker			foreach my $H ('', '-H') {
497*d83cc019SAndroid Build Coastguard Worker				my @xargs;
498*d83cc019SAndroid Build Coastguard Worker				my ($w, $c, $s, $bwwps);
499*d83cc019SAndroid Build Coastguard Worker				my $bid;
500*d83cc019SAndroid Build Coastguard Worker
501*d83cc019SAndroid Build Coastguard Worker				if ($bal ne '') {
502*d83cc019SAndroid Build Coastguard Worker					next GBAL if $G =~ '-G' and exists $bal_skip_G{$bal};
503*d83cc019SAndroid Build Coastguard Worker
504*d83cc019SAndroid Build Coastguard Worker					push @xargs, "-b $bal";
505*d83cc019SAndroid Build Coastguard Worker					push @xargs, '-R' unless exists $bal_skip_R{$bal};
506*d83cc019SAndroid Build Coastguard Worker					push @xargs, $G if $G ne '';
507*d83cc019SAndroid Build Coastguard Worker					push @xargs, $H if $H ne '';
508*d83cc019SAndroid Build Coastguard Worker					$bid = join ' ', @xargs;
509*d83cc019SAndroid Build Coastguard Worker					print "    $bal balancer ('$bid'): ";
510*d83cc019SAndroid Build Coastguard Worker				} else {
511*d83cc019SAndroid Build Coastguard Worker					$bid = '<none>';
512*d83cc019SAndroid Build Coastguard Worker					print "    No balancing: ";
513*d83cc019SAndroid Build Coastguard Worker				}
514*d83cc019SAndroid Build Coastguard Worker
515*d83cc019SAndroid Build Coastguard Worker				$wps_target = 0 if $wps_target_param < 0;
516*d83cc019SAndroid Build Coastguard Worker
517*d83cc019SAndroid Build Coastguard Worker				($c, $w, $s, $bwwps) =
518*d83cc019SAndroid Build Coastguard Worker					find_saturation_point($wrk, $r, 0,
519*d83cc019SAndroid Build Coastguard Worker							      (@args, @xargs));
520*d83cc019SAndroid Build Coastguard Worker
521*d83cc019SAndroid Build Coastguard Worker				if ($wps_target_param < 0) {
522*d83cc019SAndroid Build Coastguard Worker					$wps_target = $s / -$wps_target_param;
523*d83cc019SAndroid Build Coastguard Worker
524*d83cc019SAndroid Build Coastguard Worker					($c, $w, $s, $bwwps) =
525*d83cc019SAndroid Build Coastguard Worker						find_saturation_point($wrk, $r,
526*d83cc019SAndroid Build Coastguard Worker								      0,
527*d83cc019SAndroid Build Coastguard Worker								      (@args,
528*d83cc019SAndroid Build Coastguard Worker								       @xargs));
529*d83cc019SAndroid Build Coastguard Worker				}
530*d83cc019SAndroid Build Coastguard Worker
531*d83cc019SAndroid Build Coastguard Worker				if ($multi_mode and $w_direct) {
532*d83cc019SAndroid Build Coastguard Worker					my $widx;
533*d83cc019SAndroid Build Coastguard Worker
534*d83cc019SAndroid Build Coastguard Worker					die unless scalar(@multi_workloads) ==
535*d83cc019SAndroid Build Coastguard Worker						   scalar(@{$bwwps});
536*d83cc019SAndroid Build Coastguard Worker					die unless scalar(@multi_workloads) ==
537*d83cc019SAndroid Build Coastguard Worker						   scalar(keys %allwps);
538*d83cc019SAndroid Build Coastguard Worker
539*d83cc019SAndroid Build Coastguard Worker					# Total of all workload wps from the
540*d83cc019SAndroid Build Coastguard Worker					# mixed run.
541*d83cc019SAndroid Build Coastguard Worker					$w = 0;
542*d83cc019SAndroid Build Coastguard Worker					foreach $widx (0..$#{$bwwps}) {
543*d83cc019SAndroid Build Coastguard Worker						$w += $bwwps->[$widx];
544*d83cc019SAndroid Build Coastguard Worker					}
545*d83cc019SAndroid Build Coastguard Worker
546*d83cc019SAndroid Build Coastguard Worker					# Total of all workload wps from when
547*d83cc019SAndroid Build Coastguard Worker					# ran individually with the best
548*d83cc019SAndroid Build Coastguard Worker					# balancer.
549*d83cc019SAndroid Build Coastguard Worker					my $tot = 0;
550*d83cc019SAndroid Build Coastguard Worker					foreach my $wrk (@multi_workloads) {
551*d83cc019SAndroid Build Coastguard Worker						$tot += $allwps{$wrk}->{$best_bid{$wrk}};
552*d83cc019SAndroid Build Coastguard Worker					}
553*d83cc019SAndroid Build Coastguard Worker
554*d83cc019SAndroid Build Coastguard Worker					# Normalize mixed sum with sum of
555*d83cc019SAndroid Build Coastguard Worker					# individual runs.
556*d83cc019SAndroid Build Coastguard Worker					$w *= 100;
557*d83cc019SAndroid Build Coastguard Worker					$w /= $tot;
558*d83cc019SAndroid Build Coastguard Worker
559*d83cc019SAndroid Build Coastguard Worker					# Second metric is average of each
560*d83cc019SAndroid Build Coastguard Worker					# workload wps normalized by their
561*d83cc019SAndroid Build Coastguard Worker					# individual run performance with the
562*d83cc019SAndroid Build Coastguard Worker					# best balancer.
563*d83cc019SAndroid Build Coastguard Worker					$s = 0;
564*d83cc019SAndroid Build Coastguard Worker					$widx = 0;
565*d83cc019SAndroid Build Coastguard Worker					foreach my $wrk (@multi_workloads) {
566*d83cc019SAndroid Build Coastguard Worker						$s += 100 * $bwwps->[$widx] /
567*d83cc019SAndroid Build Coastguard Worker						      $allwps{$wrk}->{$best_bid{$wrk}};
568*d83cc019SAndroid Build Coastguard Worker						$widx++;
569*d83cc019SAndroid Build Coastguard Worker					}
570*d83cc019SAndroid Build Coastguard Worker					$s /= scalar(@multi_workloads);
571*d83cc019SAndroid Build Coastguard Worker
572*d83cc019SAndroid Build Coastguard Worker					say sprintf('Aggregate (normalized) %.2f%%; fairness %.2f%%',
573*d83cc019SAndroid Build Coastguard Worker						    $w, $s);
574*d83cc019SAndroid Build Coastguard Worker				} else {
575*d83cc019SAndroid Build Coastguard Worker					$allwps{$wrk} = \%wps;
576*d83cc019SAndroid Build Coastguard Worker				}
577*d83cc019SAndroid Build Coastguard Worker
578*d83cc019SAndroid Build Coastguard Worker				$wps{$bid} = $w;
579*d83cc019SAndroid Build Coastguard Worker				$cwps{$bid} = $s;
580*d83cc019SAndroid Build Coastguard Worker
581*d83cc019SAndroid Build Coastguard Worker				if ($realtime_target > 0 || $wps_target_param > 0) {
582*d83cc019SAndroid Build Coastguard Worker					$mwps{$bid} = $w * $c;
583*d83cc019SAndroid Build Coastguard Worker				} else {
584*d83cc019SAndroid Build Coastguard Worker					$mwps{$bid} = $w + $s;
585*d83cc019SAndroid Build Coastguard Worker				}
586*d83cc019SAndroid Build Coastguard Worker
587*d83cc019SAndroid Build Coastguard Worker				say "$c clients ($w wps, $s wps single client, score=$mwps{$bid})."
588*d83cc019SAndroid Build Coastguard Worker				    unless $multi_mode and $w_direct;
589*d83cc019SAndroid Build Coastguard Worker
590*d83cc019SAndroid Build Coastguard Worker				last BAL unless $should_b;
591*d83cc019SAndroid Build Coastguard Worker				next BAL if $bal eq '';
592*d83cc019SAndroid Build Coastguard Worker				next GBAL if exists $bal_skip_H{$bal};
593*d83cc019SAndroid Build Coastguard Worker			}
594*d83cc019SAndroid Build Coastguard Worker		}
595*d83cc019SAndroid Build Coastguard Worker	}
596*d83cc019SAndroid Build Coastguard Worker
597*d83cc019SAndroid Build Coastguard Worker	$widx++;
598*d83cc019SAndroid Build Coastguard Worker
599*d83cc019SAndroid Build Coastguard Worker	@sorted = sort { $mwps{$b} <=> $mwps{$a} } keys %mwps;
600*d83cc019SAndroid Build Coastguard Worker	$best_bid{$wrk} = $sorted[0];
601*d83cc019SAndroid Build Coastguard Worker	@sorted = sort { $b <=> $a } values %mwps;
602*d83cc019SAndroid Build Coastguard Worker	$range = 1 - $sorted[-1] / $sorted[0];
603*d83cc019SAndroid Build Coastguard Worker	$best_bal{$wrk} = $sorted[0];
604*d83cc019SAndroid Build Coastguard Worker
605*d83cc019SAndroid Build Coastguard Worker	next if $multi_mode and not $w_direct;
606*d83cc019SAndroid Build Coastguard Worker
607*d83cc019SAndroid Build Coastguard Worker	say "  Best balancer is '$best_bid{$wrk}' (range=$range).";
608*d83cc019SAndroid Build Coastguard Worker
609*d83cc019SAndroid Build Coastguard Worker
610*d83cc019SAndroid Build Coastguard Worker	$results{$wrk} = \%mwps;
611*d83cc019SAndroid Build Coastguard Worker
612*d83cc019SAndroid Build Coastguard Worker	add_points(\%wps, \%scores, \%wscores);
613*d83cc019SAndroid Build Coastguard Worker	add_points(\%mwps, \%mscores, \%mwscores);
614*d83cc019SAndroid Build Coastguard Worker	add_points(\%cwps, \%cscores, \%cwscores);
615*d83cc019SAndroid Build Coastguard Worker}
616*d83cc019SAndroid Build Coastguard Worker
617*d83cc019SAndroid Build Coastguard Workersub dump_scoreboard
618*d83cc019SAndroid Build Coastguard Worker{
619*d83cc019SAndroid Build Coastguard Worker	my ($n, $h) = @_;
620*d83cc019SAndroid Build Coastguard Worker	my ($i, $str, $balancer);
621*d83cc019SAndroid Build Coastguard Worker	my ($max, $range);
622*d83cc019SAndroid Build Coastguard Worker	my @sorted;
623*d83cc019SAndroid Build Coastguard Worker
624*d83cc019SAndroid Build Coastguard Worker	@sorted = sort { $b <=> $a } values %{$h};
625*d83cc019SAndroid Build Coastguard Worker	$max = $sorted[0];
626*d83cc019SAndroid Build Coastguard Worker	$range = 1 - $sorted[-1] / $max;
627*d83cc019SAndroid Build Coastguard Worker	$str = "$n rank (range=$range):";
628*d83cc019SAndroid Build Coastguard Worker	say "\n$str";
629*d83cc019SAndroid Build Coastguard Worker	say '=' x length($str);
630*d83cc019SAndroid Build Coastguard Worker	$i = 1;
631*d83cc019SAndroid Build Coastguard Worker	foreach my $w (sort { $h->{$b} <=> $h->{$a} } keys %{$h}) {
632*d83cc019SAndroid Build Coastguard Worker		my $score;
633*d83cc019SAndroid Build Coastguard Worker
634*d83cc019SAndroid Build Coastguard Worker		$balancer = $w if $i == 1;
635*d83cc019SAndroid Build Coastguard Worker		$score = $h->{$w} / $max;
636*d83cc019SAndroid Build Coastguard Worker
637*d83cc019SAndroid Build Coastguard Worker		say "  $i: '$w' ($score)";
638*d83cc019SAndroid Build Coastguard Worker
639*d83cc019SAndroid Build Coastguard Worker		$i = $i + 1;
640*d83cc019SAndroid Build Coastguard Worker	}
641*d83cc019SAndroid Build Coastguard Worker
642*d83cc019SAndroid Build Coastguard Worker	return $balancer;
643*d83cc019SAndroid Build Coastguard Worker}
644*d83cc019SAndroid Build Coastguard Worker
645*d83cc019SAndroid Build Coastguard Workerdump_scoreboard($multi_mode ? 'Throughput' : 'Total wps', \%scores);
646*d83cc019SAndroid Build Coastguard Workerdump_scoreboard('Total weighted wps', \%wscores) unless $multi_mode;
647*d83cc019SAndroid Build Coastguard Workerdump_scoreboard($multi_mode ? 'Fairness' : 'Per client wps', \%cscores);
648*d83cc019SAndroid Build Coastguard Workerdump_scoreboard('Per client weighted wps', \%cwscores) unless $multi_mode;
649*d83cc019SAndroid Build Coastguard Worker$balancer = dump_scoreboard($multi_mode ? 'Combined' : 'Combined wps', \%mscores);
650*d83cc019SAndroid Build Coastguard Worker$balancer = dump_scoreboard('Combined weighted wps', \%mwscores) unless $multi_mode;
651*d83cc019SAndroid Build Coastguard Worker
652*d83cc019SAndroid Build Coastguard WorkerVERIFY:
653*d83cc019SAndroid Build Coastguard Worker
654*d83cc019SAndroid Build Coastguard Workermy %problem_wrk;
655*d83cc019SAndroid Build Coastguard Worker
656*d83cc019SAndroid Build Coastguard Workerdie unless defined $balancer;
657*d83cc019SAndroid Build Coastguard Worker
658*d83cc019SAndroid Build Coastguard Workersay "\nBalancer is '$balancer'.";
659*d83cc019SAndroid Build Coastguard Workersay "Idleness tolerance is $idle_tolerance_pct%.";
660*d83cc019SAndroid Build Coastguard Worker
661*d83cc019SAndroid Build Coastguard Workerif ($multi_mode) {
662*d83cc019SAndroid Build Coastguard Worker	$w_direct = '-w ' . join ' -w ', map("$wrk_root/$_", @workloads);
663*d83cc019SAndroid Build Coastguard Worker	@workloads = ($w_direct);
664*d83cc019SAndroid Build Coastguard Worker}
665*d83cc019SAndroid Build Coastguard Worker
666*d83cc019SAndroid Build Coastguard Workerforeach my $wrk (@workloads) {
667*d83cc019SAndroid Build Coastguard Worker	my @args = ( "-n $nop" );
668*d83cc019SAndroid Build Coastguard Worker	my ($r, $error, $c, $wps, $swps);
669*d83cc019SAndroid Build Coastguard Worker	my $saturated = 0;
670*d83cc019SAndroid Build Coastguard Worker	my $result = 'Pass';
671*d83cc019SAndroid Build Coastguard Worker	my $vcs2 = $gt2 ? '1:0' : '2:1';
672*d83cc019SAndroid Build Coastguard Worker	my %problem;
673*d83cc019SAndroid Build Coastguard Worker	my $engines;
674*d83cc019SAndroid Build Coastguard Worker
675*d83cc019SAndroid Build Coastguard Worker	next if not defined $w_direct and not can_balance_workload($wrk);
676*d83cc019SAndroid Build Coastguard Worker
677*d83cc019SAndroid Build Coastguard Worker	push @args, $balancer unless $balancer eq '<none>';
678*d83cc019SAndroid Build Coastguard Worker
679*d83cc019SAndroid Build Coastguard Worker	if (scalar(keys %results)) {
680*d83cc019SAndroid Build Coastguard Worker		$r = $results{$wrk}->{$balancer} / $best_bal{$wrk} * 100.0;
681*d83cc019SAndroid Build Coastguard Worker	} else {
682*d83cc019SAndroid Build Coastguard Worker		$r = '---';
683*d83cc019SAndroid Build Coastguard Worker	}
684*d83cc019SAndroid Build Coastguard Worker	say "  \nProfiling '$wrk' ($r% of best)...";
685*d83cc019SAndroid Build Coastguard Worker
686*d83cc019SAndroid Build Coastguard Worker	($r, $error) = calibrate_workload($wrk);
687*d83cc019SAndroid Build Coastguard Worker	say "      ${client_target_s}s is $r workloads. (error=$error)";
688*d83cc019SAndroid Build Coastguard Worker
689*d83cc019SAndroid Build Coastguard Worker	($c, $wps, $swps) = find_saturation_point($wrk, $r, $verbose, @args);
690*d83cc019SAndroid Build Coastguard Worker	say "      Saturation at $c clients ($wps workloads/s).";
691*d83cc019SAndroid Build Coastguard Worker	push @args, "-c $c";
692*d83cc019SAndroid Build Coastguard Worker
693*d83cc019SAndroid Build Coastguard Worker	$engines = trace_workload($wrk, $balancer, $r, $c);
694*d83cc019SAndroid Build Coastguard Worker
695*d83cc019SAndroid Build Coastguard Worker	foreach my $key (keys %{$engines}) {
696*d83cc019SAndroid Build Coastguard Worker		next if $key eq 'gpu';
697*d83cc019SAndroid Build Coastguard Worker		$saturated = $saturated + 1
698*d83cc019SAndroid Build Coastguard Worker			     if $engines->{$key} < $idle_tolerance_pct;
699*d83cc019SAndroid Build Coastguard Worker	}
700*d83cc019SAndroid Build Coastguard Worker
701*d83cc019SAndroid Build Coastguard Worker	if ($saturated == 0) {
702*d83cc019SAndroid Build Coastguard Worker		# Not a single saturated engine
703*d83cc019SAndroid Build Coastguard Worker		$result = 'FAIL';
704*d83cc019SAndroid Build Coastguard Worker	} elsif (not exists $engines->{'2:0'} or not exists $engines->{$vcs2}) {
705*d83cc019SAndroid Build Coastguard Worker		# VCS1 and VCS2 not present in a balancing workload
706*d83cc019SAndroid Build Coastguard Worker		$result = 'FAIL';
707*d83cc019SAndroid Build Coastguard Worker	} elsif ($saturated == 1 and
708*d83cc019SAndroid Build Coastguard Worker		 ($engines->{'2:0'} < $idle_tolerance_pct or
709*d83cc019SAndroid Build Coastguard Worker		  $engines->{$vcs2} < $idle_tolerance_pct)) {
710*d83cc019SAndroid Build Coastguard Worker		# Only one VCS saturated
711*d83cc019SAndroid Build Coastguard Worker		$result = 'WARN';
712*d83cc019SAndroid Build Coastguard Worker	}
713*d83cc019SAndroid Build Coastguard Worker
714*d83cc019SAndroid Build Coastguard Worker	$result = 'WARN' if $engines->{'gpu'} > $idle_tolerance_pct;
715*d83cc019SAndroid Build Coastguard Worker
716*d83cc019SAndroid Build Coastguard Worker	if ($result ne 'Pass') {
717*d83cc019SAndroid Build Coastguard Worker		$problem{'c'} = $c;
718*d83cc019SAndroid Build Coastguard Worker		$problem{'r'} = $r;
719*d83cc019SAndroid Build Coastguard Worker		$problem{'stats'} = $engines;
720*d83cc019SAndroid Build Coastguard Worker		$problem_wrk{$wrk} = \%problem;
721*d83cc019SAndroid Build Coastguard Worker	}
722*d83cc019SAndroid Build Coastguard Worker
723*d83cc019SAndroid Build Coastguard Worker	print "    $result [";
724*d83cc019SAndroid Build Coastguard Worker	print map " $_: $engines->{$_}%,", sort keys %{$engines};
725*d83cc019SAndroid Build Coastguard Worker	say " ]";
726*d83cc019SAndroid Build Coastguard Worker}
727*d83cc019SAndroid Build Coastguard Worker
728*d83cc019SAndroid Build Coastguard Workersay "\nProblematic workloads were:" if scalar(keys %problem_wrk) > 0;
729*d83cc019SAndroid Build Coastguard Workerforeach my $wrk (sort keys %problem_wrk) {
730*d83cc019SAndroid Build Coastguard Worker	my $problem = $problem_wrk{$wrk};
731*d83cc019SAndroid Build Coastguard Worker
732*d83cc019SAndroid Build Coastguard Worker	print "   $wrk -c $problem->{'c'} -r $problem->{'r'} [";
733*d83cc019SAndroid Build Coastguard Worker	print map " $_: $problem->{'stats'}->{$_}%,",
734*d83cc019SAndroid Build Coastguard Worker	      sort keys %{$problem->{'stats'}};
735*d83cc019SAndroid Build Coastguard Worker	say " ]";
736*d83cc019SAndroid Build Coastguard Worker}
737