diff --git a/dawn/src/dawn/IIR/DependencyGraph.h b/dawn/src/dawn/IIR/DependencyGraph.h index 633645bc9..b814b417b 100644 --- a/dawn/src/dawn/IIR/DependencyGraph.h +++ b/dawn/src/dawn/IIR/DependencyGraph.h @@ -68,7 +68,9 @@ class DependencyGraph { }; protected: + // map of Value (i.e. normally accessID to Vertex object std::unordered_map vertices_; + // adjacencyList for each vertex where the position within the vector is the vertexID std::vector adjacencyList_; public: @@ -96,8 +98,8 @@ class DependencyGraph { DependencyGraph() = default; /// @brief Insert a new node - Vertex& insertNode(int ID) { - auto [iter, inserted] = vertices_.emplace(ID, Vertex{adjacencyList_.size(), ID}); + Vertex& insertNode(int Value) { + auto [iter, inserted] = vertices_.emplace(Value, Vertex{adjacencyList_.size(), Value}); if(inserted) adjacencyList_.push_back(EdgeList()); return iter->second; diff --git a/dawn/src/dawn/IIR/DependencyGraphAccesses.cpp b/dawn/src/dawn/IIR/DependencyGraphAccesses.cpp index cb4445a5c..f418c7d53 100644 --- a/dawn/src/dawn/IIR/DependencyGraphAccesses.cpp +++ b/dawn/src/dawn/IIR/DependencyGraphAccesses.cpp @@ -245,6 +245,32 @@ bool DependencyGraphAccesses::isDAG() const { return true; } +bool DependencyGraphAccesses::hasZeroOutdegreeNodes() const { + auto partitions = partitionInSubGraphs(); + std::vector vertices; + + for(std::set& partition : partitions) { + getOutputVertexIDsImpl( + *this, partition, [](std::size_t VertexID) { return VertexID; }, vertices); + if(vertices.empty()) + return false; + } + return true; +} + +bool DependencyGraphAccesses::hasZeroIndegreeNodes() const { + auto partitions = partitionInSubGraphs(); + std::vector vertices; + + for(std::set& partition : partitions) { + getInputVertexIDsImpl( + *this, partition, [](std::size_t VertexID) { return VertexID; }, vertices); + if(vertices.empty()) + return false; + } + return true; +} + std::vector DependencyGraphAccesses::getOutputVertexIDs() const { std::vector outputVertexIDs; getOutputVertexIDsImpl( diff --git a/dawn/src/dawn/IIR/DependencyGraphAccesses.h b/dawn/src/dawn/IIR/DependencyGraphAccesses.h index fc0c8cc7b..08157491d 100644 --- a/dawn/src/dawn/IIR/DependencyGraphAccesses.h +++ b/dawn/src/dawn/IIR/DependencyGraphAccesses.h @@ -127,6 +127,11 @@ class DependencyGraphAccesses /// In our context, a DAG is defined as having a non-empty set of input as well as output nodes. bool isDAG() const; + /// @brief true if graph has nodes with indegree=0 + bool hasZeroIndegreeNodes() const; + /// @brief true if graph has nodes with outdegree=0 + bool hasZeroOutdegreeNodes() const; + /// @brief Get the VertexIDs of the pure `output` vertices /// /// Output vertices are vertices which do not have incoming edges from other vertices. diff --git a/dawn/src/dawn/Optimizer/PassFieldVersioning.cpp b/dawn/src/dawn/Optimizer/PassFieldVersioning.cpp index 58deaaf70..c1ff71ce3 100644 --- a/dawn/src/dawn/Optimizer/PassFieldVersioning.cpp +++ b/dawn/src/dawn/Optimizer/PassFieldVersioning.cpp @@ -138,6 +138,7 @@ bool PassFieldVersioning::run( newGraph = oldGraph; newGraph.insertStatement(stmt); } + doMethod.update(iir::NodeUpdateType::level); } stage.update(iir::NodeUpdateType::level); @@ -211,22 +212,6 @@ PassFieldVersioning::RCKind PassFieldVersioning::fixRaceCondition( } } - // If we only have non-stencil SCCs and there are no input and output fields (i.e we don't have a - // DAG) we have to break (by renaming) one of the SCCs to get a DAG. For example: - // - // field_a = field_b; - // field_b = field_a; - // - // needs to be renamed to - // - // field_a = field_b_0; - // field_b = field_a; - // - // ... and then field_b_0 must be initialized from field_b. - if(stencilSCCs->empty() && !SCCs->empty() && !graph.isDAG()) { - stencilSCCs->emplace_back(std::move(SCCs->front())); - } - if(stencilSCCs->empty()) return RCKind::Nothing; diff --git a/dawn/src/dawn/Optimizer/ReadBeforeWriteConflict.cpp b/dawn/src/dawn/Optimizer/ReadBeforeWriteConflict.cpp index c5916bc38..d5072af6b 100644 --- a/dawn/src/dawn/Optimizer/ReadBeforeWriteConflict.cpp +++ b/dawn/src/dawn/Optimizer/ReadBeforeWriteConflict.cpp @@ -42,6 +42,10 @@ class ReadBeforeWriteConflictDetector { ReadBeforeWriteConflict check() const { std::vector nodesToVisit = graph_.getOutputVertexIDs(); + // if the graph does not have nodes with outdegree=0, there is no seed to start the algorithm + // in this case, there is at least one SCC, which means we can start from any node of the graph + if(nodesToVisit.empty() ) nodesToVisit.push_back(0); + DAWN_ASSERT_MSG(!nodesToVisit.empty(), "invalid graph (probably contains cycles!)"); ReadBeforeWriteConflict conflict; @@ -77,6 +81,9 @@ class ReadBeforeWriteConflictDetector { else visitedNodes.insert(curNode); + DAWN_ASSERT_MSG((adjacencyList.size() > curNode), "out of bounds access to adjacency list of graph"); + + // Follow edges of the current node if(!adjacencyList[curNode].empty()) { for(const auto& edge : adjacencyList[curNode]) { diff --git a/dawn/test/integration-test/dawn4py-tests/data/generate_versioned_field_ref.cpp b/dawn/test/integration-test/dawn4py-tests/data/generate_versioned_field_ref.cpp index f6d395776..b8283423e 100644 --- a/dawn/test/integration-test/dawn4py-tests/data/generate_versioned_field_ref.cpp +++ b/dawn/test/integration-test/dawn4py-tests/data/generate_versioned_field_ref.cpp @@ -21,11 +21,10 @@ class generate_versioned_field { ::dawn::edge_field_t& m_c; ::dawn::edge_field_t& m_d; ::dawn::edge_field_t& m_e; - ::dawn::edge_field_t& m_c_0; ::dawn::unstructured_domain m_unstructured_domain ; public: - stencil_37(::dawn::mesh_t const &mesh, int k_size, ::dawn::edge_field_t&a, ::dawn::edge_field_t&b, ::dawn::edge_field_t&c, ::dawn::edge_field_t&d, ::dawn::edge_field_t&e, ::dawn::edge_field_t&c_0) : m_mesh(mesh), m_k_size(k_size), m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_c_0(c_0){} + stencil_37(::dawn::mesh_t const &mesh, int k_size, ::dawn::edge_field_t&a, ::dawn::edge_field_t&b, ::dawn::edge_field_t&c, ::dawn::edge_field_t&d, ::dawn::edge_field_t&e) : m_mesh(mesh), m_k_size(k_size), m_a(a), m_b(b), m_c(c), m_d(d), m_e(e){} ~stencil_37() { } @@ -37,18 +36,14 @@ class generate_versioned_field { static constexpr ::dawn::driver::unstructured_extent c_extent = {false, 0,0}; static constexpr ::dawn::driver::unstructured_extent d_extent = {false, 0,0}; static constexpr ::dawn::driver::unstructured_extent e_extent = {false, 0,0}; - static constexpr ::dawn::driver::unstructured_extent c_0_extent = {false, 0,0}; void run() { using ::dawn::deref; { for(int k = 0+0; k <= ( m_k_size == 0 ? 0 : (m_k_size - 1)) + 0+0; ++k) { for(auto const& loc : getEdges(LibTag{}, m_mesh)) { -m_c_0(deref(LibTag{}, loc), (k + 0)) = m_c(deref(LibTag{}, loc), (k + 0)); - } }}{ - for(int k = 0+0; k <= ( m_k_size == 0 ? 0 : (m_k_size - 1)) + 0+0; ++k) { - for(auto const& loc : getEdges(LibTag{}, m_mesh)) { -m_a(deref(LibTag{}, loc), (k + 0)) = ((m_b(deref(LibTag{}, loc), (k + 0)) / m_c_0(deref(LibTag{}, loc), (k + 0))) + (::dawn::float_type) 5); +m_a(deref(LibTag{}, loc), (k + 0)) = ((m_b(deref(LibTag{}, loc), (k + 0)) / m_c(deref(LibTag{}, loc), (k + 0))) + (::dawn::float_type) 5); + } for(auto const& loc : getEdges(LibTag{}, m_mesh)) { if(m_d(deref(LibTag{}, loc), (k + 0))) { m_a(deref(LibTag{}, loc), (k + 0)) = m_b(deref(LibTag{}, loc), (k + 0)); @@ -70,13 +65,12 @@ else generate_versioned_field(const generate_versioned_field&) = delete; // Members - ::dawn::edge_field_t m_c_0; void set_splitter_index(::dawn::LocationType loc, ::dawn::UnstructuredIterationSpace space, int offset, int index) { m_stencil_37.m_unstructured_domain.set_splitter_index({loc, space, offset}, index); } - generate_versioned_field(const ::dawn::mesh_t &mesh, int k_size, ::dawn::edge_field_t& a, ::dawn::edge_field_t& b, ::dawn::edge_field_t& c, ::dawn::edge_field_t& d, ::dawn::edge_field_t& e) : m_stencil_37(mesh, k_size,a,b,c,d,e,m_c_0), m_c_0(allocateFieldLike(LibTag{}, c)){} + generate_versioned_field(const ::dawn::mesh_t &mesh, int k_size, ::dawn::edge_field_t& a, ::dawn::edge_field_t& b, ::dawn::edge_field_t& c, ::dawn::edge_field_t& d, ::dawn::edge_field_t& e) : m_stencil_37(mesh, k_size,a,b,c,d,e){} void run() { m_stencil_37.run();