-
Notifications
You must be signed in to change notification settings - Fork 80
Almost-exact graph recognizes equivalence in the split-split pattern #5986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
474a060
334420d
bc4af4a
cfbb01e
675efe4
6c22d6f
842bbcb
ebad10a
e1d3cfc
f83a379
40a2cc6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| #include "device_lower/lower2device.h" | ||
| #include "device_lower/utils.h" | ||
| #include "disjoint_set.h" | ||
| #include "expr_simplifier.h" | ||
| #include "id_model/loop_promotion.h" | ||
| #include "id_model/to_string.h" | ||
| #include "id_model/transform_replay.h" | ||
|
|
@@ -481,6 +482,66 @@ std::vector<std::vector<Val*>> getTriviallyMappedIds(Expr* expr) { | |
| return mapped_ids; | ||
| } | ||
|
|
||
| // The following is a subpattern of | ||
| // https://github.com/NVIDIA/Fuser/blob/main/doc/reading/iterdomain.md#2-properties-of-iterdomain-transformations | ||
| // | ||
| // outer, _ = split(root) | ||
| // outermost_grand, _ = split(outer) | ||
| // outer', _ = split(root) | ||
| // | ||
| // If outermost_grand and outer' have the same extent, map them. | ||
| // The splits must be divisible for this mapping to be valid. | ||
| void mapDivisibleSplits(ValGraph& graph) { | ||
| auto is_divisible = [](Split* s) { | ||
| return simplifyExpr(s->isDivisible())->isTrue(); | ||
| }; | ||
|
|
||
| std::vector<std::pair<Val*, Val*>> ids_to_map; | ||
| for (const ValGroup& root : graph.disjointValSets().disjointSets()) { | ||
| const ExprGroups& uses_of_root = graph.getUses(root); | ||
| std::vector<ValGroup> outermost_grands; | ||
| for (const ExprGroup& use_of_root : uses_of_root) { | ||
| auto* split0 = dynamic_cast<Split*>(use_of_root->front()); | ||
| if (split0 == nullptr || !is_divisible(split0)) { | ||
| continue; | ||
| } | ||
| // Only follow the outer output of the first split; outer and inner | ||
| // must not be conflated. | ||
| const ValGroup& outer = graph.toGroup(split0->outer()); | ||
| for (const ExprGroup& use_of_outer : graph.getUses(outer)) { | ||
| auto* split1 = dynamic_cast<Split*>(use_of_outer->front()); | ||
| if (split1 == nullptr || !is_divisible(split1)) { | ||
| continue; | ||
| } | ||
| const ValGroup& outermost_grand = graph.toGroup(split1->outer()); | ||
| outermost_grands.push_back(outermost_grand); | ||
| } | ||
| } | ||
|
|
||
| for (const ValGroup& outermost_grand : outermost_grands) { | ||
| Val* extent_of_grand = | ||
| outermost_grand->front()->as<IterDomain>()->extent(); | ||
|
|
||
| for (const ExprGroup& use_of_root : uses_of_root) { | ||
| auto* split = dynamic_cast<Split*>(use_of_root->front()); | ||
| if (split == nullptr || !is_divisible(split)) { | ||
| continue; | ||
| } | ||
|
|
||
| const ValGroup& outer = graph.toGroup(split->outer()); | ||
| if (outer->front()->as<IterDomain>()->extent()->sameAs( | ||
| extent_of_grand)) { | ||
| ids_to_map.emplace_back(outermost_grand->front(), outer->front()); | ||
|
Comment on lines
+521
to
+534
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Second loop can self-map The second loop re-scans every use of In practice this case cannot occur when A guard comparing the two if (outer != outermost_grand &&
outer->front()->as<IterDomain>()->extent()->sameAs(extent_of_grand)) {
ids_to_map.emplace_back(outermost_grand->front(), outer->front());
} |
||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+521
to
+537
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate mapping entries possible When multiple split-split paths from the same root share the same |
||
| } | ||
|
|
||
| for (const auto& [id1, id2] : ids_to_map) { | ||
| graph.mapVals(id1, id2); | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| ValGraph& IdModel::buildAlmostExactGraph() { | ||
|
|
@@ -540,6 +601,8 @@ ValGraph& IdModel::buildAlmostExactGraph() { | |
| almost_exact_graph.mapVals(id1, id2); | ||
| } | ||
|
|
||
| mapDivisibleSplits(almost_exact_graph); | ||
|
|
||
| almost_exact_graph.validateConsistency(); | ||
|
|
||
| if (!allow_self_mapping_) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -269,8 +269,8 @@ std::string ValGraph::toString() const { | |
| ss << "IdGraph { \n"; | ||
| ss << "Disjoint Ids:\n" | ||
| << idGroupsString(*this, 1) << "\n\nDisjoint Expression groups:\n" | ||
| << exprGroupsString(*this, 1) << std::endl; | ||
| ss << " } IdGraph\n" << std::endl; | ||
| << exprGroupsString(*this, 1) << '\n'; | ||
| ss << " } IdGraph\n"; | ||
| return ss.str(); | ||
| } | ||
|
|
||
|
|
@@ -397,11 +397,12 @@ const ExprGroups& ValGraph::getDefinitions(const ValGroup& val_group) const { | |
|
|
||
| const ExprGroups& ValGraph::getUses(const ValGroup& val_group) const { | ||
| NVF_ERROR(val_group, "Nullptr not allowed"); | ||
|
|
||
| static const ExprGroups empty_expr_groups; | ||
| const auto it = unique_uses_.find(val_group); | ||
| NVF_ERROR( | ||
| it != unique_uses_.end(), | ||
| "Use group not found for ", | ||
| nvfuser::toString(val_group)); | ||
| if (it == unique_uses_.end()) { | ||
| return empty_expr_groups; | ||
| } | ||
| return it->second; | ||
| } | ||
|
Comment on lines
398
to
407
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Behavioral change silently relaxes a previous invariant The old implementation treated a missing Consider whether a comment, or a separate |
||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.