scheduler: try carrying only self-dependences in the Feautrier fallback
commitf0e0f1f47a4b17f750da687b783c021f603ce33e
authorSven Verdoolaege <skimo@kotnet.org>
Tue, 18 Apr 2017 14:48:25 +0000 (18 16:48 +0200)
committerSven Verdoolaege <sven.verdoolaege@gmail.com>
Wed, 7 Jun 2017 12:15:47 +0000 (7 14:15 +0200)
tree9b7fe8afea27359fe68c4a6e78fa110198bc9258
parent484bccbf981c326c91f57e234e7dd0b996d70c0d
scheduler: try carrying only self-dependences in the Feautrier fallback

A Feautrier style scheduler is used as a fallback for the Pluto-scheduler
when the latter fails to make progress.  This may happen, for example,
when the --schedule-outer-coincidence option is set and it proves
to be impossible to construct a band member satisfying the coincidence
constraints.  The fallback scheduler should then try to carry
as many validity (and coincidence) constraints as possible
in order to increase the chances that a subsequent nested call
to the Pluto-scheduler will produce a solution.

However, the Feautrier scheduler tends to carry a bit too many
dependences for the purpose for which it is (ab)used.
In particular, if it is possible to construct a valid schedule
that results in several strongly connected components
at the next level, then the Feautrier scheduler will
scale the schedule by the number of components and
assign each component a different offset in order to also carry
the edges between the components.
Such cases are already handled by split_scaled, but there
are similar cases where it is not the entire schedule
that is scaled by an integer, but rather a more complicated
transformation that has a similar effect.
In some cases, the Feautrier scheduler will also shift
some statements only to be able to carry one more dependence.
Such shifts are not only surprising to the user, they can
also result in a deterioration of the entire schedule.

One thing that most if not all of the bad side-effects
of the Feautrier scheduler have in common is that they
are introduced in order to be able to carry a dependence
between different nodes.
This commit therefore tries to first carry self-dependences only
(while the other dependences are only required to be respected).
This usually produces the same benefits of a Feautrier step
that also tries to carry the other dependences, but
without the unwanted side-effects.
If the Feautrier scheduler is unable to carry any of
the self-dependences, then a second attempt is performed
with all the dependences.

For example, for the PolyBench cholesky benchmark
with --schedule-outer-coincidence set, trying to carry all
dependences produces a schedule of the form

    { S_10[i] -> [(3i)]; S_5[i, j] -> [(1 + 3j)];
      S_3[i, j, k] -> [(2j + k)]; S_8[i, k] -> [(2i + k)] }

When only trying to carry self-dependences, the following
schedule is produced:

    { S_10[i] -> [(i)]; S_5[i, j] -> [(j)];
      S_3[i, j, k] -> [(k)]; S_8[i, k] -> [(k)] }

Note that if there are any self-dependences to carry,
then there will typically be no scaling in the schedule and
split_scaled is not needed.  However, it can still be useful
in cases where there are no self-dependences.

The rational solution of the LP problem constructed
by the Feautrier scheduler may still be non-integral,
even when only trying to carry self-dependences.
It is therefore still useful to continue looking
for an integral solution.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/schedule.h
isl_options.c
isl_options_private.h
isl_scheduler.c