#pragma once #include #include "sycl_meta.hpp" namespace tf { // ---------------------------------------------------------------------------- // syclGraph class // ---------------------------------------------------------------------------- // class: syclGraph class syclGraph : public CustomGraphBase { friend class syclNode; friend class syclTask; friend class syclFlow; friend class Taskflow; friend class Executor; constexpr static int OFFLOADED = 0x01; constexpr static int TOPOLOGY_CHANGED = 0x02; public: syclGraph() = default; ~syclGraph() = default; syclGraph(const syclGraph&) = delete; syclGraph(syclGraph&&); syclGraph& operator = (const syclGraph&) = delete; syclGraph& operator = (syclGraph&&); template syclNode* emplace_back(ArgsT&&...); bool empty() const; void clear(); void dump(std::ostream&, const void*, const std::string&) const override final; private: int _state {0}; std::vector> _nodes; }; // ---------------------------------------------------------------------------- // syclNode definitions // ---------------------------------------------------------------------------- // class: syclNode class syclNode { friend class syclGraph; friend class syclTask; friend class syclFlow; friend class Taskflow; friend class Executor; struct Empty { }; struct CGH { std::function work; template CGH(F&& func) : work {std::forward(func)} {} }; using handle_t = std::variant< Empty, CGH >; public: // variant index constexpr static auto EMPTY = get_index_v; constexpr static auto COMMAND_GROUP_HANDLER = get_index_v; syclNode() = delete; template syclNode(syclGraph&, ArgsT&&...); private: syclGraph& _graph; std::string _name; int _level; sycl::event _event; handle_t _handle; SmallVector _successors; SmallVector _dependents; void _precede(syclNode*); }; // ---------------------------------------------------------------------------- // syclNode definitions // ---------------------------------------------------------------------------- // Constructor template syclNode::syclNode(syclGraph& g, ArgsT&&... args) : _graph {g}, _handle {std::forward(args)...} { } // Procedure: _precede inline void syclNode::_precede(syclNode* v) { _graph._state |= syclGraph::TOPOLOGY_CHANGED; _successors.push_back(v); v->_dependents.push_back(this); } // ---------------------------------------------------------------------------- // syclGraph definitions // ---------------------------------------------------------------------------- // Move constructor inline syclGraph::syclGraph(syclGraph&& g) : _nodes {std::move(g._nodes)} { assert(g._nodes.empty()); } // Move assignment inline syclGraph& syclGraph::operator = (syclGraph&& rhs) { // lhs _nodes = std::move(rhs._nodes); assert(rhs._nodes.empty()); return *this; } // Function: empty inline bool syclGraph::empty() const { return _nodes.empty(); } // Procedure: clear inline void syclGraph::clear() { _state = syclGraph::TOPOLOGY_CHANGED; _nodes.clear(); } // Function: emplace_back template syclNode* syclGraph::emplace_back(ArgsT&&... args) { _state |= syclGraph::TOPOLOGY_CHANGED; auto node = std::make_unique(std::forward(args)...); _nodes.emplace_back(std::move(node)); return _nodes.back().get(); // TODO: object pool //auto node = new syclNode(std::forward(args)...); //_nodes.push_back(node); //return node; } // Procedure: dump the graph to a DOT format inline void syclGraph::dump( std::ostream& os, const void* root, const std::string& root_name ) const { // recursive dump with stack std::stack> stack; stack.push(std::make_tuple(this, nullptr, 1)); int pl = 0; while(!stack.empty()) { auto [graph, parent, l] = stack.top(); stack.pop(); for(int i=0; i_name.empty()) os << 'p' << parent; else os << parent->_name; os << "\";\n" << "color=\"purple\"\n"; } for(auto& v : graph->_nodes) { os << 'p' << v.get() << "[label=\""; if(v->_name.empty()) { os << 'p' << v.get() << "\""; } else { os << v->_name << "\""; } os << "];\n"; for(const auto s : v->_successors) { os << 'p' << v.get() << " -> " << 'p' << s << ";\n"; } if(v->_successors.size() == 0) { if(parent == nullptr) { if(root) { os << 'p' << v.get() << " -> p" << root << ";\n"; } } else { os << 'p' << v.get() << " -> p" << parent << ";\n"; } } } // set the previous level pl = l; } for(int i=0; i