Skip to content
This repository was archived by the owner on Apr 28, 2023. It is now read-only.

Commit 3d54f2d

Browse files
author
Sven Verdoolaege
committed
MappedScop::detectReductions: order away statements that depend on updates
Commit ceef5c3 (MappedScop::detectReductions: use dependences to check validity of ordering, Fri May 25 12:43:39 2018 +0200) extended the scope of MappedScop::detectReductions by also considering statements other than explicitly marked reduction initialization statements for ordering in front of the reduction update statements. Some statements that are originally coscheduled with the update statements may, however, depend on those update statements and can therefore not be ordered before the update statements. Try and order them after the update statements. Closes #454
1 parent ee5671e commit 3d54f2d

File tree

4 files changed

+58
-16
lines changed

4 files changed

+58
-16
lines changed

tc/core/polyhedral/cuda/mapped_scop.cc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@ void fixThreadsBelow(
190190

191191
/*
192192
* Try and order the other statements in "domain" (if any)
193-
* before the "updates" statements, returning true is the operation succeeds.
193+
* away from the "updates" statements, returning true is the operation succeeds.
194194
* In particular, only do this if it doesn't violate any dependences.
195-
* TODO (#454): order statements before or after the reduction based on
196-
* dependences.
195+
* Anything that depends on an update statement is ordered after
196+
* the update statements. Anything else is ordered before.
197197
*/
198198
bool separatedOut(
199199
Scop& scop,
@@ -205,10 +205,19 @@ bool separatedOut(
205205
return true;
206206
}
207207
auto dependences = scop.activeDependences(tree);
208-
if (!canOrderBefore(scop.scheduleRoot(), tree, other, dependences)) {
208+
auto after =
209+
dependences.intersect_domain(updates).intersect_range(other).range();
210+
auto before = other.subtract(after);
211+
if (!canOrderBefore(scop.scheduleRoot(), tree, before, dependences) ||
212+
!canOrderAfter(scop.scheduleRoot(), tree, after, dependences)) {
209213
return false;
210214
}
211-
orderBefore(scop.scheduleRoot(), tree, other);
215+
if (!before.is_empty()) {
216+
orderBefore(scop.scheduleRoot(), tree, before);
217+
}
218+
if (!after.is_empty()) {
219+
orderAfter(scop.scheduleRoot(), tree, after);
220+
}
212221
return true;
213222
}
214223

tc/core/polyhedral/schedule_transforms.cc

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -729,25 +729,49 @@ ScheduleTreeUPtr gistedFilter(isl::union_set filter, ScheduleTreeUPtr child) {
729729
return ScheduleTree::makeFilter(filter, std::move(child));
730730
}
731731

732+
/*
733+
* Given a partition of the (active) domain elements into "first" and "second",
734+
* is it possible to order the "first" elements before the "second"
735+
* without violating any of the (active) "dependences"?
736+
*/
737+
bool canOrder(
738+
isl::union_set first,
739+
isl::union_set second,
740+
isl::union_map dependences) {
741+
if (first.is_empty() || second.is_empty()) {
742+
return true;
743+
}
744+
// Create an ordering schedule function first -> 0; second -> 1.
745+
auto ctx = dependences.get_ctx();
746+
auto space = isl::space(ctx, 0).unnamed_set_from_params(1);
747+
auto zero = isl::multi_val::zero(space);
748+
auto one = zero.set_val(0, isl::val::one(ctx));
749+
auto order = isl::multi_union_pw_aff(first, zero);
750+
order = order.union_add(isl::multi_union_pw_aff(second, one));
751+
752+
// Check that this ordering preserves all dependences.
753+
auto preserved = dependences.lex_lt_at(order).unite(dependences.eq_at(order));
754+
return dependences.is_subset(preserved);
755+
}
756+
732757
} // namespace
733758

734759
bool canOrderBefore(
735760
ScheduleTree* root,
736761
ScheduleTree* tree,
737762
isl::union_set filter,
738763
isl::union_map dependences) {
739-
// Create an ordering schedule function filter -> 0; other -> 1.
740764
auto other = activeDomainPoints(root, tree).subtract(filter);
741-
auto ctx = root->ctx_;
742-
auto space = isl::space(ctx, 0).unnamed_set_from_params(1);
743-
auto zero = isl::multi_val::zero(space);
744-
auto one = zero.set_val(0, isl::val::one(ctx));
745-
auto order = isl::multi_union_pw_aff(filter, zero);
746-
order = order.union_add(isl::multi_union_pw_aff(other, one));
765+
return canOrder(filter, other, dependences);
766+
}
747767

748-
// Check that this ordering preserves all dependences.
749-
auto preserved = dependences.lex_lt_at(order).unite(dependences.eq_at(order));
750-
return dependences.is_subset(preserved);
768+
bool canOrderAfter(
769+
ScheduleTree* root,
770+
ScheduleTree* tree,
771+
isl::union_set filter,
772+
isl::union_map dependences) {
773+
auto other = activeDomainPoints(root, tree).subtract(filter);
774+
return canOrder(other, filter, dependences);
751775
}
752776

753777
void orderBefore(

tc/core/polyhedral/schedule_transforms.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ bool canOrderBefore(
241241
detail::ScheduleTree* tree,
242242
isl::union_set filter,
243243
isl::union_map dependences);
244+
// Is it possible to order the elements in the given filter
245+
// after the other active elements without violating
246+
// any of the given dependences?
247+
bool canOrderAfter(
248+
detail::ScheduleTree* root,
249+
detail::ScheduleTree* tree,
250+
isl::union_set filter,
251+
isl::union_map dependences);
244252

245253
// Insert a sequence to ensure that the active domain elements
246254
// in the given filter are executed before the other active domain elements.

test/test_cuda_mapper.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,8 @@ struct ReductionTest : public PolyhedralMapperTest {
867867
.outerScheduleFusionStrategy(tc::FusionStrategy::Preserve3Coincident)
868868
.outerScheduleAllowSkewing(false)
869869
.outerSchedulePositiveOrthant(true)
870-
.intraTileScheduleFusionStrategy(tc::FusionStrategy::Min)
870+
.intraTileScheduleFusionStrategy(
871+
tc::FusionStrategy::Preserve3Coincident)
871872
.intraTileScheduleAllowSkewing(false)
872873
.intraTileSchedulePositiveOrthant(true)
873874
.fixParametersBeforeScheduling(false)

0 commit comments

Comments
 (0)