/** * Copyright 2020 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. */ #include "graph/build/memory/binary_block_mem_assigner.h" #include #include "framework/common/debug/ge_log.h" #include "graph/utils/type_utils.h" namespace { const uint32_t kRangeCeilInterval = 2; const uint32_t kLogBase = 2; const int64_t kLargeBlockSize = 8 * 1024 * 1024; const int64_t kLargeBlockRangeSize = 10; } // namespace namespace ge { using std::vector; void BinaryBlockMemAssigner::PlanRanges(size_t range_number_limit, vector> &ranges) { /// range delete and merge /// result after delete and merge is: [[6,12],[16,24,24],[30,32,48],[60,256]] bool changed = false; vector temp; do { changed = false; for (auto iter = ranges.begin(); iter != ranges.end();) { if (!temp.empty()) { iter->insert(iter->end(), temp.begin(), temp.end()); temp.clear(); } if (iter->empty()) { iter = ranges.erase(iter); changed = true; } else if ((iter->size() < range_number_limit) && (ranges.end() - iter > 1) && !(iter->at(0) >= kLargeBlockSize && iter->size() >= kLargeBlockRangeSize)) { temp.insert(temp.end(), iter->begin(), iter->end()); iter = ranges.erase(iter); changed = true; } else { ++iter; } } } while (changed); } /// /// @ingroup domi_omg /// @brief memory size fixed for reuse. this function determines memory types and sizes /// @param [out] range_ceils return memory sizes /// @return Status result /// @author /// Status BinaryBlockMemAssigner::GetMemoryRanges(vector &range_ceils) { vector all_memory_size; GetOutAndWorkSpaceMem(all_memory_size); if (all_memory_size.empty()) { GELOGW("Vector all_memory_size is empty!"); return SUCCESS; } if ((all_memory_size.front() == 0) || (log(kLogBase) == 0)) { GELOGE(FAILED, "dividend is 0!"); return FAILED; } auto range_number = static_cast( ceil(log(all_memory_size.back() / static_cast(all_memory_size.front())) / log(kLogBase))); range_number = (range_number == 0) ? 1 : range_number; GELOGI("Range number: %zu", range_number); vector> ranges(range_number); GE_CHK_BOOL_EXEC((range_number != 0), return PARAM_INVALID, "range_number can't be 0."); size_t range_number_limit = all_memory_size.size() / range_number; int64_t range_ceil = all_memory_size[0]; for (size_t i = 1; i <= range_number; i++) { GE_IF_BOOL_EXEC(TypeUtils::CheckUint64MulOverflow(static_cast(range_ceil), kRangeCeilInterval), GELOGE(FAILED, "Multiply result is out of range."); return FAILED); range_ceil *= kRangeCeilInterval; // The block size of each interval is doubled every time. for (auto iter = all_memory_size.begin(); iter != all_memory_size.end();) { if (*iter <= range_ceil) { ranges[i - 1].push_back(*iter); iter = all_memory_size.erase(iter); } else { break; } } } GELOGD("Origin ranges:"); for (auto &v : ranges) { GELOGD("__%s", ToString(v).c_str()); } PlanRanges(range_number_limit, ranges); GELOGD("Origin ranges:"); for (auto &v : ranges) { GELOGD("__%s", ToString(v).c_str()); } for (auto &range : ranges) { std::sort(range.begin(), range.end()); if (!range.empty()) { range_ceils.push_back(range.back()); } } GELOGI("Range ceils: %s", ToString(range_ceils).c_str()); return SUCCESS; } } // namespace ge