summaryrefslogtreecommitdiff
path: root/scripts/media-bench.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/media-bench.pl')
-rwxr-xr-xscripts/media-bench.pl736
1 files changed, 0 insertions, 736 deletions
diff --git a/scripts/media-bench.pl b/scripts/media-bench.pl
deleted file mode 100755
index 1cd8205f..00000000
--- a/scripts/media-bench.pl
+++ /dev/null
@@ -1,736 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright © 2017 Intel Corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-
-use strict;
-use warnings;
-use 5.010;
-
-use Getopt::Std;
-
-chomp(my $igt_root = `pwd -P`);
-my $wsim = "$igt_root/benchmarks/gem_wsim";
-my $wrk_root = "$igt_root/benchmarks/wsim";
-my $tracepl = "$igt_root/scripts/trace.pl";
-my $tolerance = 0.01;
-my $client_target_s = 10;
-my $idle_tolerance_pct = 2.0;
-my $verbose = 0;
-my $gt2 = 0;
-my $show_cmds = 0;
-my $realtime_target = 0;
-my $wps_target = 0;
-my $wps_target_param = 0;
-my $multi_mode = 0;
-my @multi_workloads;
-my $w_direct;
-my $balancer;
-my $nop;
-my %opts;
-
-my @balancers = ( 'rr', 'rand', 'qd', 'qdr', 'qdavg', 'rt', 'rtr', 'rtavg',
- 'context', 'busy', 'busy-avg', 'i915' );
-my %bal_skip_H = ( 'rr' => 1, 'rand' => 1, 'context' => 1, , 'busy' => 1,
- 'busy-avg' => 1, 'i915' => 1 );
-my %bal_skip_R = ( 'i915' => 1 );
-my %bal_skip_G = ( 'i915' => 1 );
-
-my @workloads = (
- 'media_load_balance_17i7.wsim',
- 'media_load_balance_19.wsim',
- 'media_load_balance_4k12u7.wsim',
- 'media_load_balance_fhd26u7.wsim',
- 'media_load_balance_hd01.wsim',
- 'media_load_balance_hd06mp2.wsim',
- 'media_load_balance_hd12.wsim',
- 'media_load_balance_hd17i4.wsim',
- 'media_1n2_480p.wsim',
- 'media_1n3_480p.wsim',
- 'media_1n4_480p.wsim',
- 'media_1n5_480p.wsim',
- 'media_1n2_asy.wsim',
- 'media_1n3_asy.wsim',
- 'media_1n4_asy.wsim',
- 'media_1n5_asy.wsim',
- 'media_mfe2_480p.wsim',
- 'media_mfe3_480p.wsim',
- 'media_mfe4_480p.wsim',
- 'media_nn_1080p.wsim',
- 'media_nn_480p.wsim',
- );
-
-sub show_cmd
-{
- my ($cmd) = @_;
-
- say "\n+++ $cmd" if $show_cmds;
-}
-
-sub calibrate_nop
-{
- my ($delay, $nop);
- my $cmd = "$wsim";
-
- show_cmd($cmd);
- open WSIM, "$cmd |" or die;
- while (<WSIM>) {
- chomp;
- if (/Nop calibration for (\d+)us delay is (\d+)./) {
- $delay = $1;
- $nop = $2;
- }
-
- }
- close WSIM;
-
- die unless $nop;
-
- return $nop
-}
-
-sub can_balance_workload
-{
- my ($wrk) = @_;
- my $res = 0;
-
- open WRK, "$wrk_root/$wrk" or die;
- while (<WRK>) {
- chomp;
- if (/\.VCS\./) {
- $res = 1;
- last;
- }
- }
- close WRK;
-
- return $res;
-}
-
-sub add_wps_arg
-{
- my (@args) = @_;
- my $period;
-
- return @args if $realtime_target <= 0;
-
- $period = int(1000000 / $realtime_target);
- push @args, '-a';
- push @args, 'p.$period';
-
- return @args;
-}
-
-sub run_workload
-{
- my (@args) = @_;
- my ($time, $wps, $cmd);
- my @ret;
-
- @args = add_wps_arg(@args);
- push @args, '-2' if $gt2;
-
- unshift @args, $wsim;
- $cmd = join ' ', @args;
- show_cmd($cmd);
-
- open WSIM, "$cmd |" or die;
- while (<WSIM>) {
- chomp;
- if (/^(\d+\.\d+)s elapsed \((\d+\.?\d+) workloads\/s\)$/) {
- $time = $1;
- $wps = $2;
- } elsif (/(\d+)\: \d+\.\d+s elapsed \(\d+ cycles, (\d+\.?\d+) workloads\/s\)/) {
- $ret[$1] = $2;
- }
- }
- close WSIM;
-
- return ($time, $wps, \@ret);
-}
-
-sub dump_cmd
-{
- my ($cmd, $file) = @_;
-
- show_cmd("$cmd > $file");
-
- open FOUT, '>', $file or die;
- open TIN, "$cmd |" or die;
- while (<TIN>) {
- print FOUT $_;
- }
- close TIN;
- close FOUT;
-}
-
-sub trace_workload
-{
- my ($wrk, $b, $r, $c) = @_;
- my @args = ($tracepl, '--trace', $wsim, '-q', '-n', $nop, '-r', $r, '-c', $c);
- my $min_batches = 16 + $r * $c / 2;
- my @skip_engine;
- my %engines;
- my ($cmd, $file);
-
- push @args, '-2' if $gt2;
-
- unless ($b eq '<none>') {
- push @args, '-R';
- push @args, split /\s+/, $b;
- }
-
- if (defined $w_direct) {
- push @args, split /\s+/, $wrk;
- } else {
- push @args, '-w';
- push @args, $wrk_root . '/' . $wrk;
- }
-
- show_cmd(join ' ', @args);
- if (-e 'perf.data') {
- unlink 'perf.data' or die;
- }
- system(@args) == 0 or die;
-
- $cmd = "perf script | $tracepl";
- show_cmd($cmd);
- open CMD, "$cmd |" or die;
- while (<CMD>) {
- chomp;
- if (/Ring(\S+): (\d+) batches.*?(\d+\.?\d+)% idle,/) {
- if ($2 >= $min_batches) {
- $engines{$1} = $3;
- } else {
- push @skip_engine, $1;
- }
- } elsif (/GPU: (\d+\.?\d+)% idle/) {
- $engines{'gpu'} = $1;
- }
- }
- close CMD;
-
- $wrk =~ s/$wrk_root//g;
- $wrk =~ s/\.wsim//g;
- $wrk =~ s/-w/W/g;
- $wrk =~ s/[ -]/_/g;
- $wrk =~ s/\//-/g;
- $b =~ s/[ <>]/_/g;
- $file = "${wrk}_${b}_-r${r}_-c${c}";
-
- dump_cmd('perf script', "${file}.trace");
-
- $cmd = "perf script | $tracepl --html -x ctxsave -s -c ";
- $cmd .= join ' ', map("-i $_", @skip_engine);
-
- dump_cmd($cmd, "${file}.html");
-
- return \%engines;
-}
-
-sub calibrate_workload
-{
- my ($wrk) = @_;
- my $tol = $tolerance;
- my $loops = 0;
- my $error;
- my $r;
-
- $r = $realtime_target > 0 ? $realtime_target * $client_target_s : 23;
- for (;;) {
- my @args = ('-n', $nop, '-r', $r);
- my ($time, $wps);
-
- if (defined $w_direct) {
- push @args, split /\s+/, $wrk;
- } else {
- push @args, '-w';
- push @args, $wrk_root . '/' . $wrk;
- }
-
- ($time, $wps) = run_workload(@args);
-
- $wps = $r / $time if $w_direct;
- $error = abs($time - $client_target_s) / $client_target_s;
-
- last if $error <= $tol;
-
- $r = int($wps * $client_target_s);
- $loops = $loops + 1;
- if ($loops >= 3) {
- $tol = $tol * (1.2 + ($tol));
- $loops = 0;
- }
- last if $tol > 0.2;
- }
-
- return ($r, $error);
-}
-
-sub find_saturation_point
-{
- my ($wrk, $rr, $verbose, @args) = @_;
- my ($last_wps, $c, $swps, $wwps);
- my $target = $realtime_target > 0 ? $realtime_target : $wps_target;
- my $r = $rr;
- my $wcnt;
- my $maxc;
- my $max = 0;
-
- push @args, '-v' if $multi_mode and $w_direct;
-
- if (defined $w_direct) {
- push @args, split /\s+/, $wrk;
- $wcnt = () = $wrk =~ /-[wW]/gi;
-
- } else {
- push @args, '-w';
- push @args, $wrk_root . '/' . $wrk;
- $wcnt = 1;
- }
-
- for ($c = 1; ; $c = $c + 1) {
- my ($time, $wps);
- my @args_ = (@args, ('-r', $r, '-c', $c));
-
- ($time, $wps, $wwps) = run_workload(@args_);
-
- say " $c clients is $wps wps." if $verbose;
-
- if ($c > 1) {
- my $delta;
-
- if ($target <= 0) {
- if ($wps > $max) {
- $max = $wps;
- $maxc = $c;
- }
- $delta = ($wps - $last_wps) / $last_wps;
- if ($delta > 0) {
- last if $delta < $tolerance;
- } else {
- $delta = ($wps - $max) / $max;
- last if abs($delta) >= $tolerance;
- }
- } else {
- $delta = ($wps / $c - $target) / $target;
- last if $delta < 0 and abs($delta) >= $tolerance;
- }
- $r = int($rr * ($client_target_s / $time));
- } elsif ($c == 1) {
- $swps = $wps;
- return ($c, $wps, $swps, $wwps) if $wcnt > 1 or
- $multi_mode or
- ($wps_target_param < 0 and
- $wps_target == 0);
- }
-
- $last_wps = $wps;
- }
-
- if ($target <= 0) {
- return ($maxc, $max, $swps, $wwps);
- } else {
- return ($c - 1, $last_wps, $swps, $wwps);
- }
-}
-
-getopts('hv2xmn:b:W:B:r:t:i:R:T:w:', \%opts);
-
-if (defined $opts{'h'}) {
- print <<ENDHELP;
-Supported options:
-
- -h Help text.
- -v Be verbose.
- -x Show external commands.
- -2 Run gem_wsim in GT2 mode.
- -n num Nop calibration.
- -b str Balancer to pre-select.
- Skips balancer auto-selection.
- Passed straight the gem_wsim so use like -b "-b qd -R"
- -W a,b,c Override the default list of workloads.
- -B a,b,c Override the default list of balancers.
- -r sec Target workload duration.
- -t pct Calibration tolerance.
- -i pct Engine idleness tolerance.
- -R wps Run workloads in the real-time mode at wps rate.
- -T wps Calibrate up to wps/client target instead of GPU saturation.
- Negative values set the target based on the single client
- performance where target = single-client-wps / -N.
- -w str Pass-through to gem_wsim. Overrides normal workload selection.
- -m Multi-workload mode. All selected workloads will be run in
- parallel and overal score will be relative to when run
- individually.
-ENDHELP
- exit 0;
-}
-
-$verbose = 1 if defined $opts{'v'};
-$gt2 = 1 if defined $opts{'2'};
-$show_cmds = 1 if defined $opts{'x'};
-$multi_mode = 1 if defined $opts{'m'};
-if (defined $opts{'b'}) {
- die unless substr($opts{'b'}, 0, 2) eq '-b';
- $balancer = $opts{'b'};
-}
-if (defined $opts{'B'}) {
- @balancers = split /,/, $opts{'B'};
-} else {
- unshift @balancers, '';
-}
-@workloads = split /,/, $opts{'W'} if defined $opts{'W'};
-$client_target_s = $opts{'r'} if defined $opts{'r'};
-$tolerance = $opts{'t'} / 100.0 if defined $opts{'t'};
-$idle_tolerance_pct = $opts{'i'} if defined $opts{'i'};
-$realtime_target = $opts{'R'} if defined $opts{'R'};
-$wps_target = $opts{'T'} if defined $opts{'T'};
-$wps_target_param = $wps_target;
-$w_direct = $opts{'w'} if defined $opts{'w'};
-
-if ($multi_mode) {
- die if $w_direct; # Not supported
- @multi_workloads = @workloads;
-}
-
-@workloads = ($w_direct) if defined $w_direct;
-
-say "Workloads:";
-print map { " $_\n" } @workloads;
-print "Balancers: ";
-say map { "$_," } @balancers;
-say "Target workload duration is ${client_target_s}s.";
-say "Calibration tolerance is $tolerance.";
-say "Real-time mode at ${realtime_target} wps." if $realtime_target > 0;
-say "Wps target is ${wps_target} wps." if $wps_target > 0;
-say "Multi-workload mode." if $multi_mode;
-$nop = $opts{'n'};
-$nop = calibrate_nop() unless $nop;
-say "Nop calibration is $nop.";
-
-goto VERIFY if defined $balancer;
-
-my (%best_bal, %best_bid);
-my %results;
-my %scores;
-my %wscores;
-my %cscores;
-my %cwscores;
-my %mscores;
-my %mwscores;
-
-sub add_points
-{
- my ($wps, $scores, $wscores) = @_;
- my ($min, $max, $spread);
- my @sorted;
-
- @sorted = sort { $b <=> $a } values %{$wps};
- $max = $sorted[0];
- $min = $sorted[-1];
- $spread = $max - $min;
- die if $spread < 0;
-
- foreach my $w (keys %{$wps}) {
- my ($score, $wscore);
-
- unless (exists $scores->{$w}) {
- $scores->{$w} = 0;
- $wscores->{$w} = 0;
- }
-
- $score = $wps->{$w} / $max;
- $scores->{$w} = $scores->{$w} + $score;
- $wscore = $score * $spread / $max;
- $wscores->{$w} = $wscores->{$w} + $wscore;
- }
-}
-
-my @saturation_workloads = $multi_mode ? @multi_workloads : @workloads;
-my %allwps;
-my $widx = 0;
-
-push @saturation_workloads, '-w ' . join ' -w ', map("$wrk_root/$_", @workloads)
- if $multi_mode;
-
-foreach my $wrk (@saturation_workloads) {
- my @args = ( "-n $nop");
- my ($r, $error, $should_b, $best);
- my (%wps, %cwps, %mwps);
- my @sorted;
- my $range;
-
- $w_direct = $wrk if $multi_mode and $widx == $#saturation_workloads;
-
- $should_b = 1;
- $should_b = can_balance_workload($wrk) unless defined $w_direct;
-
- print "\nEvaluating '$wrk'...";
-
- ($r, $error) = calibrate_workload($wrk);
- say " ${client_target_s}s is $r workloads. (error=$error)";
-
- say " Finding saturation points for '$wrk'...";
-
- BAL: foreach my $bal (@balancers) {
- GBAL: foreach my $G ('', '-G', '-d', '-G -d') {
- foreach my $H ('', '-H') {
- my @xargs;
- my ($w, $c, $s, $bwwps);
- my $bid;
-
- if ($bal ne '') {
- next GBAL if $G =~ '-G' and exists $bal_skip_G{$bal};
-
- push @xargs, "-b $bal";
- push @xargs, '-R' unless exists $bal_skip_R{$bal};
- push @xargs, $G if $G ne '';
- push @xargs, $H if $H ne '';
- $bid = join ' ', @xargs;
- print " $bal balancer ('$bid'): ";
- } else {
- $bid = '<none>';
- print " No balancing: ";
- }
-
- $wps_target = 0 if $wps_target_param < 0;
-
- ($c, $w, $s, $bwwps) =
- find_saturation_point($wrk, $r, 0,
- (@args, @xargs));
-
- if ($wps_target_param < 0) {
- $wps_target = $s / -$wps_target_param;
-
- ($c, $w, $s, $bwwps) =
- find_saturation_point($wrk, $r,
- 0,
- (@args,
- @xargs));
- }
-
- if ($multi_mode and $w_direct) {
- my $widx;
-
- die unless scalar(@multi_workloads) ==
- scalar(@{$bwwps});
- die unless scalar(@multi_workloads) ==
- scalar(keys %allwps);
-
- # Total of all workload wps from the
- # mixed run.
- $w = 0;
- foreach $widx (0..$#{$bwwps}) {
- $w += $bwwps->[$widx];
- }
-
- # Total of all workload wps from when
- # ran individually with the best
- # balancer.
- my $tot = 0;
- foreach my $wrk (@multi_workloads) {
- $tot += $allwps{$wrk}->{$best_bid{$wrk}};
- }
-
- # Normalize mixed sum with sum of
- # individual runs.
- $w *= 100;
- $w /= $tot;
-
- # Second metric is average of each
- # workload wps normalized by their
- # individual run performance with the
- # best balancer.
- $s = 0;
- $widx = 0;
- foreach my $wrk (@multi_workloads) {
- $s += 100 * $bwwps->[$widx] /
- $allwps{$wrk}->{$best_bid{$wrk}};
- $widx++;
- }
- $s /= scalar(@multi_workloads);
-
- say sprintf('Aggregate (normalized) %.2f%%; fairness %.2f%%',
- $w, $s);
- } else {
- $allwps{$wrk} = \%wps;
- }
-
- $wps{$bid} = $w;
- $cwps{$bid} = $s;
-
- if ($realtime_target > 0 || $wps_target_param > 0) {
- $mwps{$bid} = $w * $c;
- } else {
- $mwps{$bid} = $w + $s;
- }
-
- say "$c clients ($w wps, $s wps single client, score=$mwps{$bid})."
- unless $multi_mode and $w_direct;
-
- last BAL unless $should_b;
- next BAL if $bal eq '';
- next GBAL if exists $bal_skip_H{$bal};
- }
- }
- }
-
- $widx++;
-
- @sorted = sort { $mwps{$b} <=> $mwps{$a} } keys %mwps;
- $best_bid{$wrk} = $sorted[0];
- @sorted = sort { $b <=> $a } values %mwps;
- $range = 1 - $sorted[-1] / $sorted[0];
- $best_bal{$wrk} = $sorted[0];
-
- next if $multi_mode and not $w_direct;
-
- say " Best balancer is '$best_bid{$wrk}' (range=$range).";
-
-
- $results{$wrk} = \%mwps;
-
- add_points(\%wps, \%scores, \%wscores);
- add_points(\%mwps, \%mscores, \%mwscores);
- add_points(\%cwps, \%cscores, \%cwscores);
-}
-
-sub dump_scoreboard
-{
- my ($n, $h) = @_;
- my ($i, $str, $balancer);
- my ($max, $range);
- my @sorted;
-
- @sorted = sort { $b <=> $a } values %{$h};
- $max = $sorted[0];
- $range = 1 - $sorted[-1] / $max;
- $str = "$n rank (range=$range):";
- say "\n$str";
- say '=' x length($str);
- $i = 1;
- foreach my $w (sort { $h->{$b} <=> $h->{$a} } keys %{$h}) {
- my $score;
-
- $balancer = $w if $i == 1;
- $score = $h->{$w} / $max;
-
- say " $i: '$w' ($score)";
-
- $i = $i + 1;
- }
-
- return $balancer;
-}
-
-dump_scoreboard($multi_mode ? 'Throughput' : 'Total wps', \%scores);
-dump_scoreboard('Total weighted wps', \%wscores) unless $multi_mode;
-dump_scoreboard($multi_mode ? 'Fairness' : 'Per client wps', \%cscores);
-dump_scoreboard('Per client weighted wps', \%cwscores) unless $multi_mode;
-$balancer = dump_scoreboard($multi_mode ? 'Combined' : 'Combined wps', \%mscores);
-$balancer = dump_scoreboard('Combined weighted wps', \%mwscores) unless $multi_mode;
-
-VERIFY:
-
-my %problem_wrk;
-
-die unless defined $balancer;
-
-say "\nBalancer is '$balancer'.";
-say "Idleness tolerance is $idle_tolerance_pct%.";
-
-if ($multi_mode) {
- $w_direct = '-w ' . join ' -w ', map("$wrk_root/$_", @workloads);
- @workloads = ($w_direct);
-}
-
-foreach my $wrk (@workloads) {
- my @args = ( "-n $nop" );
- my ($r, $error, $c, $wps, $swps);
- my $saturated = 0;
- my $result = 'Pass';
- my $vcs2 = $gt2 ? '1:0' : '2:1';
- my %problem;
- my $engines;
-
- next if not defined $w_direct and not can_balance_workload($wrk);
-
- push @args, $balancer unless $balancer eq '<none>';
-
- if (scalar(keys %results)) {
- $r = $results{$wrk}->{$balancer} / $best_bal{$wrk} * 100.0;
- } else {
- $r = '---';
- }
- say " \nProfiling '$wrk' ($r% of best)...";
-
- ($r, $error) = calibrate_workload($wrk);
- say " ${client_target_s}s is $r workloads. (error=$error)";
-
- ($c, $wps, $swps) = find_saturation_point($wrk, $r, $verbose, @args);
- say " Saturation at $c clients ($wps workloads/s).";
- push @args, "-c $c";
-
- $engines = trace_workload($wrk, $balancer, $r, $c);
-
- foreach my $key (keys %{$engines}) {
- next if $key eq 'gpu';
- $saturated = $saturated + 1
- if $engines->{$key} < $idle_tolerance_pct;
- }
-
- if ($saturated == 0) {
- # Not a single saturated engine
- $result = 'FAIL';
- } elsif (not exists $engines->{'2:0'} or not exists $engines->{$vcs2}) {
- # VCS1 and VCS2 not present in a balancing workload
- $result = 'FAIL';
- } elsif ($saturated == 1 and
- ($engines->{'2:0'} < $idle_tolerance_pct or
- $engines->{$vcs2} < $idle_tolerance_pct)) {
- # Only one VCS saturated
- $result = 'WARN';
- }
-
- $result = 'WARN' if $engines->{'gpu'} > $idle_tolerance_pct;
-
- if ($result ne 'Pass') {
- $problem{'c'} = $c;
- $problem{'r'} = $r;
- $problem{'stats'} = $engines;
- $problem_wrk{$wrk} = \%problem;
- }
-
- print " $result [";
- print map " $_: $engines->{$_}%,", sort keys %{$engines};
- say " ]";
-}
-
-say "\nProblematic workloads were:" if scalar(keys %problem_wrk) > 0;
-foreach my $wrk (sort keys %problem_wrk) {
- my $problem = $problem_wrk{$wrk};
-
- print " $wrk -c $problem->{'c'} -r $problem->{'r'} [";
- print map " $_: $problem->{'stats'}->{$_}%,",
- sort keys %{$problem->{'stats'}};
- say " ]";
-}