diff options
Diffstat (limited to 'runtime/neurun/backend/acl_common/TemplTensorBuilder.h')
-rw-r--r-- | runtime/neurun/backend/acl_common/TemplTensorBuilder.h | 612 |
1 files changed, 0 insertions, 612 deletions
diff --git a/runtime/neurun/backend/acl_common/TemplTensorBuilder.h b/runtime/neurun/backend/acl_common/TemplTensorBuilder.h deleted file mode 100644 index bb43823ed..000000000 --- a/runtime/neurun/backend/acl_common/TemplTensorBuilder.h +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved - * - * 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 __NEURUN_BACKEND_ACL_COMMON_TEMPL_TENSOR_BUILDER_H__ -#define __NEURUN_BACKEND_ACL_COMMON_TEMPL_TENSOR_BUILDER_H__ - -#include <memory> -#include <queue> - -#include <arm_compute/core/Types.h> -#include <backend/ITensorBuilder.h> -#include "ir/OperandIndexMap.h" -#include "AclTensorManager.h" -#include "cpp14/memory.h" -#include <util/Utils.h> - -namespace neurun -{ -namespace backend -{ -namespace acl_common -{ - -enum class UsesType -{ - FIRST, - LAST -}; - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -class TemplTensorBuilder : public ITensorBuilder -{ -public: - using T_AclTensorManager = AclTensorManager<T_ITensor, T_Tensor, T_SubTensor>; - - TemplTensorBuilder(T_AclTensorManager *tensor_mgr); - - /** - * @brief Register tensor information to allocate on ACL-CL backend - * @param[in] ind Operand index - * @param[in] info Tensor information - * @param[in] layout Tensor data layout - */ - void registerTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info, - ir::Layout backend_layout, bool as_const) override; - /** - * @brief Register subtensor information to allocate on ACL-CL backend - * @param[in] ind Operand index - * @param[in] info Tensor information - */ - void registerSubTensorInfo(const ir::OperandIndex &ind, - const compiler::SubTensorInfo &info) override; - - void notifyFirstUse(const ir::OperandIndex &) override; - void notifyLastUse(const ir::OperandIndex &) override; - - bool isRegistered(const ir::OperandIndex &) const override; - - void prepare(void) override; - void allocateConsts() override; - void allocateNonconsts() override; - void postFunctionPrepare() override; - void finalize() override; - - std::shared_ptr<::neurun::backend::operand::ITensor> - tensorAt(const ir::OperandIndex &ind) override; - void iterate(const IterateFunction &fn) override; - - void preVisit(const ir::Operation &node) override; - void postVisit(const ir::Operation &node) override; - - std::unique_ptr<ITensorManager> releaseTensorManager(void) override; - - std::shared_ptr<T_ITensor> at(const ir::OperandIndex &ind); - /** - * @brief Check child tensor is allocated as subtensor of parent tensor - * @param[in] parent Index of parent - * @param[in] child Index of child - * @return @c true if child is allocated as subtensor of parent, otherwise @c false - */ - bool isSubTensorOf(const ir::OperandIndex &parent, const ir::OperandIndex &child); - - void dimCorrection(const ir::OperandIndex &index, bool apply_dim_correction); - - T_AclTensorManager *acl_tensor_manager(void) { return _tensor_mgr.get(); } - - void setUsesCount(const ir::OperandIndex &index, size_t num_uses) - { - assert(_uses_count_map.find(index) != _uses_count_map.end() ? _uses_count_map[index] == num_uses - : true); - _uses_count_map[index] = num_uses; - } - -private: - void buildTensors(void); - void buildSubtensors(void); - void validate(void); - ir::OperandIndex findRootParent(ir::OperandIndex index); - -private: - ir::OperandIndexMap<ir::OperandInfo> _tensor_info_map; - ir::OperandIndexMap<compiler::SubTensorInfo> _subtensor_info_map; - ir::OperandIndexMap<bool> _apply_dim_correction_map; - ir::OperandIndexMap<ir::Layout> _tensor_layout_map; - ir::OperandIndexMap<size_t> _uses_count_map; - - std::unique_ptr<T_AclTensorManager> _tensor_mgr; - ir::OperandIndexSequence _constants; - - // TODO Consider dividing TensorBuilder into Linear and others - const std::string _executor_str; - - // for linear executor - std::queue<std::pair<UsesType, ir::OperandIndex>> _uses_queue; - uint32_t _first_uses_num; - ir::OperandIndexMap<bool> _first_uses_visit; - - // for subtensors - ir::OperandIndexMap<uint32_t> _parent_def; - ir::OperandIndexMap<uint32_t> _parent_uses; -}; - -} // namespace acl_common -} // namespace backend -} // namespace neurun - -#include <cassert> -#include <stack> - -#include "Convert.h" - -#include "util/logging.h" - -namespace neurun -{ -namespace backend -{ -namespace acl_common -{ - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::TemplTensorBuilder( - T_AclTensorManager *tensor_mgr) - : _tensor_mgr{tensor_mgr}, _executor_str(util::getConfigString(util::config::EXECUTOR)), - _first_uses_num(0) -{ - assert(_tensor_mgr); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::registerTensorInfo( - const ir::OperandIndex &ind, const ir::OperandInfo &info, ir::Layout backend_layout, - bool as_const) -{ - assert(_tensor_mgr->constTensors().size() == 0); - assert(_tensor_mgr->nonconstTensors().size() == 0); - - _tensor_info_map.emplace(ind, info); - _apply_dim_correction_map.emplace(ind, true); - _tensor_layout_map.insert({ind, backend_layout}); - if (as_const) - _constants.append(ind); - - assert(_first_uses_visit.find(ind) == _first_uses_visit.end()); - _first_uses_visit[ind] = false; -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::registerSubTensorInfo( - const ir::OperandIndex &ind, const compiler::SubTensorInfo &info) -{ - assert(_tensor_mgr->constTensors().size() == 0); - assert(_tensor_mgr->nonconstTensors().size() == 0); - - _subtensor_info_map.emplace(ind, info); - _apply_dim_correction_map.emplace(ind, true); - - assert(_first_uses_visit.find(ind) == _first_uses_visit.end()); - _first_uses_visit[ind] = false; - - const auto &parent_ind = info.parent(); - - // parent_def - _parent_def[parent_ind] = 1; - - // parent_use - if (_parent_uses.find(parent_ind) == _parent_uses.end()) - _parent_uses[parent_ind] = 1; // 1 means including parent it-self - _parent_uses[parent_ind]++; -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::notifyFirstUse( - const ir::OperandIndex &ind) -{ - _first_uses_num++; - _uses_queue.emplace(UsesType::FIRST, ind); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::notifyLastUse( - const ir::OperandIndex &ind) -{ - _uses_queue.emplace(UsesType::LAST, ind); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -bool TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::isRegistered( - const ir::OperandIndex &ind) const -{ - return _tensor_info_map.find(ind) != _tensor_info_map.end() || - _subtensor_info_map.find(ind) != _subtensor_info_map.end(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::prepare(void) -{ - buildTensors(); - buildSubtensors(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::allocateConsts(void) -{ - assert(_constants.size() == _tensor_mgr->constTensors().size()); - _tensor_mgr->allocateConsts(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::allocateNonconsts(void) -{ - assert(_tensor_info_map.size() == _tensor_mgr->nonconstTensors().size() + _constants.size()); - _tensor_mgr->allocateNonconsts(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::postFunctionPrepare(void) -{ - _tensor_mgr->tryDeallocConstants(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::finalize(void) -{ - validate(); - _tensor_mgr->allocateInternalBufferManager(); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -std::shared_ptr<::neurun::backend::operand::ITensor> -TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::tensorAt(const ir::OperandIndex &ind) -{ - return _tensor_mgr->at(ind); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::iterate(const IterateFunction &fn) -{ - _tensor_mgr->iterate(fn); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -std::shared_ptr<T_ITensor> -TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::at(const ir::OperandIndex &ind) -{ - return _tensor_mgr->at(ind); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -bool TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::isSubTensorOf( - const ir::OperandIndex &parent, const ir::OperandIndex &child) -{ - if (_subtensor_info_map.find(child) == _subtensor_info_map.end()) - { - return false; - } - - auto &subtensors = _tensor_mgr->nonconstSubtensors(); - if (subtensors.find(child) == subtensors.end()) - { - return false; - } - - if (_subtensor_info_map.at(child).parent() != parent) - { - return false; - } - - return true; -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::dimCorrection( - const ir::OperandIndex &index, bool apply_dim_correction) -{ - _apply_dim_correction_map[index] = apply_dim_correction; -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -std::unique_ptr<ITensorManager> -TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::releaseTensorManager(void) -{ - return std::move(_tensor_mgr); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::buildTensors(void) -{ - assert(_tensor_mgr->constTensors().size() == 0); - assert(_tensor_mgr->nonconstTensors().size() == 0); - - for (auto &entry : _tensor_info_map) - { - auto ind = entry.first; - const auto &info = entry.second; - // NOTE SubTensor's layout must be the same with layout of parent tensor - const auto &root_parent = findRootParent(ind); - const auto &backend_layout = _tensor_layout_map[root_parent]; - auto tensor_info = asTensorInfo(info.shape(), info.typeInfo(), ir::Layout::UNKNOWN, - backend_layout, _apply_dim_correction_map[ind]); - _tensor_mgr->buildTensor(ind, tensor_info, info.shape().rank(), _constants.contains(ind), - _uses_count_map[ind]); - } -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::buildSubtensors(void) -{ - // TODO Handle SubTensor(subsumption) - // Currently this TemplTensorBuilder does not have subsumption info yet - // Allocated subtensor will be mapped to _subtensors instead of _tensors - assert(_tensor_mgr->nonconstSubtensors().size() == 0); - - // To make subtensor, parent tensor must be made first - // For this condition, use stack - // 1) Push one subtensor index to stack (iterate subtensors) - // 2) If tensor at stack top is already made, pop and go to 4) - // 3) If tensor pushed at 1) is not made, check parent tensor - // 3-1) If parent tensor is already made, we can make child tensor - // Make child tensor and pop, go to 4) - // 3-2) If parent tensor is not made, we can't make child tensor yet - // Push parent tensor index to stack and return to 4) - // 4) If stack is empty, return to 1), else return to 2) - auto &subtensors = _tensor_mgr->nonconstSubtensors(); - for (auto &entry : _subtensor_info_map) - { - ir::OperandIndex ind = entry.first; - - std::stack<ir::OperandIndex> stack; - stack.push(ind); - - while (!stack.empty()) - { - const auto current = stack.top(); - const auto &info = _subtensor_info_map.at(current); - - // Already generated SubTensor - if (subtensors.find(current) != subtensors.end()) - { - stack.pop(); - continue; - } - - auto parent = info.parent(); - std::shared_ptr<T_ITensor> parent_tensor = _tensor_mgr->findTensorAsParent(parent); - if (!parent_tensor) - { - // Cannot find allocated parent tensor: allocate parent first - assert(_subtensor_info_map.find(parent) != _subtensor_info_map.end()); - stack.push(parent); - continue; - } - assert(parent_tensor != nullptr); - - // Child's type should be same with parent - assert(info.type().offset() == parent_tensor->info()->quantization_info().offset); - assert(info.type().scale() == parent_tensor->info()->quantization_info().scale); - assert(asDataType(info.type().type()) == parent_tensor->info()->data_type()); - - // NOTE SubTensor's layout must be the same with layout of parent tensor - const auto &root_parent = findRootParent(parent); - const auto &backend_layout = _tensor_layout_map[root_parent]; - - auto shape = asTensorShape(info.shape(), ir::Layout::UNKNOWN, backend_layout, - _apply_dim_correction_map[current]); - ::arm_compute::Coordinates coordinates = - asTensorCoordinate(info.offset(), ir::Layout::UNKNOWN, backend_layout); - _tensor_mgr->buildSubtensor(parent, current, shape, coordinates, info.shape().rank(), true); - stack.pop(); - } - } -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::preVisit(const ir::Operation &node) -{ - // For now others executor doesn't need this step - if (_executor_str != "Linear") - { - return; - } - - std::function<void(const ir::OperandIndex &ind)> def_handler = - [this, &def_handler](const ir::OperandIndex &ind) { - bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end(); - bool is_parent = _parent_def.find(ind) != _parent_def.end(); - if (!is_subtensor && !is_parent) - { - _tensor_mgr->startLifetime(ind); - return; - } - - if (is_parent) - { - if (_parent_def[ind] == 0) - return; - - _parent_def[ind] = 0; - - if (is_subtensor) - { - const auto &it = _parent_def.find(ind); - _parent_def.erase(it); - def_handler(ind); - } - else - { - _tensor_mgr->startLifetime(ind); - } - } - else if (is_subtensor) - { - const ir::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent(); - if (_parent_def[parent_ind] == 0) - return; - def_handler(parent_ind); - } - }; - - // See #5642 - ir::OperandIndexMap<bool> outputs_map; - for (const auto &ind : node.getOutputs()) - { - assert(_first_uses_visit.find(ind) != _first_uses_visit.end()); - outputs_map[ind] = _first_uses_visit[ind]; - } - - // outputs_map's all elements are true? - auto outputs_map_all_check = [&outputs_map]() { - return std::all_of(outputs_map.begin(), outputs_map.end(), - [](std::pair<const ir::OperandIndex, bool> it) { return it.second; }); - }; - - std::pair<UsesType, ir::OperandIndex> peak; - while (!outputs_map_all_check() && (peak = _uses_queue.front()).first == UsesType::FIRST) - { - _uses_queue.pop(); - _first_uses_num--; - - const auto &popped_idx = peak.second; - def_handler(popped_idx); - - outputs_map[popped_idx] = true; - _first_uses_visit[popped_idx] = true; - } -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::postVisit(const ir::Operation &node) -{ - // For now others executor doesn't need this step - if (_executor_str != "Linear") - { - return; - } - - std::function<void(const ir::OperandIndex &ind)> use_handler = - [this, &use_handler](const ir::OperandIndex &ind) { - bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end(); - bool is_parent = _parent_uses.find(ind) != _parent_uses.end(); - if (!is_subtensor && !is_parent) - { - _tensor_mgr->finishLifetime(ind); - return; - } - - // This handler shall be executed by the linear executor so that - // The parent operand will always be done after the subtensor - if (is_parent) - { - --_parent_uses[ind]; - assert(_parent_uses[ind] == 0); - - if (is_subtensor) - { - const auto &it = _parent_uses.find(ind); - _parent_uses.erase(it); - use_handler(ind); - } - else - { - _tensor_mgr->finishLifetime(ind); - } - } - else if (is_subtensor) - { - const ir::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent(); - --_parent_uses[parent_ind]; - assert(_parent_uses[parent_ind] > 0); - } - }; - - // See #5642 - const auto &inputs = node.getInputs(); - std::pair<UsesType, ir::OperandIndex> peak; - while ((peak = _uses_queue.front()).first == UsesType::LAST) - { - const auto &popped_idx = peak.second; - if (inputs.contains(popped_idx)) - { - _uses_queue.pop(); - use_handler(popped_idx); - } - else - { - break; - } - } - - if (_first_uses_num == 0) - { - while (!_uses_queue.empty()) - { - peak = _uses_queue.front(); - assert(peak.first == UsesType::LAST); - - _uses_queue.pop(); - - use_handler(peak.second); - } - } -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::validate(void) -{ - // For now others executor doesn't need this step - if (_executor_str != "Linear") - { - return; - } - - for (auto it : _tensor_info_map) - { - assert(_first_uses_visit.find(it.first) != _first_uses_visit.end()); - assert(_first_uses_visit[it.first]); - } - - for (auto it : _subtensor_info_map) - { - assert(_first_uses_visit.find(it.first) != _first_uses_visit.end()); - assert(_first_uses_visit[it.first]); - } - - for (auto it : _tensor_layout_map) - { - assert(_first_uses_visit.find(it.first) != _first_uses_visit.end()); - assert(_first_uses_visit[it.first]); - UNUSED_RELEASE(it); - } - - assert(_uses_queue.size() == 0); - assert(_first_uses_num == 0); - - assert( - std::all_of(_parent_def.begin(), _parent_def.end(), - [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; })); - - assert( - std::all_of(_parent_uses.begin(), _parent_uses.end(), - [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; })); -} - -template <typename T_ITensor, typename T_Tensor, typename T_SubTensor> -ir::OperandIndex -TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor>::findRootParent(ir::OperandIndex ind) -{ - if (_subtensor_info_map.find(ind) == _subtensor_info_map.end()) - return ind; - - const auto &parent_ind = _subtensor_info_map.at(ind).parent(); - return findRootParent(parent_ind); -} - -} // namespace acl_common -} // namespace backend -} // namespace neurun - -#endif // __NEURUN_BACKEND_ACL_COMMON_TEMPL_TENSOR_BUILDER_H__ |