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

Commit 3ed7f4a

Browse files
authored
Merge pull request #477 from facebookresearch/pr/extent
outputRanges: use isl::map::get_range_simple_fixed_box_hull
2 parents f86ba5b + a92d1fb commit 3ed7f4a

File tree

4 files changed

+47
-119
lines changed

4 files changed

+47
-119
lines changed

tc/core/polyhedral/memory_promotion.cc

Lines changed: 22 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -31,71 +31,12 @@ namespace polyhedral {
3131
using detail::ScheduleTree;
3232

3333
namespace {
34-
std::pair<isl::val, isl::aff> outputRange(
35-
isl::basic_set wrappedAccess,
36-
isl::constraint cstr) {
37-
auto emptyRange =
38-
std::make_pair(isl::val::nan(wrappedAccess.get_ctx()), isl::aff());
39-
int pos = cstr.dim(isl::dim_type::set) - 1;
40-
if (!cstr.is_lower_bound(isl::dim_type::set, pos)) {
41-
return emptyRange;
42-
}
43-
if (cstr.involves_dims(isl::dim_type::div, 0, cstr.dim(isl::dim_type::div))) {
44-
return emptyRange;
45-
}
46-
47-
auto lowerBound = cstr.get_bound(isl::dim_type::set, pos).ceil();
48-
auto aff = lowerBound.neg().add_coefficient_si(isl::dim_type::in, pos, 1);
49-
lowerBound = lowerBound.drop_dims(isl::dim_type::in, pos, 1);
50-
51-
auto range = wrappedAccess.max_val(aff);
52-
if (range.is_int()) {
53-
return std::make_pair(range + 1, lowerBound);
54-
}
55-
return emptyRange;
56-
}
57-
58-
std::pair<isl::val, isl::aff> outputRangeSingle(isl::map access) {
59-
CHECK_EQ(access.dim(isl::dim_type::out), 1u)
60-
<< "expected 1-dim output, call outputRanges instead";
61-
access = access.detect_equalities();
62-
auto wrappedAccess = access.wrap().flatten().compute_divs().simple_hull();
34+
ScopedFootprint outputRanges(isl::map access) {
35+
ScopedFootprint footprint;
6336

6437
// TODO: also compute strides
6538

66-
isl::val minRange;
67-
isl::aff lowerBoundWithMinRange;
68-
for (auto cstr : wrappedAccess.get_constraint_list()) {
69-
auto range = outputRange(wrappedAccess, cstr);
70-
if (range.first.is_nan()) {
71-
continue;
72-
}
73-
if (minRange.is_null() || range.first < minRange) {
74-
minRange = range.first;
75-
lowerBoundWithMinRange = range.second;
76-
}
77-
}
78-
if (minRange.is_null()) {
79-
return std::make_pair(
80-
isl::val::nan(access.get_ctx()), lowerBoundWithMinRange);
81-
}
82-
83-
return std::make_pair(minRange, lowerBoundWithMinRange);
84-
}
85-
86-
ScopedFootprint outputRanges(isl::map access) {
87-
int nSubscripts = access.dim(isl::dim_type::out);
88-
ScopedFootprint footprint;
89-
for (int i = 0; i < nSubscripts; ++i) {
90-
auto singleDim =
91-
access.project_out(isl::dim_type::out, 0, i)
92-
.project_out(isl::dim_type::out, 1, nSubscripts - i - 1);
93-
auto range = outputRangeSingle(singleDim);
94-
if (range.first.is_nan()) {
95-
return {};
96-
}
97-
footprint.emplace_back(range.second, range.first);
98-
}
39+
footprint.box = access.get_range_simple_fixed_box_hull();
9940
return footprint;
10041
}
10142

@@ -117,15 +58,16 @@ std::unique_ptr<TensorReferenceGroup> TensorReferenceGroup::makeSingleton(
11758
auto ref = std::unique_ptr<TensorReference>(new TensorReference);
11859
auto refId = scopedAccess.get_space().domain().unwrap().get_tuple_id(
11960
isl::dim_type::out);
61+
scopedAccess = scopedAccess.domain_factor_domain();
12062
ref->originalAccess = originalAccess.domain_factor_domain();
121-
ref->scopedAccess = scopedAccess.domain_factor_domain();
63+
ref->scopedAccess = scopedAccess;
12264
ref->type = type;
12365
ref->refId = refId;
12466
auto group = std::unique_ptr<TensorReferenceGroup>(new TensorReferenceGroup);
12567
group->references.push_back(std::move(ref));
12668
group->approximation = outputRanges(scopedAccess);
12769

128-
if (group->approximation.size() != scopedAccess.dim(isl::dim_type::out)) {
70+
if (!group->approximation.box.is_valid()) {
12971
std::stringstream ss;
13072
ss << "could not compute rectangular overapproximation of: "
13173
<< scopedAccess;
@@ -136,32 +78,25 @@ std::unique_ptr<TensorReferenceGroup> TensorReferenceGroup::makeSingleton(
13678
}
13779

13880
isl::set ScopedFootprint::footprint(isl::set domain) const {
139-
auto space = add_range(domain.get_space(), size());
81+
auto space = box.get_space();
14082
auto accessed = isl::map::universe(space).intersect_domain(domain);
14183
auto lspace = isl::local_space(accessed.get_space().range());
14284

143-
for (size_t i = 0; i < size(); ++i) {
144-
auto dim = at(i);
85+
for (size_t i = 0; i < dim(); ++i) {
86+
auto dimLowerBound = lowerBound(i);
14587
auto rhs = isl::aff(lspace, isl::dim_type::set, i);
146-
isl::map partial = (isl::aff_map(dim.lowerBound) <= rhs) &
147-
(isl::aff_map(dim.lowerBound + dim.size) > rhs);
88+
isl::map partial = (isl::aff_map(dimLowerBound) <= rhs) &
89+
(isl::aff_map(dimLowerBound + size(i)) > rhs);
14890
accessed = accessed & partial;
14991
}
15092
return accessed.range();
15193
}
15294

15395
isl::multi_aff ScopedFootprint::lowerBounds() const {
154-
if (size() == 0) {
96+
if (dim() == 0) {
15597
throw promotion::PromotionNYI("promotion for scalars");
15698
}
157-
auto space = add_range(at(0).lowerBound.get_space().domain(), size());
158-
auto ma = isl::multi_aff::zero(space);
159-
160-
int i = 0;
161-
for (const auto& a : *this) {
162-
ma = ma.set_aff(i++, a.lowerBound);
163-
}
164-
return ma;
99+
return box.get_offset();
165100
}
166101

167102
bool TensorReferenceGroup::isReadOnly() const {
@@ -173,28 +108,28 @@ bool TensorReferenceGroup::isReadOnly() const {
173108
}
174109

175110
isl::set TensorReferenceGroup::promotedFootprint() const {
176-
auto space =
177-
scopedAccesses().get_space().range().reset_tuple_id(isl::dim_type::set);
178-
auto sizes = approximationSizes();
179-
if (sizes.size() != space.dim(isl::dim_type::set)) {
111+
auto space = scopedAccesses().get_space().range();
112+
auto sizes = approximation.box.get_size();
113+
if (!sizes.get_space().has_equal_tuples(space)) {
180114
throw promotion::GroupingError("unexpected dimensionality mismatch");
181115
}
182116

183117
isl::set footprint = isl::set::universe(space);
184118
auto lspace = isl::local_space(space);
185119
for (size_t i = 0, e = sizes.size(); i < e; ++i) {
186120
auto aff = isl::aff(lspace, isl::dim_type::out, i);
121+
auto size = sizes.get_val(i);
187122
footprint =
188-
footprint & (isl::aff_set(aff) >= 0) & (isl::aff_set(aff) < sizes[i]);
123+
footprint & (isl::aff_set(aff) >= 0) & (isl::aff_set(aff) < size);
189124
}
190125
return footprint;
191126
}
192127

193128
std::vector<size_t> TensorReferenceGroup::approximationSizes() const {
194129
std::vector<size_t> result;
195-
result.reserve(approximation.size());
196-
for (const auto& dim : approximation) {
197-
result.push_back(dim.size.get_num_si());
130+
result.reserve(approximation.dim());
131+
for (const auto& size : approximation.box.get_size().get_val_list()) {
132+
result.push_back(size.get_num_si());
198133
}
199134
return result;
200135
}
@@ -381,9 +316,7 @@ isl::multi_aff TensorReferenceGroup::promotion() const {
381316
// lower bounds space is S -> P; which we transform into [S -> O] -> P
382317
auto lowerBounds = approximation.lowerBounds().pullback(
383318
isl::multi_aff::domain_map(accessSpace));
384-
auto promotion = isl::multi_aff::range_map(accessSpace)
385-
.reset_tuple_id(isl::dim_type::out) -
386-
lowerBounds;
319+
auto promotion = isl::multi_aff::range_map(accessSpace) - lowerBounds;
387320
return promotion;
388321
}
389322

tc/core/polyhedral/memory_promotion.h

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,25 @@ namespace polyhedral {
3030

3131
enum class AccessType : short { Read, Write };
3232

33-
// A single dimension of the ScopedFootprint.
34-
// The scope is defined by a specific position in a schedule tree (const
35-
// ScheduleTree*), the user is responsible for maintaining the correspondance
36-
// between schedule tree positions and footprints.
37-
// Overapproximates one dimension by its lower bound, affine function of
33+
// Rectangular overapproximation of a tensor elements accessed through a single
34+
// reference.
35+
// Each dimension is overapproximated by a lower bound, an affine function of
3836
// parameters and schedule dimensions visible around the scope, and by a
3937
// constant size.
40-
struct ScopedFootprintDim {
41-
public:
42-
ScopedFootprintDim(isl::aff lb, isl::val s) : lowerBound(lb), size(s) {}
43-
44-
public:
45-
isl::aff lowerBound;
46-
isl::val size;
47-
};
48-
49-
// Rectangular overapproximation of a tensor elements accessed through a single
50-
// reference. Each dimension is described independently.
5138
// The scope is defined by a specific position in a schedule tree (const
5239
// ScheduleTree*), the user is responsible for maintaining the correspondance
5340
// between schedule tree positions and footprints.
54-
struct ScopedFootprint : std::vector<ScopedFootprintDim> {
41+
struct ScopedFootprint {
42+
size_t dim() const {
43+
return box.get_size().size();
44+
}
45+
isl::val size(size_t pos) const {
46+
return box.get_size().get_val(pos);
47+
}
48+
isl::aff lowerBound(size_t pos) const {
49+
return box.get_offset().get_aff(pos);
50+
}
51+
isl::fixed_box box;
5552
isl::set footprint(isl::set domain) const;
5653
isl::multi_aff lowerBounds() const;
5754
};
@@ -159,13 +156,11 @@ class TensorReferenceGroup {
159156
};
160157

161158
inline std::ostream& operator<<(std::ostream& os, const ScopedFootprint& fp) {
162-
int i = 0;
163-
for (const auto& f : fp) {
164-
if (i++ == 0) {
165-
os << "{\n";
166-
}
167-
os << f.lowerBound << " of size " << f.size << "\n";
159+
if (!fp.box) {
160+
return os;
168161
}
162+
os << "{\n";
163+
os << fp.box.get_offset() << " of size " << fp.box.get_size() << "\n";
169164
os << "}";
170165
return os;
171166
}

test/test_cuda_mapper_memory_promotion.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -281,14 +281,14 @@ def fun(float(N, M) A, float(N, M) B) -> (C) {
281281
}
282282

283283
auto ref = oneGroup->references[0].get();
284-
ASSERT_EQ(oneGroup->approximation.size(), 2u)
284+
ASSERT_EQ(oneGroup->approximation.dim(), 2u)
285285
<< "Could not compute footprint for" << ref->scopedAccess;
286286

287287
EXPECT_EQ(
288-
oneGroup->approximation[0].size,
288+
oneGroup->approximation.size(0),
289289
isl::val(ctx, std::min(tile1, problemSize1)));
290290
EXPECT_EQ(
291-
oneGroup->approximation[1].size,
291+
oneGroup->approximation.size(1),
292292
isl::val(ctx, std::min(tile2, problemSize2)));
293293
auto footprint =
294294
oneGroup->approximateFootprint().intersect_params(blockZero);
@@ -346,12 +346,12 @@ def fun(float(N, M) A) -> (B, C) {
346346

347347
const auto& groupsB = groups.at(idB);
348348
ASSERT_EQ(groupsB.size(), 1u) << "expected B refereces to be grouped";
349-
ASSERT_EQ(groupsB[0]->approximation.size(), 2u) << "B should be a 2D array";
349+
ASSERT_EQ(groupsB[0]->approximation.dim(), 2u) << "B should be a 2D array";
350350
EXPECT_EQ(
351-
groupsB[0]->approximation[0].size,
351+
groupsB[0]->approximation.size(0),
352352
isl::val(ctx, std::min(tile1, problemSize1)));
353353
EXPECT_EQ(
354-
groupsB[0]->approximation[1].size,
354+
groupsB[0]->approximation.size(1),
355355
isl::val(ctx, std::min(tile2, problemSize2)));
356356

357357
auto t = scop.scheduleRoot()->child(childPos);

third-party/islpp

Submodule islpp updated from 32360f8 to 0cf707e

0 commit comments

Comments
 (0)