diff mbox

[i-g-t,4/4] trace.pl: Fix request split mode

Message ID 20180423095238.29238-5-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tvrtko Ursulin April 23, 2018, 9:52 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Request split mode had several bugs, both in the original version and also
after the recent refactorings.

One big one was that it wasn't considering different submit ports as a
reason to split execution, and also that it was too time based instead of
looking at relevant timelines.

In this refactoring we address the former by using the engine timelines
introduced in the previous patch. Secondary port submissions are moved
to follow the preceding submission as a first step in the correction
process.

In the second step, we add context timelines and use then in a similar
fashion to separate start and end time of coalesced requests. For each
coalesced request we know its boundaries by looking at the engine
timeline (via global seqnos), and we know the previous request it should
only start after, by looking at the context timeline.

v2:
 * Remove some dead code.
 * Fix !port0 shifting logic.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: John Harrison <John.C.Harrison@intel.com>
---
 scripts/trace.pl | 121 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 95 insertions(+), 26 deletions(-)
diff mbox

Patch

diff --git a/scripts/trace.pl b/scripts/trace.pl
index b48f43225fc1..88aa667df2d4 100755
--- a/scripts/trace.pl
+++ b/scripts/trace.pl
@@ -601,41 +601,110 @@  sub sortStart {
 	return $val;
 }
 
-my @sorted_keys = sort sortStart keys %db;
-my $re_sort = 0;
+my $re_sort = 1;
+my @sorted_keys;
 
-die "Database changed size?!" unless scalar(@sorted_keys) == $key_count;
+sub maybe_sort_keys
+{
+	if ($re_sort) {
+		@sorted_keys = sort sortStart keys %db;
+		$re_sort = 0;
+		die "Database changed size?!" unless scalar(@sorted_keys) ==
+						     $key_count;
+	}
+}
 
-foreach my $key (@sorted_keys) {
-	my $ring = $db{$key}->{'ring'};
-	my $end = $db{$key}->{'end'};
+maybe_sort_keys();
+
+my %ctx_timelines;
+
+sub sortContext {
+	my $as = $db{$a}->{'seqno'};
+	my $bs = $db{$b}->{'seqno'};
+	my $val;
+
+	$val = $as <=> $bs;
+
+	die if $val == 0;
+
+	return $val;
+}
+
+sub get_ctx_timeline {
+	my ($ctx, $ring, $key) = @_;
+	my @timeline;
 
-	# correct duration of merged batches
-	if ($correct_durations and exists $db{$key}->{'no-end'}) {
+	return $ctx_timelines{$key} if exists $ctx_timelines{$key};
+
+	@timeline = grep { $db{$_}->{'ring'} == $ring and
+			   $db{$_}->{'ctx'} == $ctx } @sorted_keys;
+	# FIXME seqno restart
+	@timeline = sort sortContext @timeline;
+
+	$ctx_timelines{$key} = \@timeline;
+
+	return \@timeline;
+}
+
+# Split out merged batches if requested.
+if ($correct_durations) {
+	my @port1;
+	my @no_end;
+
+	# Shift !port0 requests start time to after the previous context on the
+	# same timeline has finished.
+	@port1 = grep { $db{$_}->{'port'} != 0 } @sorted_keys;
+	foreach my $key (@port1) {
+		my $timeline = get_engine_timeline($db{$key}->{'ring'});
+		my $i = List::Util::first { ${$timeline}[$_] eq $key } 0..$#{$timeline};
+		my $prev_key;
+		my $start;
+
+		while ($i > 0) {
+			my $prev;
+
+			$i = $i - 1;
+			$prev = ${$timeline}[$i];
+
+			next if exists $db{$prev}->{'no-end'};
+
+			$prev_key = $prev;
+			last;
+		}
+
+		$start = $db{$prev_key}->{'end'};
+		$db{$key}->{'start'} = $start;
+		die if $start > $db{$key}->{'end'};
+
+		$re_sort = 1;
+	}
+
+	maybe_sort_keys();
+
+	# Batch with no-end (no request_out) means it was submitted as part of
+	# colaesced context. This means it's start time should be set to the end
+	# time of a precedeing request on this timeline.
+	@no_end = grep { exists $db{$_}->{'no-end'} } @sorted_keys;
+	foreach my $key (@no_end) {
 		my $ctx = $db{$key}->{'ctx'};
-		my $seqno = $db{$key}->{'seqno'};
-		my $start = $db{$key}->{'start'};
-		my $next_key;
-		my $i = 1;
-
-		do {
-			$next_key = db_key($ring, $ctx, $seqno + $i);
-			$i++;
-		} until (exists $db{$next_key} or $i > $key_count);  # ugly stop hack
-
-		# 20us tolerance
-		if (exists $db{$next_key} and $db{$next_key}->{'start'} < $start + 20) {
-			my $notify = $db{$key}->{'notify'};
+		my $ring = $db{$key}->{'ring'};
+		my $tkey = $ctx . '/' . $ring;
+		my $timeline = get_ctx_timeline($ctx, $ring, $tkey);
+		my $i;
+
+		$i = List::Util::first { ${$timeline}[$_] eq $key } 0..$#{$timeline};
+
+		# Shift following request to start after the current one.
+		if ($i < $#{$timeline}) {
+			my $next_key = ${$timeline}[$i + 1];
+
+			$db{$next_key}->{'start'} = $db{$key}->{'notify'};
 			$re_sort = 1;
-			$db{$next_key}->{'start'} = $notify;
-			$db{$next_key}->{'start'} = $db{$next_key}->{'end'} if $db{$next_key}->{'start'} > $db{$next_key}->{'end'};
-			die if $db{$next_key}->{'start'} > $db{$next_key}->{'end'};
 		}
-		die if $start > $end;
 	}
 }
 
-@sorted_keys = sort sortStart keys %db if $re_sort;
+maybe_sort_keys();
 
 # GPU time accounting
 my (%running, %runnable, %queued, %batch_avg, %batch_total_avg, %batch_count);