-
Notifications
You must be signed in to change notification settings - Fork 237
[rocroller] Build Basic-Block Dependence DAGs #4785
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
base: develop
Are you sure you want to change the base?
Changes from 19 commits
d5c6b3f
7782f17
5c3924f
38fe5be
4d30184
e21943f
0dd47e2
b6df996
36aeca0
f2b4cf1
9b0c590
13800bd
36a999e
6b9dbd0
d741c3a
d40e06f
4f55c99
910bb44
22a735e
91d79fa
383333d
78c9a9e
966c558
f872cdc
d3f184d
f38c6f0
6e6902d
e789bb6
76bebb8
76cea6b
ca52c33
35cdd49
7e9a01b
c1eaf26
c80ba10
76f2905
2542551
cbdb67a
955a4dd
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 |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // Copyright Advanced Micro Devices, Inc., or its affiliates. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <rocRoller/KernelGraph/ControlGraph/ControlGraph.hpp> | ||
|
|
||
| namespace rocRoller::KernelGraph::DataDependenceDAG | ||
| { | ||
| ControlGraph::ControlGraph ConstructDataDependenceDAG(KernelGraph const& graph); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Copyright Advanced Micro Devices, Inc., or its affiliates. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <rocRoller/KernelGraph/ControlGraph/ControlFlowRWTracer.hpp> | ||
|
|
||
| namespace rocRoller::KernelGraph::DataDependenceDAG::Detail | ||
| { | ||
| class DataDependenceDAGDetail | ||
| { | ||
| public: | ||
| DataDependenceDAGDetail(KernelGraph const& graph); | ||
|
|
||
| int getBodyParent(int control); | ||
| void addDependenceEdge(int sourceControl, int destControl); | ||
| void processReadWriteRecord(ControlFlowRWTracer::ReadWriteRecord const& record); | ||
| void constructDataDependenceDAG(); | ||
| ControlGraph::ControlGraph getDataDependenceDAG(); | ||
|
||
|
|
||
| private: | ||
| KernelGraph const& m_graph; | ||
| ControlGraph::ControlGraph m_dependenceDAG; | ||
| std::unordered_map<int, int> m_bodyParentCache; | ||
| std::map<int, int> m_latestWriteToCoord; | ||
| std::map<int, std::unordered_set<int>> m_latestReadsToCoord; | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,7 +32,7 @@ namespace rocRoller::KernelGraph | |
| * The sub-graph is created by adding the given nodes to a new control graph, and then | ||
| * adding edges between the nodes based on the order of the nodes in the original | ||
| * control graph. | ||
| * | ||
| * | ||
| * rv.compare(cacheMode, a, b) should always return the same result as the original | ||
| * control graph as long as a and b are both in `nodes`. | ||
| */ | ||
|
|
@@ -46,6 +46,15 @@ namespace rocRoller::KernelGraph | |
| * `graph.control`. | ||
| */ | ||
| void orderNodes(KernelGraph const& graph, std::vector<int>& nodes, auto const& comp); | ||
|
|
||
| /** | ||
| * Builds the data dependence graph for the given kernel graph. | ||
| * | ||
| * The dependences are represented at each basic block level i.e. between the | ||
|
||
| * nodes sharing the same immediate body-parent in `graph.control`. | ||
| * The flow, anti, and output data dependences between such nodes are included. | ||
| */ | ||
| ControlGraph::ControlGraph ConstructDataDependenceDAG(KernelGraph const& graph); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| // Copyright Advanced Micro Devices, Inc., or its affiliates. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #include <rocRoller/KernelGraph/ControlGraph/DataDependenceDAG.hpp> | ||
| #include <rocRoller/KernelGraph/ControlGraph/DataDependenceDAG_detail.hpp> | ||
| #include <rocRoller/KernelGraph/Utils.hpp> | ||
|
|
||
| namespace rocRoller::KernelGraph | ||
| { | ||
| namespace DataDependenceDAG | ||
| { | ||
| using ReadWrite = ControlFlowRWTracer::ReadWrite; | ||
|
|
||
| ControlGraph::ControlGraph ConstructDataDependenceDAG(KernelGraph const& graph) | ||
| { | ||
| using namespace Detail; | ||
|
|
||
| DataDependenceDAGDetail obj(graph); | ||
| obj.constructDataDependenceDAG(); | ||
| return obj.getDataDependenceDAG(); | ||
| } | ||
|
|
||
| namespace Detail | ||
| { | ||
| DataDependenceDAGDetail::DataDependenceDAGDetail(KernelGraph const& graph) | ||
|
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. If it makes sense, the constructor could call |
||
| : m_graph(graph) | ||
| { | ||
| } | ||
|
|
||
| ControlGraph::ControlGraph DataDependenceDAGDetail::getDataDependenceDAG() | ||
| { | ||
| return m_dependenceDAG; | ||
| } | ||
|
|
||
| void DataDependenceDAGDetail::constructDataDependenceDAG() | ||
| { | ||
| // Insert all control graph nodes into the data dependence DAG | ||
| for(auto node : m_graph.control.getNodes()) | ||
| { | ||
| m_dependenceDAG.setElement(node, m_graph.control.getElement(node)); | ||
| } | ||
|
|
||
| auto tracer = ControlFlowRWTracer(m_graph); | ||
| auto records = tracer.coordinatesReadWrite(); | ||
|
|
||
| // This assumes that the trace is ordered and records for the | ||
| // same control operation are consecutive. | ||
| std::unordered_set<int> seen; | ||
| for(auto iter = records.begin(); iter != records.end();) | ||
| { | ||
| auto currentControl = iter->control; | ||
|
|
||
| AssertFatal(seen.find(currentControl) == seen.end(), | ||
| "The records for the same control operation are not consecutive.", | ||
| ShowValue(currentControl)); | ||
|
|
||
| for(; iter != records.end() && iter->control == currentControl; ++iter) | ||
| { | ||
| processReadWriteRecord(*iter); | ||
| } | ||
|
|
||
| seen.insert(currentControl); | ||
| } | ||
| } | ||
|
|
||
| int DataDependenceDAGDetail::getBodyParent(int control) | ||
| { | ||
| if(auto iter = m_bodyParentCache.find(control); iter != m_bodyParentCache.end()) | ||
| return iter->second; | ||
|
|
||
| auto topSetCoordinate = getTopSetCoordinate(m_graph, control); | ||
| auto bodyParent = bodyParents(topSetCoordinate, m_graph).take(1).only(); | ||
| AssertFatal(bodyParent.has_value(), | ||
| "Control node has no body parent", | ||
| ShowValue(control), | ||
| ShowValue(topSetCoordinate)); | ||
|
|
||
| m_bodyParentCache.emplace(control, bodyParent.value()); | ||
| return bodyParent.value(); | ||
| } | ||
|
|
||
| void DataDependenceDAGDetail::addDependenceEdge(int sourceControl, int destControl) | ||
| { | ||
| AssertFatal( | ||
| sourceControl != destControl, ShowValue(sourceControl), ShowValue(destControl)); | ||
|
|
||
| auto sourceBodyParent = getBodyParent(sourceControl); | ||
| auto destBodyParent = getBodyParent(destControl); | ||
|
|
||
| if(sourceBodyParent != destBodyParent) | ||
| return; | ||
|
|
||
| if(!m_dependenceDAG.findEdge(sourceControl, destControl).has_value()) | ||
| { | ||
| m_dependenceDAG.addElement( | ||
| ControlGraph::Sequence(), {sourceControl}, {destControl}); | ||
| } | ||
| } | ||
|
|
||
| void DataDependenceDAGDetail::processReadWriteRecord( | ||
| ControlFlowRWTracer::ReadWriteRecord const& record) | ||
| { | ||
| AssertFatal(record.rw != ReadWrite::Count, | ||
| ShowValue(record.control), | ||
| ShowValue(record.coordinate), | ||
| ShowValue(record.rw)); | ||
|
|
||
| if(auto writeIter = m_latestWriteToCoord.find(record.coordinate); | ||
| writeIter != m_latestWriteToCoord.end()) | ||
| { | ||
| AssertFatal(writeIter->second != record.control, | ||
| ShowValue(writeIter->second), | ||
| ShowValue(record.control), | ||
| ShowValue(record.coordinate), | ||
| ShowValue(record.rw)); | ||
|
|
||
| // adds WW(output dep) and WR(flow dep) edges | ||
| addDependenceEdge(writeIter->second, record.control); | ||
pjots marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| if(record.rw == ReadWrite::WRITE || record.rw == ReadWrite::READWRITE) | ||
| { | ||
| for(auto const readControl : m_latestReadsToCoord[record.coordinate]) | ||
| { | ||
| if(readControl == record.control) | ||
| continue; | ||
|
|
||
| // adds RW(anti dep) edges | ||
| addDependenceEdge(readControl, record.control); | ||
| } | ||
|
|
||
| // Since the current control node writes into this coord, | ||
| // the latest reads info needs to be reset. | ||
| m_latestReadsToCoord[record.coordinate].clear(); | ||
| // update the latest write to coord | ||
| m_latestWriteToCoord[record.coordinate] = record.control; | ||
| } | ||
|
|
||
| if(record.rw == ReadWrite::READ || record.rw == ReadWrite::READWRITE) | ||
| { | ||
| m_latestReadsToCoord[record.coordinate].insert(record.control); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1123,7 +1123,8 @@ namespace rocRoller | |
| else | ||
| break; | ||
|
|
||
| AssertFatal(graph.mapper.get<CT::Unroll>(tag) > 0, | ||
| AssertFatal(graph.mapper.get<CT::Unroll>(tag) > 0 | ||
| || graph.mapper.get<CT::ForLoop>(tag) > 0, | ||
| "SetCoordinate needs Unroll dimension"); | ||
|
||
| } | ||
| return tag; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.