From 3425ffea01f6061a03acd7d1f5ae5f5cf15b9173 Mon Sep 17 00:00:00 2001 From: lichun Date: Sun, 25 Apr 2021 20:02:49 +0800 Subject: [PATCH] mark attr distance --- ge/graph/build/memory/graph_mem_assigner.cc | 219 ++++++++++++++++------------ ge/graph/build/memory/graph_mem_assigner.h | 25 ++++ 2 files changed, 152 insertions(+), 92 deletions(-) diff --git a/ge/graph/build/memory/graph_mem_assigner.cc b/ge/graph/build/memory/graph_mem_assigner.cc index 7d01dcc3..74f8042b 100755 --- a/ge/graph/build/memory/graph_mem_assigner.cc +++ b/ge/graph/build/memory/graph_mem_assigner.cc @@ -1941,7 +1941,7 @@ Status GraphMemoryAssigner::AssignBufferPoolMemory() { // if producer and customers in the same stream, or customers on the same stream when producer not assign a stream, // then return false. -static bool IsOutputVisitedByMultiStream(const NodePtr &peer_out_node, int64_t out_anchor_index) { +bool GraphMemoryAssigner::IsOutputVisitedByMultiStream(const NodePtr &peer_out_node, int64_t out_anchor_index) { GE_IF_BOOL_EXEC(peer_out_node->GetOpDesc() == nullptr, return true); int64_t unique_stream_id = peer_out_node->GetOpDesc()->GetStreamId(); @@ -1963,9 +1963,9 @@ static bool IsOutputVisitedByMultiStream(const NodePtr &peer_out_node, int64_t o return false; } -static void UpdatePrevNodeInputDesc(const NodePtr &prev_node, - const vector &prev_node_input_index_vec, - int64_t distance) { +void GraphMemoryAssigner::UpdatePrevNodeInputDesc(const NodePtr &prev_node, + const vector &prev_node_input_index_vec, + int64_t distance) { GE_IF_BOOL_EXEC(prev_node == nullptr, return); auto prev_node_op_desc = prev_node->GetOpDesc(); GE_IF_BOOL_EXEC(prev_node_op_desc == nullptr, return); @@ -2007,7 +2007,9 @@ static void UpdatePrevNodeInputDesc(const NodePtr &prev_node, return; } -static void UpdateCurNodeInputDesc(const NodePtr &cur_node, int64_t cur_node_input_index, int64_t distance) { +void GraphMemoryAssigner::UpdateCurNodeInputDesc(const NodePtr &cur_node, + int64_t cur_node_input_index, + int64_t distance) { GE_IF_BOOL_EXEC(cur_node == nullptr, return); GE_IF_BOOL_EXEC(cur_node->GetOpDesc() == nullptr, return); auto input_desc = cur_node->GetOpDesc()->GetInputDesc(cur_node_input_index); @@ -2032,7 +2034,113 @@ static void UpdateCurNodeInputDesc(const NodePtr &cur_node, int64_t cur_node_inp return; } +size_t GraphMemoryAssigner::GetMemoryOffset(const HybridMemAssignerPtr &mem_assigner, + const NodePtr &peer_out_node, + const OutDataAnchorPtr &peer_out_anchor) { + NodeIndexIO node_index_io(peer_out_node, peer_out_anchor->GetIdx(), kOut); + string symbol; + size_t matched_mem_offset = mem_assigner->GetPriorityAssinger()->GetAnchorDataOffset(node_index_io, symbol); + if (matched_mem_offset == kInvalidOffset) { + // peer_out_anchor not assign MemoryBlock, we search the peer_out_anchor's data in continous memory + matched_mem_offset = peer_out_node->GetOpDesc()->GetOutputOffset().at(peer_out_anchor->GetIdx()); + } + return matched_mem_offset; +} + +void GraphMemoryAssigner::CheckNeedCalcDistAndUpdateVisitInfo( + map>> &mem_block_visit_info, + size_t matched_mem_offset, + const NodePtr &peer_out_node, + const OutDataAnchorPtr &peer_out_anchor, + bool &is_need_calc_distance) { + auto iter = mem_block_visit_info.find(matched_mem_offset); + // cannot find visit info, peer_out_node must be a producer and this data is the first time to be visited. + if (iter == mem_block_visit_info.end()) { + if (IsOutputVisitedByMultiStream(peer_out_node, peer_out_anchor->GetIdx())) { + vector temp; + mem_block_visit_info.insert(std::make_pair(matched_mem_offset, std::make_pair(nullptr, temp))); + is_need_calc_distance = false; + return; + } else { + vector temp = {-1}; + // producer's prev_node_index set to -1 as default + mem_block_visit_info.insert(std::make_pair(matched_mem_offset, std::make_pair(peer_out_node, temp))); + is_need_calc_distance = true; + return; + } + } else { + if (mem_block_visit_info[matched_mem_offset].first == nullptr) { // multi-stream visit, no need to calculate + is_need_calc_distance = false; + return; + } + if (peer_out_node->GetOpDesc()->GetStreamId() != + mem_block_visit_info[matched_mem_offset].first->GetOpDesc()->GetStreamId()) { + // cur node and peer_out_node not in the same stream, no need to calculate + is_need_calc_distance = false; + return; + } + } + is_need_calc_distance = true; + return; +} +// calculate distance, update visit info, update prev_node input desc, update cur node input desc +void GraphMemoryAssigner::CalcDistanceAndUpdateDesc(map>> &mem_block_visit_info, + size_t matched_mem_offset, + const map &node_index_in_stream, + NodePtr &node, + const InDataAnchorPtr &in_data_anchor, + bool &is_need_skip) { + int64_t distance = -1; + auto prev_node = mem_block_visit_info[matched_mem_offset].first; + auto prev_node_input_index_vec = mem_block_visit_info[matched_mem_offset].second; + GE_IF_BOOL_EXEC(prev_node == nullptr, is_need_skip = true; return); + if (prev_node_input_index_vec.size() == 1 && prev_node_input_index_vec[0] == -1) { + // prev_node is producer and the data is just be produced(not visited by other node) + GE_IF_BOOL_EXEC(prev_node->GetOpDesc() == nullptr, is_need_skip = true; return); + if (prev_node->GetOpDesc()->GetStreamId() == -1) { // producer not assigned a stream + distance = 0; + } else if (node_index_in_stream.find(prev_node->GetName()) == node_index_in_stream.end()) { + distance = 0; + } else { + distance = node_index_in_stream.at(node->GetName()) - node_index_in_stream.at(prev_node->GetName()) - 1; + } + mem_block_visit_info[matched_mem_offset].first = node; + mem_block_visit_info[matched_mem_offset].second.clear(); + mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); + } else { // the data is visit by other customer just before. + if (prev_node_input_index_vec.empty()) { + GELOGW("Missing prev node[%s] input index.", prev_node->GetName().c_str()); + is_need_skip = true; + return; + } + if (prev_node == node) { // scene: multiple anchors of a node access the same data + vector prev_next_distances; + GE_IF_BOOL_EXEC(prev_node->GetOpDesc() == nullptr, is_need_skip = true; return); + auto input_desc = prev_node->GetOpDesc()->GetInputDesc(prev_node_input_index_vec[0]); + if (!ge::AttrUtils::GetListInt(input_desc, ATTR_NAME_DATA_VISIT_DISTANCE, prev_next_distances)) { + GELOGW("Get ATTR_NAME_DATA_VISIT_DISTANCE failed."); + is_need_skip = true; + return; + } + if (prev_next_distances.size() != kPrevNextDistanceNum) { + GELOGW("Size of prev_next_distance is not 2."); + is_need_skip = true; + return; + } else { + distance = prev_next_distances[0]; //use the same prev_distance of previous anchor + } + mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); + } else { + distance = node_index_in_stream.at(node->GetName()) - node_index_in_stream.at(prev_node->GetName()) - 1; + UpdatePrevNodeInputDesc(prev_node, prev_node_input_index_vec, distance); + mem_block_visit_info[matched_mem_offset].first = node; + mem_block_visit_info[matched_mem_offset].second.clear(); + mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); + } + } + UpdateCurNodeInputDesc(node, in_data_anchor->GetIdx(), distance); +} void GraphMemoryAssigner::MarkNodeDistanceAttr(const ComputeGraphPtr &compute_graph, NodePtr &node, @@ -2046,105 +2154,32 @@ void GraphMemoryAssigner::MarkNodeDistanceAttr(const ComputeGraphPtr &compute_gr auto peer_out_node = peer_out_anchor->GetOwnerNode(); GE_IF_BOOL_EXEC(peer_out_node == nullptr, continue); - NodeIndexIO node_index_io(peer_out_node, peer_out_anchor->GetIdx(), kOut); - std::string symbol; - size_t matched_mem_offset = mem_assigner_->GetPriorityAssinger()->GetAnchorDataOffset(node_index_io, symbol); - if (matched_mem_offset == kInvalidOffset) { - // peer_out_anchor not assign MemoryBlock, we search the peer_out_anchor's data in continous memory - matched_mem_offset = peer_out_node->GetOpDesc()->GetOutputOffset().at(peer_out_anchor->GetIdx()); - } + auto matched_mem_offset = GetMemoryOffset(mem_assigner_, peer_out_node, peer_out_anchor); - auto iter = mem_block_visit_info.find(matched_mem_offset); - // cannot find visit info, peer_out_node must be a producer and this data is the first time to be visited. - if (iter == mem_block_visit_info.end()) { - if (IsOutputVisitedByMultiStream(peer_out_node, peer_out_anchor->GetIdx())) { - vector temp; - mem_block_visit_info.insert(std::make_pair(matched_mem_offset, std::make_pair(nullptr, temp))); - continue; - } else { - vector temp = {-1}; - // producer's prev_node_index set to -1 as default - mem_block_visit_info.insert(std::make_pair(matched_mem_offset, std::make_pair(peer_out_node, temp))); - } - } else { - if (mem_block_visit_info[matched_mem_offset].first == nullptr) { // multi-stream visit, no need to calculate - continue; - } - if (peer_out_node->GetOpDesc()->GetStreamId() != - mem_block_visit_info[matched_mem_offset].first->GetOpDesc()->GetStreamId()) { - // cur node and peer_out_node not in the same stream, no need to calculate - continue; - } + bool is_need_calc_distance = false; + CheckNeedCalcDistAndUpdateVisitInfo(mem_block_visit_info, matched_mem_offset, peer_out_node, + peer_out_anchor, is_need_calc_distance); + if (!is_need_calc_distance) { + continue; } - // now mem_block_visit_info must contains that memory_block - // steps: calculate distance, update visit info, update prev_node input desc, update cur node input desc - int64_t distance = -1; - auto prev_node = mem_block_visit_info[matched_mem_offset].first; - auto prev_node_input_index_vec = mem_block_visit_info[matched_mem_offset].second; - GE_IF_BOOL_EXEC(prev_node == nullptr, continue); - if (prev_node_input_index_vec.size() == 1 && prev_node_input_index_vec[0] == -1) { - // prev_node is producer and the data is just be produced(not visited by other node) - GE_IF_BOOL_EXEC(prev_node->GetOpDesc() == nullptr, continue); - if (prev_node->GetOpDesc()->GetStreamId() == -1) { // producer not assigned a stream - distance = 0; - } else if (node_index_in_stream.find(prev_node->GetName()) == node_index_in_stream.end()) { - // prev_node is ge local op - distance = 0; - } else { - distance = node_index_in_stream.at(node->GetName()) - node_index_in_stream.at(prev_node->GetName()) - 1; - } - mem_block_visit_info[matched_mem_offset].first = node; - mem_block_visit_info[matched_mem_offset].second.clear(); - mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); - } else { // the data is visit by other customer just before. - if (prev_node_input_index_vec.empty()) { - GELOGW("Missing prev node[%s] input index.", prev_node->GetName().c_str()); - continue; - } - if (prev_node == node) { // scene: multiple anchors of a node access the same data - vector prev_next_distances; - // 1. do not need to update prev_node's input desc, because it must be updated when the first anchor visit it. - // 2. we use the same distance of previous anchor to keep this value the same. - // 3. update visit info's prev_node_input_index_vec - if (prev_node->GetOpDesc() == nullptr) { - continue; - } - auto input_desc = prev_node->GetOpDesc()->GetInputDesc(prev_node_input_index_vec[0]); - if (!ge::AttrUtils::GetListInt(input_desc, ATTR_NAME_DATA_VISIT_DISTANCE, prev_next_distances)) { - GELOGW("Get ATTR_NAME_DATA_VISIT_DISTANCE failed."); - continue; - } - if (prev_next_distances.size() != kPrevNextDistanceNum) { - GELOGW("Size of prev_next_distance is not 2."); - continue; - } else { - distance = prev_next_distances[0]; //use the same prev_distance of previous anchor - } - mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); - } else { - // now, prev_node must be customer because if cur node and prev node not on the same stream, then it will be - // continue at IsOutputVisitedByMultiStream. - distance = node_index_in_stream.at(node->GetName()) - node_index_in_stream.at(prev_node->GetName()) - 1; - UpdatePrevNodeInputDesc(prev_node, prev_node_input_index_vec, distance); - mem_block_visit_info[matched_mem_offset].first = node; - mem_block_visit_info[matched_mem_offset].second.clear(); - mem_block_visit_info[matched_mem_offset].second.push_back(in_data_anchor->GetIdx()); - } + bool is_need_skip = false; + CalcDistanceAndUpdateDesc(mem_block_visit_info, matched_mem_offset, node_index_in_stream, node, + in_data_anchor, is_need_skip); + if (is_need_skip) { + continue; } - UpdateCurNodeInputDesc(node, in_data_anchor->GetIdx(), distance); auto input_desc = node->GetOpDesc()->GetInputDesc(in_data_anchor->GetIdx()); bool is_end_of_inputmem_lifecycle = false; - // if is_end_of_inputmem_lifecycle is true, indicating that cur node is the last customer of this data, // then we need to delete the visit info of the block in case that the memblock be reused and visited. if (ge::AttrUtils::GetBool(input_desc, ATTR_NAME_IS_END_OF_INPUTMEM_LIFECYCLE, is_end_of_inputmem_lifecycle) && is_end_of_inputmem_lifecycle) { GELOGD("ATTR_NAME_IS_END_OF_INPUTMEM_LIFECYCLE is true"); - auto iter2 = mem_block_visit_info.find(matched_mem_offset); - if (iter2 != mem_block_visit_info.end()) { - mem_block_visit_info.erase(iter2); + auto iter = mem_block_visit_info.find(matched_mem_offset); + if (iter != mem_block_visit_info.end()) { + mem_block_visit_info.erase(iter); } } } diff --git a/ge/graph/build/memory/graph_mem_assigner.h b/ge/graph/build/memory/graph_mem_assigner.h index 04c21a3f..b3abefb1 100755 --- a/ge/graph/build/memory/graph_mem_assigner.h +++ b/ge/graph/build/memory/graph_mem_assigner.h @@ -204,6 +204,31 @@ class GraphMemoryAssigner { Status UpdateRefOpOffsetReverse(const NodePtr &node); + bool IsOutputVisitedByMultiStream(const NodePtr &peer_out_node, int64_t out_anchor_index); + + void UpdatePrevNodeInputDesc(const NodePtr &prev_node, + const vector &prev_node_input_index_vec, + int64_t distance); + + void UpdateCurNodeInputDesc(const NodePtr &cur_node, int64_t cur_node_input_index, int64_t distance); + + size_t GetMemoryOffset(const HybridMemAssignerPtr &mem_assigner, + const NodePtr &peer_out_node, + const OutDataAnchorPtr &peer_out_anchor); + + void CheckNeedCalcDistAndUpdateVisitInfo(map>> &mem_block_visit_info, + size_t matched_mem_offset, + const NodePtr &peer_out_node, + const OutDataAnchorPtr &peer_out_anchor, + bool &is_need_calc_distance); + + void CalcDistanceAndUpdateDesc(map>> &mem_block_visit_info, + size_t matched_mem_offset, + const map &node_index_in_stream, + NodePtr &node, + const InDataAnchorPtr &in_data_anchor, + bool &is_need_skip); + MemoryOffsetMap memory_offset_; ge::ComputeGraphPtr compute_graph_; HybridMemAssignerPtr mem_assigner_;