forked from huawei/mindspore2022
245 lines
9.2 KiB
C++
245 lines
9.2 KiB
C++
/**
|
|
* Copyright 2019 Huawei Technologies Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef DATASET_ENGINE_EXECUTION_TREE_H_
|
|
#define DATASET_ENGINE_EXECUTION_TREE_H_
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <vector>
|
|
#include "dataset/engine/datasetops/dataset_op.h"
|
|
#include "dataset/util/status.h"
|
|
#include "mindspore/ccsrc/dataset/engine/perf/profiling.h"
|
|
|
|
namespace mindspore {
|
|
namespace dataset {
|
|
// Forward declares
|
|
class TaskGroup;
|
|
class DatasetOp;
|
|
class Monitor;
|
|
|
|
class ExecutionTree {
|
|
public:
|
|
// Prepare flags used during tree prepare phase
|
|
enum PrepareFlags {
|
|
kDePrepNone = 0,
|
|
kDePrepRepeat = 1 // Processing a repeat operation
|
|
};
|
|
|
|
// State flags for the lifecycle of the tree
|
|
enum TreeState {
|
|
kDeTStateInit = 0, // The freshly initialized state after construction
|
|
kDeTStateBuilding, // The tree is being built, nodes are being added
|
|
kDeTStatePrepare, // The tree has been assigned a root node and is pending prepare
|
|
kDeTStateReady, // The tree has been prepared and is ready to be launched
|
|
kDeTStateExecuting, // The tree has been launched and is executing
|
|
kDeTStateFinished // The tree has been drained, dataset iterator received EOF
|
|
};
|
|
|
|
class Iterator {
|
|
public:
|
|
// Constructor
|
|
// @param root The root node to start iterating from
|
|
explicit Iterator(const std::shared_ptr<DatasetOp> &root = nullptr);
|
|
|
|
// Destructor
|
|
~Iterator() {}
|
|
|
|
Iterator &operator++() {
|
|
++ind_;
|
|
return *this;
|
|
} // prefix ++ overload
|
|
Iterator operator++(int) {
|
|
Iterator it = *this;
|
|
it.ind_ = ind_;
|
|
ind_++;
|
|
return it;
|
|
} // post-fix ++ overload
|
|
Iterator &operator--() {
|
|
--ind_;
|
|
return *this;
|
|
} // prefix -- overload
|
|
Iterator operator--(int) {
|
|
Iterator it = *this;
|
|
it.ind_ = ind_;
|
|
ind_--;
|
|
return it;
|
|
} // post-fix -- overload
|
|
DatasetOp &operator*() { return *nodes_[ind_]; } // dereference operator
|
|
std::shared_ptr<DatasetOp> operator->() { return nodes_[ind_]; }
|
|
|
|
// getter function
|
|
// @return Shared pointer to the current operator
|
|
std::shared_ptr<DatasetOp> get() { return nodes_[ind_]; }
|
|
|
|
bool operator!=(const Iterator &rhs) { return nodes_[ind_] != rhs.nodes_[rhs.ind_]; }
|
|
|
|
private:
|
|
int ind_; // the cur node our Iterator points to
|
|
std::vector<std::shared_ptr<DatasetOp>> nodes_; // store the nodes in post order
|
|
void PostOrderTraverse(const std::shared_ptr<DatasetOp> &);
|
|
};
|
|
|
|
// Constructor
|
|
ExecutionTree();
|
|
|
|
// Destructor
|
|
~ExecutionTree();
|
|
|
|
// Associates a DatasetOp with this tree. This assigns a valid node id to the operator and
|
|
// provides it with a link to the tree. A node cannot form any relationships (parent/child) with
|
|
// other nodes unless they are associated with the same tree.
|
|
// @param op - The operator to associate
|
|
// @return Status - The error code return
|
|
Status AssociateNode(const std::shared_ptr<DatasetOp> &op);
|
|
|
|
// Sets the root node of the tree
|
|
// @param op - The operator to assign as root
|
|
// @return Status - The error code return
|
|
Status AssignRoot(const std::shared_ptr<DatasetOp> &op);
|
|
|
|
// Start the execution of the tree
|
|
// @return Status - The error code return
|
|
Status Launch();
|
|
|
|
// A print method typically used for debugging
|
|
// @param out - The output stream to write output to
|
|
void Print(std::ostream &out) const;
|
|
|
|
// Returns an iterator positioned at the start
|
|
// @return Iterator - The iterator
|
|
ExecutionTree::Iterator begin(const std::shared_ptr<DatasetOp> &root = nullptr) const {
|
|
return Iterator(root == nullptr ? root_ : root);
|
|
}
|
|
|
|
// Returns an iterator positioned at the end
|
|
// @return Iterator - The iterator
|
|
ExecutionTree::Iterator end() const { return Iterator(nullptr); }
|
|
|
|
// << Stream output operator overload
|
|
// @notes This allows you to write the debug print info using stream operators
|
|
// @param out - reference to the output stream being overloaded
|
|
// @param exe_tree - reference to the execution tree to display
|
|
// @return - the output stream must be returned
|
|
friend std::ostream &operator<<(std::ostream &out, ExecutionTree &exe_tree) {
|
|
exe_tree.Print(out);
|
|
return out;
|
|
}
|
|
|
|
// Given the number of workers, launches the worker entry function for each. Essentially a
|
|
// wrapper for the TaskGroup handling that is stored inside the execution tree.
|
|
// @param num_workers - The number of workers to launch
|
|
// @param func - The function entry point that workers will execute
|
|
// @return Status - The error code return
|
|
Status LaunchWorkers(int32_t num_workers, std::function<Status(uint32_t)> func);
|
|
|
|
// Getter method
|
|
// @return shared_ptr to the root operator
|
|
std::shared_ptr<DatasetOp> root() const { return root_; }
|
|
|
|
// Getter method
|
|
// @return the prepare flags
|
|
uint32_t PrepareFlags() const { return prepare_flags_; }
|
|
|
|
// The driver of the prepare phase of the execution tree.
|
|
// Prepare phase consists of three sub phases
|
|
//
|
|
// 1. PrepareTreePreAction()
|
|
// Compulsory transformation/action pre optimization.
|
|
// For example, CacheOp Insertion
|
|
//
|
|
// 2. Optimize()
|
|
// Optimization transformation/action, optional
|
|
// For example, MapOp Fusion
|
|
//
|
|
// 3. PrepareTreePostAction()
|
|
// Compulsory transformation/action post optimization.
|
|
// For example, repeatOp inlining
|
|
//
|
|
// @return Status - The error code return
|
|
Status Prepare();
|
|
|
|
// Compulsory transformation/action pre optimization.
|
|
// @return Status - The error code return
|
|
Status PrepareTreePreAction();
|
|
|
|
// Compulsory transformation/action post optimization.
|
|
// @return Status - The error code return
|
|
Status PrepareTreePostAction();
|
|
|
|
// Optimization transformation/action, optional.
|
|
// @return Status - The error code return
|
|
Status Optimize();
|
|
|
|
// The DEPRECATED driver of the prepare phase of the execution tree. The prepare phase will recursively
|
|
// walk the tree to perform modifications to the tree or specific nodes within the tree to get
|
|
// it ready for execution.
|
|
// @return Status - The error code return
|
|
Status PrepareDeprecated();
|
|
|
|
// Recursive function used during prepare phase to visit a node and drive any pre- and post-
|
|
// node actions during a tree walk.
|
|
// @param op - The dataset op to work on
|
|
// @return Status - The error code return
|
|
Status PrepareNode(const std::shared_ptr<DatasetOp> &dataset_op);
|
|
|
|
// Adds an operator to the repeat stack during prepare phase.
|
|
// @param op - The dataset op to work add to repeat stack
|
|
// @return Status - The error code return
|
|
void AddToRepeatStack(std::shared_ptr<DatasetOp> dataset_op);
|
|
|
|
// Pops an operator from the repeat stack during prepare phase.
|
|
// @return shared_ptr to the popped operator
|
|
std::shared_ptr<DatasetOp> PopFromRepeatStack();
|
|
|
|
// Return the pointer to the TaskGroup
|
|
// @return raw pointer to the TaskGroup
|
|
TaskGroup *AllTasks() const { return tg_.get(); }
|
|
|
|
// Return if the ExecutionTree is finished (iterator receives EOF).
|
|
// @return Bool - true is ExecutionTree is finished
|
|
bool isFinished() const { return tree_state_ == TreeState::kDeTStateFinished; }
|
|
|
|
// Set the ExecutionTree to Finished state.
|
|
void SetFinished() { tree_state_ = TreeState::kDeTStateFinished; }
|
|
|
|
// Getter for profiling manager, no ownership
|
|
ProfilingManager *GetProfilingManager() { return profiling_manager_.get(); }
|
|
|
|
private:
|
|
// A helper functions for doing the recursive printing
|
|
// @param dataset_op - The dataset op to print
|
|
// @param indent - an indent string for aligning child levels in output
|
|
// @param last - an indicator if it's the last child or not
|
|
// @param detailed - should it display the detailed node output or the summary line
|
|
void PrintNode(std::ostream &out, const std::shared_ptr<DatasetOp> &dataset_op, std::string indent, bool last,
|
|
bool detailed) const;
|
|
|
|
std::unique_ptr<TaskGroup> tg_; // Class for worker management
|
|
std::shared_ptr<DatasetOp> root_; // The root node of the tree
|
|
int32_t id_count_; // Counter for generating operator id's
|
|
uint32_t prepare_flags_; // Flags used during tree prepare
|
|
TreeState tree_state_; // Tracking the current tree state
|
|
std::stack<std::shared_ptr<DatasetOp>> repeat_stack_; // A stack used during prepare phase
|
|
std::unique_ptr<Monitor> perf_monitor_; // Performance Monitor
|
|
std::unique_ptr<ProfilingManager> profiling_manager_; // Profiling manager
|
|
};
|
|
} // namespace dataset
|
|
} // namespace mindspore
|
|
|
|
#endif // DATASET_ENGINE_EXECUTION_TREE_H_
|