forked from mindspore-Ecosystem/mindspore
!34390 [MS][LITE] dpico runtime refactoring
Merge pull request !34390 from jianghui58/dpico_runtime_0512
This commit is contained in:
commit
fa43506432
|
@ -1,6 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
project(DPICO_Custom)
|
||||
include(${TOP_DIR}/cmake/utils.cmake)
|
||||
|
||||
if(DEFINED ENV{HISI_SDK_PATH})
|
||||
set(SD3403_SDK_PATH $ENV{HISI_SDK_PATH}/sd3403_sdk/dpico_acl_adapter/3403_sdk)
|
||||
|
@ -8,7 +7,7 @@ else()
|
|||
message(FATAL_ERROR "error, no sdk found")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${SD3403_SDK_PATH})
|
||||
include_directories(${SD3403_SDK_PATH}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../runtime)
|
||||
|
@ -16,12 +15,17 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../runtime/include)
|
|||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../runtime/include/third_party)
|
||||
link_directories(${SD3403_SDK_PATH}/lib)
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src COMMON_SRC)
|
||||
set(DEPENDENCY_LIBS
|
||||
${SD3403_SDK_PATH}/lib/libsvp_acl.so
|
||||
${SD3403_SDK_PATH}/lib/libprotobuf-c.so.1
|
||||
${SD3403_SDK_PATH}/lib/libsecurec.so)
|
||||
|
||||
set(LINK_LOCAT_LIB ${SD3403_SDK_PATH}/lib/libsvp_acl.so
|
||||
pthread ${SD3403_SDK_PATH}/lib/libsecurec.so dl
|
||||
${SD3403_SDK_PATH}/lib/libprotobuf-c.so.1 stdc++)
|
||||
file(GLOB_RECURSE DPICO_RUNTIME_SRC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/infer/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/manager/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc
|
||||
)
|
||||
|
||||
add_library(dpico_acl_adapter SHARED
|
||||
${COMMON_SRC})
|
||||
target_link_libraries(dpico_acl_adapter ${LINK_LOCAT_LIB} securec)
|
||||
add_library(dpico_acl_adapter SHARED ${DPICO_RUNTIME_SRC})
|
||||
target_link_libraries(dpico_acl_adapter ${DEPENDENCY_LIBS})
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_COMMON_CHECK_BASE_H_
|
||||
#define DPICO_COMMON_CHECK_BASE_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include "common/log_util.h"
|
||||
|
||||
#define UP_DIV(x, y) (((x) + (y) - (1)) / (y))
|
||||
#define UP_ROUND(x, y) (((x) + (y) - (1)) / (y) * (y))
|
||||
#define DOWN_DIV(x, y) ((x) / (y))
|
||||
#define DOWN_ROUND(x, y) ((x) / (y) * (y))
|
||||
|
||||
#define kNHWC_N 0
|
||||
#define kNHWC_H 1
|
||||
#define kNHWC_W 2
|
||||
#define kNHWC_C 3
|
||||
#define kNCHW_N 0
|
||||
#define kNCHW_C 1
|
||||
#define kNCHW_H 2
|
||||
#define kNCHW_W 3
|
||||
#define kInputSize1 1
|
||||
#define kInputSize2 2
|
||||
#define kInputSize3 3
|
||||
#ifdef Debug
|
||||
#include <cassert>
|
||||
#define MS_ASSERT(f) assert(f)
|
||||
#else
|
||||
#define MS_ASSERT(f) ((void)0)
|
||||
#endif
|
||||
|
||||
#define SIZE_MUL_OVERFLOW(x, y) (((x) == 0) ? false : (SIZE_MAX / (x)) < (y))
|
||||
#define INT_MUL_OVERFLOW(x, y) \
|
||||
(((x) == 0) ? false \
|
||||
: ((x) > 0 ? (((y) >= 0) ? (INT_MAX / (x)) < (y) : (INT_MAX / (x)) < (-1 * (y))) \
|
||||
: (((y) >= 0) ? (INT_MAX / (x)) > (-1 * (y)) : (INT_MAX / (x)) > (y))))
|
||||
|
||||
#define INT_MUL_OVERFLOW_THRESHOLD(x, y, threshold) \
|
||||
(((x) == 0) ? false \
|
||||
: ((x) > 0 ? (((y) >= 0) ? ((threshold) / (x)) < (y) : ((threshold) / (x)) < (-1 * (y))) \
|
||||
: (((y) >= 0) ? ((threshold) / (x)) > (-1 * (y)) : ((threshold) / (x)) > (y))))
|
||||
|
||||
#define INT_ADD_OVERFLOW(x, y) (INT_MAX - (x)) < (y)
|
||||
|
||||
#define CHECK_LESS_RETURN(size1, size2) \
|
||||
do { \
|
||||
if ((size1) < (size2)) { \
|
||||
MS_LOG(ERROR) << #size1 << " must not be less than " << #size2; \
|
||||
return mindspore::lite::RET_ERROR; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Check whether value is true, if not return 'errcode'
|
||||
// and print error string msg
|
||||
#define MS_CHECK_TRUE_MSG(value, errcode, msg) \
|
||||
do { \
|
||||
if (!(value)) { \
|
||||
MS_LOG(ERROR) << msg; \
|
||||
return errcode; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Check whether value is true, if not return void
|
||||
// and print error string msg
|
||||
#define MS_CHECK_TRUE_MSG_VOID(value, msg) \
|
||||
do { \
|
||||
if (!(value)) { \
|
||||
MS_LOG(ERROR) << msg; \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // DPICO_COMMON_CHECK_BASE_H_
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_COMMON_CUSTOM_ENUM_H_
|
||||
#define DPICO_COMMON_CUSTOM_ENUM_H_
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
enum AclModelType : size_t { kCnn = 0, kRoi = 1, kRecurrent = 2 };
|
||||
enum DetectParam : size_t { kNmsThreshold = 0, kScoreThreshold = 1, kMinHeight = 2, kMinWidth = 3 };
|
||||
enum DetectBoxParam : size_t {
|
||||
kTopLeftX = 0,
|
||||
kDetectBoxParamBegin = kTopLeftX,
|
||||
kTopLeftY = 1,
|
||||
kBottomRightX = 2,
|
||||
kBottomRightY = 3,
|
||||
kScore = 4,
|
||||
kClassId = 5,
|
||||
kDetectBoxParamEnd
|
||||
};
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_COMMON_CUSTOM_ENUM_H_
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright 2022 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 "common/infer_util.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "common/log_util.h"
|
||||
#include "include/errorcode.h"
|
||||
|
||||
using mindspore::lite::RET_ERROR;
|
||||
using mindspore::lite::RET_OK;
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
int CheckCustomInputOutput(const std::vector<mindspore::MSTensor> *inputs,
|
||||
const std::vector<mindspore::MSTensor> *outputs, const schema::Primitive *primitive) {
|
||||
if (inputs == nullptr) {
|
||||
MS_LOG(ERROR) << "inputs is nullptr.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (outputs == nullptr) {
|
||||
MS_LOG(ERROR) << "outputs is nullptr.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (primitive == nullptr) {
|
||||
MS_LOG(ERROR) << "primitive is nullptr.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (inputs->empty()) {
|
||||
MS_LOG(ERROR) << "Inputs size 0.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (outputs->empty()) {
|
||||
MS_LOG(ERROR) << "Outputs size 0.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (primitive->value_type() != schema::PrimitiveType_Custom) {
|
||||
MS_LOG(ERROR) << "Primitive type is not PrimitiveType_Custom.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int CheckCustomParam(const schema::Custom *param, const std::string ¶m_name) {
|
||||
if (param == nullptr) {
|
||||
MS_LOG(ERROR) << "param is nullptr";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (param->type() == nullptr) {
|
||||
MS_LOG(ERROR) << "param->type() is nullptr";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (param->type()->str() != param_name) {
|
||||
MS_LOG(ERROR) << "current custom node should be " << param_name << ", but in fact it's " << param->type()->str();
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_COMMON_INFER_UTIL_H_
|
||||
#define DPICO_COMMON_INFER_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "include/api/types.h"
|
||||
#include "schema/model_generated.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
int CheckCustomInputOutput(const std::vector<mindspore::MSTensor> *inputs,
|
||||
const std::vector<mindspore::MSTensor> *outputs, const schema::Primitive *primitive);
|
||||
int CheckCustomParam(const schema::Custom *param, const std::string ¶m_name);
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DPICO_COMMON_INFER_UTIL_H_
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "src/custom_log.h"
|
||||
#include "common/log_util.h"
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
namespace mindspore {
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -13,14 +13,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MINDSPORE_LITE_TOOLS_BENCHMARK_DPICO_SRC_CUSTOM_LOG_H_
|
||||
#define MINDSPORE_LITE_TOOLS_BENCHMARK_DPICO_SRC_CUSTOM_LOG_H_
|
||||
|
||||
#ifndef DPICO_COMMON_LOG_UTIL_H_
|
||||
#define DPICO_COMMON_LOG_UTIL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
// NOTICE: when relative path of 'log.h' changed, macro 'DPICO_LOG_HEAR_FILE_REL_PATH' must be changed
|
||||
#define DPICO_LOG_HEAR_FILE_REL_PATH "mindspore/lite/tools/benchmark/dpico/src/custom_log.h"
|
||||
#define DPICO_LOG_HEAR_FILE_REL_PATH "mindspore/lite/providers/dpico/common/log_util.h"
|
||||
|
||||
// Get start index of file relative path in __FILE__
|
||||
static constexpr size_t GetRealPathPos() noexcept {
|
||||
|
@ -96,4 +97,4 @@ class DpicoLogWriter {
|
|||
#define MS_LOG_ERROR MSLOG_IF(mindspore::DpicoLogLevel::ERROR)
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // MINDSPORE_LITE_TOOLS_BENCHMARK_DPICO_SRC_CUSTOM_LOG_H_
|
||||
#endif // DPICO_COMMON_LOG_UTIL_H_
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_COMMON_OP_ATTR_H_
|
||||
#define DPICO_COMMON_OP_ATTR_H_
|
||||
|
||||
namespace mindspore {
|
||||
constexpr auto kAclConfigPath = "AclConfigPath";
|
||||
constexpr auto kDetectionPostProcess = "DetectionPostProcess";
|
||||
constexpr auto kDpico = "dpico";
|
||||
constexpr auto kInputsShape = "inputs_shape";
|
||||
constexpr auto kGTotalT = "GTotalT";
|
||||
constexpr auto kMaxRoiNum = "MaxRoiNum";
|
||||
constexpr auto kMinHeight = "MinHeight";
|
||||
constexpr auto kMinWidth = "MinWidth";
|
||||
constexpr auto kNetType = "net_type";
|
||||
constexpr auto kNmsThreshold = "NmsThreshold";
|
||||
constexpr auto kOutputsFormat = "outputs_format";
|
||||
constexpr auto kOutputsShape = "outputs_shape";
|
||||
constexpr auto kScoreThreshold = "ScoreThreshold";
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_COMMON_OP_ATTR_H_
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright 2022 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 "common/string_util.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include "common/log_util.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
std::vector<std::string> SplitString(const std::string &raw_str, char delimiter) {
|
||||
if (raw_str.empty()) {
|
||||
MS_LOG(ERROR) << "input string is empty.";
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> res;
|
||||
std::string::size_type last_pos = 0;
|
||||
auto cur_pos = raw_str.find(delimiter);
|
||||
while (cur_pos != std::string::npos) {
|
||||
res.push_back(raw_str.substr(last_pos, cur_pos - last_pos));
|
||||
cur_pos++;
|
||||
last_pos = cur_pos;
|
||||
cur_pos = raw_str.find(delimiter, cur_pos);
|
||||
}
|
||||
if (last_pos < raw_str.size()) {
|
||||
res.push_back(raw_str.substr(last_pos, raw_str.size() - last_pos + 1));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IsValidUnsignedNum(const std::string &num_str) {
|
||||
return !num_str.empty() && std::all_of(num_str.begin(), num_str.end(), ::isdigit);
|
||||
}
|
||||
|
||||
bool IsValidDoubleNum(const std::string &num_str) {
|
||||
if (num_str.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::istringstream iss(num_str);
|
||||
double d;
|
||||
iss >> std::noskipws >> d;
|
||||
return iss.eof() && !iss.fail();
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_COMMON_STRING_UTIL_H_
|
||||
#define DPICO_COMMON_STRING_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include "include/errorcode.h"
|
||||
|
||||
using mindspore::lite::RET_ERROR;
|
||||
using mindspore::lite::RET_OK;
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
std::vector<std::string> SplitString(const std::string &raw_str, char delimiter);
|
||||
bool IsValidUnsignedNum(const std::string &num_str);
|
||||
bool IsValidDoubleNum(const std::string &num_str);
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_COMMON_STRING_UTIL_H_
|
|
@ -0,0 +1,251 @@
|
|||
/**
|
||||
* Copyright 2021-2022 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 "infer/custom_infer.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "manager/acl_model_helper.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "include/registry/register_kernel_interface.h"
|
||||
#include "common/log_util.h"
|
||||
#include "common/op_attr.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/infer_util.h"
|
||||
|
||||
using mindspore::dpico::CustomInterface;
|
||||
using mindspore::kernel::KernelInterface;
|
||||
using mindspore::lite::RET_ERROR;
|
||||
using mindspore::lite::RET_OK;
|
||||
using mindspore::schema::PrimitiveType_Custom;
|
||||
|
||||
namespace mindspore {
|
||||
namespace dpico {
|
||||
namespace {
|
||||
constexpr int kOmParameterNum = 1;
|
||||
Status FetchAttrs(const schema::Primitive &primitive, std::map<std::string, std::string> *attrs) {
|
||||
if (attrs == nullptr) {
|
||||
MS_LOG(ERROR) << "function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto param = primitive.value_as_Custom();
|
||||
if (lite::CheckCustomParam(param, "DPICO") != RET_OK) {
|
||||
MS_LOG(ERROR) << "custom param is invalid.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (param->attr() == nullptr) {
|
||||
MS_LOG(ERROR) << "param attr is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (param->attr()->size() < 1) {
|
||||
MS_LOG(ERROR) << "There are at least 1 attribute of Custom";
|
||||
return kLiteError;
|
||||
}
|
||||
for (size_t i = 0; i < param->attr()->size(); i++) {
|
||||
if (param->attr()->Get(i) == nullptr || param->attr()->Get(i)->name() == nullptr) {
|
||||
MS_LOG(ERROR) << "param->attr()->Get(i) is nullptr or param->attr()->Get(i)->name() is nullptr";
|
||||
return kLiteError;
|
||||
}
|
||||
auto output_info = param->attr()->Get(i)->data();
|
||||
if (output_info == nullptr) {
|
||||
return kLiteError;
|
||||
}
|
||||
int buf_size = static_cast<int>(output_info->size());
|
||||
std::string attr;
|
||||
for (int j = 0; j < buf_size; j++) {
|
||||
attr.push_back(static_cast<char>(output_info->Get(j)));
|
||||
}
|
||||
auto attr_name = param->attr()->Get(i)->name()->str();
|
||||
attrs->emplace(attr_name, attr);
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status GetCustomShape(const std::map<std::string, std::string> &attrs, const std::string &attr_name, size_t tensor_num,
|
||||
std::vector<std::vector<int64_t>> *shapes) {
|
||||
if (shapes == nullptr) {
|
||||
MS_LOG(ERROR) << "the function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (attrs.find(attr_name) == attrs.end()) {
|
||||
MS_LOG(ERROR) << "custom node should have " << attr_name << " val.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto attr = attrs.at(attr_name);
|
||||
if (attr.empty()) {
|
||||
MS_LOG(ERROR) << "custom node should have " << attr_name << " val.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto split_shape_str = lite::SplitString(attr, ',');
|
||||
size_t index = 0;
|
||||
for (size_t i = 0; i < split_shape_str.size(); i++) {
|
||||
auto dim_size = std::stoul(split_shape_str.at(i));
|
||||
std::vector<int64_t> shape;
|
||||
for (size_t j = i + 1; j < i + 1 + dim_size; j++) {
|
||||
if (j >= split_shape_str.size()) {
|
||||
MS_LOG(ERROR) << "split_shape_str val is invalid. ";
|
||||
return kLiteError;
|
||||
}
|
||||
shape.push_back(std::stoul(split_shape_str.at(j)));
|
||||
}
|
||||
i += dim_size;
|
||||
if (tensor_num < index) {
|
||||
MS_LOG(ERROR) << "shape index " << index << " is greater than custom tensor_num " << tensor_num;
|
||||
return kLiteError;
|
||||
}
|
||||
shapes->push_back(shape);
|
||||
index++;
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status SetOutputFormat(const std::map<std::string, std::string> &attrs, std::vector<mindspore::MSTensor> *outputs) {
|
||||
if (outputs == nullptr) {
|
||||
MS_LOG(ERROR) << "the function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (attrs.find(kOutputsFormat) == attrs.end()) {
|
||||
MS_LOG(ERROR) << "custom node should have " << kOutputsFormat << " val.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto output_format_str = attrs.at(kOutputsFormat);
|
||||
auto output_format = lite::SplitString(output_format_str, ',');
|
||||
if (output_format.size() > outputs->size()) {
|
||||
MS_LOG(ERROR) << "output format attr is invalid, the number of which is out of range.";
|
||||
return kLiteError;
|
||||
}
|
||||
for (size_t i = 0; i < output_format.size(); ++i) {
|
||||
if (!lite::IsValidUnsignedNum(output_format[i])) {
|
||||
MS_LOG(ERROR) << "output format must be an unsigned int";
|
||||
return kLiteError;
|
||||
}
|
||||
auto format = std::stoi(output_format[i]);
|
||||
if (format != NHWC && format != NCHW) {
|
||||
MS_LOG(ERROR) << "output format is invalid, which should be NHWC or NCHW.";
|
||||
return kLiteError;
|
||||
}
|
||||
outputs->at(i).SetFormat(static_cast<Format>(format));
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
bool InferDone(const std::vector<mindspore::MSTensor> &tensors) {
|
||||
for (auto &tensor : tensors) {
|
||||
auto shape = tensor.Shape();
|
||||
if (std::find(shape.begin(), shape.end(), -1) != shape.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Status CustomInterface::Infer(std::vector<mindspore::MSTensor> *inputs, std::vector<mindspore::MSTensor> *outputs,
|
||||
const schema::Primitive *primitive, const kernel::Kernel *kernel) {
|
||||
auto status = lite::CheckCustomInputOutput(inputs, outputs, primitive);
|
||||
if (status != RET_OK) {
|
||||
MS_LOG(ERROR) << "Check custom input output failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
for (auto &output : *outputs) {
|
||||
output.SetDataType(DataType::kNumberTypeFloat32);
|
||||
output.SetFormat(inputs->front().format());
|
||||
}
|
||||
std::map<std::string, std::string> attrs;
|
||||
if (FetchAttrs(*primitive, &attrs) != kSuccess) {
|
||||
MS_LOG(ERROR) << "fetch attrs from primitive failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (SetOutputFormat(attrs, outputs) != kSuccess) {
|
||||
MS_LOG(ERROR) << "set output format failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (!InferDone(*inputs)) {
|
||||
return kLiteInferInvalid;
|
||||
}
|
||||
std::vector<std::vector<int64_t>> inputs_shape;
|
||||
if (GetCustomShape(attrs, kInputsShape, inputs->size(), &inputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "parser inputs_shape attribute failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
std::vector<std::vector<int64_t>> outputs_shape;
|
||||
if (GetCustomShape(attrs, kOutputsShape, outputs->size(), &outputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "parser outputs_shape attribute failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (inputs_shape.size() != inputs->size() - kOmParameterNum) {
|
||||
MS_LOG(ERROR) << "inputs num:" << (inputs->size() - kOmParameterNum)
|
||||
<< "should be equal to inputs_shape num:" << inputs_shape.size();
|
||||
return kLiteError;
|
||||
}
|
||||
if (inputs_shape[0].size() != (*inputs)[0].Shape().size()) {
|
||||
MS_LOG(ERROR) << "input[0] shape dim size is invalid. " << inputs_shape[0].size()
|
||||
<< "!=" << (*inputs)[0].Shape().size();
|
||||
return kLiteError;
|
||||
}
|
||||
|
||||
lite::AclModelType acl_model_type{lite::AclModelType::kCnn};
|
||||
if (lite::GetAclModelType(primitive, &acl_model_type) != RET_OK) {
|
||||
MS_LOG(ERROR) << "get acl model type failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
|
||||
bool resize_flag = false;
|
||||
int resize_num = 1;
|
||||
for (size_t i = 0; i < inputs_shape[0].size(); i++) {
|
||||
if (inputs_shape[0][i] != (*inputs)[0].Shape()[i]) {
|
||||
if (i == 0) {
|
||||
resize_flag = true;
|
||||
resize_num = (*inputs)[0].Shape()[i];
|
||||
} else {
|
||||
MS_LOG(ERROR) << "Custom of DPICO only support batch_num resize.";
|
||||
return kLiteError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resize_flag) {
|
||||
for (auto &output_shape : outputs_shape) {
|
||||
output_shape[0] = resize_num;
|
||||
if (acl_model_type == lite::AclModelType::kRecurrent) {
|
||||
MS_LOG(INFO) << "only output_0 has the information about time steps.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < outputs->size(); i++) {
|
||||
(*outputs)[i].SetShape(outputs_shape[i]);
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
std::shared_ptr<KernelInterface> CustomInferCreater() {
|
||||
std::shared_ptr<KernelInterface> infer = std::make_shared<CustomInterface>();
|
||||
if (infer == nullptr) {
|
||||
MS_LOG(ERROR) << "make shared failed, infer is nullptr.";
|
||||
return nullptr;
|
||||
}
|
||||
return infer;
|
||||
}
|
||||
} // namespace dpico
|
||||
} // namespace mindspore
|
||||
namespace mindspore {
|
||||
namespace kernel {
|
||||
REGISTER_CUSTOM_KERNEL_INTERFACE(DPICO, DPICO, dpico::CustomInferCreater);
|
||||
} // namespace kernel
|
||||
} // namespace mindspore
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -13,30 +13,25 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MINDSPORE_LITE_NNACL_CUSTOM_PARAMETER_H_
|
||||
#define MINDSPORE_LITE_NNACL_CUSTOM_PARAMETER_H_
|
||||
|
||||
#ifndef DPICO_INFER_CUSTOM_INFER_H_
|
||||
#define DPICO_INFER_CUSTOM_INFER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "include/kernel_interface.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dpico {
|
||||
class CustomInterface : public mindspore::kernel::KernelInterface {
|
||||
class CustomInterface : public kernel::KernelInterface {
|
||||
public:
|
||||
CustomInterface() {}
|
||||
|
||||
~CustomInterface() = default;
|
||||
|
||||
Status Infer(std::vector<mindspore::MSTensor> *inputs, std::vector<mindspore::MSTensor> *outputs,
|
||||
const mindspore::schema::Primitive *primitive, const kernel::Kernel *kernel) override;
|
||||
|
||||
private:
|
||||
Status InferShapeJudge(std::vector<mindspore::MSTensor> *inputs,
|
||||
const std::vector<std::vector<int64_t>> &inputs_shape) const;
|
||||
Status InferRecurrentTwoOutputProcess(const mindspore::schema::Primitive *primitive, const kernel::Kernel *kernel,
|
||||
std::vector<std::vector<int64_t>> *outputs_shape) const;
|
||||
const schema::Primitive *primitive, const kernel::Kernel *kernel) override;
|
||||
};
|
||||
} // namespace dpico
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_LITE_NNACL_CUSTOM_PARAMETER_H_
|
||||
|
||||
#endif // DPICO_INFER_CUSTOM_INFER_H_
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright 2022 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 "manager/acl_context_manager.h"
|
||||
#include <string>
|
||||
#include "include/svp_acl.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "common/check_base.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
AclContextManager::~AclContextManager() {
|
||||
if (acl_rt_stream_ != nullptr) {
|
||||
auto ret = svp_acl_rt_destroy_stream(acl_rt_stream_);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "acl destroy stream failed.");
|
||||
acl_rt_stream_ = nullptr;
|
||||
}
|
||||
if (acl_rt_context_ != nullptr) {
|
||||
auto ret = svp_acl_rt_destroy_context(acl_rt_context_);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "acl destroy context failed.");
|
||||
acl_rt_context_ = nullptr;
|
||||
ret = svp_acl_rt_reset_device(acl_device_id_);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "acl reset device failed.");
|
||||
ret = svp_acl_finalize();
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "finalize acl failed.");
|
||||
}
|
||||
}
|
||||
|
||||
int AclContextManager::Init(const std::string &acl_config_path) {
|
||||
if (acl_rt_context_ != nullptr) {
|
||||
MS_LOG(INFO) << "device only needs to init once.";
|
||||
return RET_OK;
|
||||
}
|
||||
int ret;
|
||||
if (acl_config_path.empty()) {
|
||||
ret = svp_acl_init(nullptr);
|
||||
} else {
|
||||
ret = svp_acl_init(acl_config_path.c_str());
|
||||
}
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl init failed.");
|
||||
ret = svp_acl_rt_set_device(acl_device_id_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl rt set device failed.");
|
||||
ret = svp_acl_rt_create_context(&acl_rt_context_, acl_device_id_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl rt create context failed.");
|
||||
ret = svp_acl_rt_create_stream(&acl_rt_stream_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl rt create stream failed.");
|
||||
svp_acl_rt_run_mode acl_run_mode;
|
||||
ret = svp_acl_rt_get_run_mode(&acl_run_mode);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl rt get run mode failed.");
|
||||
MS_CHECK_TRUE_MSG(acl_run_mode == SVP_ACL_DEVICE, RET_ERROR, "svp acl run mode is invalid.");
|
||||
return RET_OK;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_MANAGER_ACL_CONTEXT_MANAGER_H_
|
||||
#define DPICO_MANAGER_ACL_CONTEXT_MANAGER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "include/svp_acl_base.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
class AclContextManager {
|
||||
public:
|
||||
AclContextManager() = default;
|
||||
~AclContextManager();
|
||||
|
||||
int Init(const std::string &acl_config_path);
|
||||
const svp_acl_rt_context GetAclRuntimeContext() const { return acl_rt_context_; }
|
||||
|
||||
private:
|
||||
/** acl related variables */
|
||||
int32_t acl_device_id_{0};
|
||||
svp_acl_rt_context acl_rt_context_{nullptr};
|
||||
svp_acl_rt_stream acl_rt_stream_{nullptr};
|
||||
};
|
||||
using AclContextManagerPtr = std::shared_ptr<AclContextManager>;
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_MANAGER_ACL_CONTEXT_MANAGER_H_
|
|
@ -0,0 +1,226 @@
|
|||
/**
|
||||
* Copyright 2022 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 "manager/acl_model_helper.h"
|
||||
#include <numeric>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include "include/errorcode.h"
|
||||
#include "common/check_base.h"
|
||||
#include "src/custom_allocator.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/op_attr.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
namespace {
|
||||
constexpr size_t kByteSize = 8; // 1 byte = 8 bits
|
||||
bool Cmp(const std::vector<float> &lhs, const std::vector<float> &rhs) {
|
||||
if (lhs[kClassId] < rhs[kClassId]) {
|
||||
return true;
|
||||
} else if (lhs[kClassId] == rhs[kClassId]) {
|
||||
return lhs[kScore] > rhs[kScore];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
int GetAclModelType(const schema::Primitive *primitive, AclModelType *acl_model_type) {
|
||||
MS_CHECK_TRUE_MSG(primitive != nullptr && acl_model_type != nullptr, RET_ERROR, "input params contain nullptr.");
|
||||
auto op = primitive->value_as_Custom();
|
||||
MS_CHECK_TRUE_MSG(op != nullptr, RET_ERROR, "custom op is nullptr.");
|
||||
auto attrs = op->attr();
|
||||
MS_CHECK_TRUE_MSG(attrs != nullptr && attrs->size() >= 1, RET_ERROR, "custom op attr is invalid.");
|
||||
std::string acl_model_type_str;
|
||||
for (size_t i = 0; i < attrs->size(); i++) {
|
||||
auto attr = attrs->Get(i);
|
||||
MS_CHECK_TRUE_MSG(attr != nullptr && attr->name() != nullptr, RET_ERROR, "invalid attr.");
|
||||
if (attr->name()->str() != kNetType) {
|
||||
continue;
|
||||
}
|
||||
auto data_info = attr->data();
|
||||
MS_CHECK_TRUE_MSG(data_info != nullptr, RET_ERROR, "attr data is nullptr");
|
||||
int data_size = static_cast<int>(data_info->size());
|
||||
for (int j = 0; j < data_size; j++) {
|
||||
acl_model_type_str.push_back(static_cast<char>(data_info->Get(j)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (acl_model_type_str.empty()) {
|
||||
*acl_model_type = AclModelType::kCnn;
|
||||
return RET_OK;
|
||||
}
|
||||
if (!IsValidUnsignedNum(acl_model_type_str)) {
|
||||
MS_LOG(ERROR) << "net_type attr data is invalid num.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
int acl_model_type_val = stoi(acl_model_type_str);
|
||||
if (acl_model_type_val < static_cast<int>(AclModelType::kCnn) ||
|
||||
acl_model_type_val > static_cast<int>(AclModelType::kRecurrent)) {
|
||||
MS_LOG(ERROR) << "net_type val is invalid. " << acl_model_type_val;
|
||||
return RET_ERROR;
|
||||
}
|
||||
*acl_model_type = static_cast<AclModelType>(acl_model_type_val);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int GetAclDataInfo(struct AclDataInfo *acl_data_info, svp_acl_mdl_desc *acl_mdl_desc, int index) {
|
||||
MS_CHECK_TRUE_MSG(acl_data_info != nullptr && acl_mdl_desc != nullptr, RET_ERROR, "input params contain nullptr");
|
||||
int ret;
|
||||
if (acl_data_info->data_mode == AclDataInfo::Input) {
|
||||
ret = svp_acl_mdl_get_input_dims(acl_mdl_desc, index, &(acl_data_info->dim_info));
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl get input dims failed.");
|
||||
acl_data_info->stride = svp_acl_mdl_get_input_default_stride(acl_mdl_desc, index);
|
||||
MS_CHECK_TRUE_MSG(acl_data_info->stride != 0, RET_ERROR, "acl get input default stride failed.");
|
||||
acl_data_info->data_size = svp_acl_mdl_get_input_size_by_index(acl_mdl_desc, index);
|
||||
MS_CHECK_TRUE_MSG(acl_data_info->data_size != 0, RET_ERROR, "acl get input size by index failed.");
|
||||
} else {
|
||||
ret = svp_acl_mdl_get_output_dims(acl_mdl_desc, index, &(acl_data_info->dim_info));
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl get output dims failed.");
|
||||
acl_data_info->stride = svp_acl_mdl_get_output_default_stride(acl_mdl_desc, index);
|
||||
MS_CHECK_TRUE_MSG(acl_data_info->stride != 0, RET_ERROR, "acl get output default stride failed.");
|
||||
acl_data_info->data_size = svp_acl_mdl_get_output_size_by_index(acl_mdl_desc, index);
|
||||
MS_CHECK_TRUE_MSG(acl_data_info->data_size != 0, RET_ERROR, "acl get output size by index failed.");
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AddDatasetBuffer(svp_acl_mdl_dataset *acl_mdl_dataset, size_t data_buffer_size, size_t stride, void *data) {
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "data is nullptr.");
|
||||
auto *data_buffer = svp_acl_create_data_buffer(data, data_buffer_size, stride);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "create data buffer failed.");
|
||||
int ret = svp_acl_mdl_add_dataset_buffer(acl_mdl_dataset, data_buffer);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "add dataset buffer failed.";
|
||||
ret = svp_acl_destroy_data_buffer(data_buffer);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "destroy data buffer failed.");
|
||||
data_buffer = nullptr;
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int DestroyAclDataset(svp_acl_mdl_dataset **acl_mdl_dataset,
|
||||
const std::unordered_map<size_t, bool> &mem_managed_by_tensor, const AllocatorPtr &allocator) {
|
||||
if (*acl_mdl_dataset == nullptr) {
|
||||
MS_LOG(INFO) << "acl_mdl_dataset is nullptr, no need to destroy";
|
||||
return RET_OK;
|
||||
}
|
||||
int ret;
|
||||
auto dataset_buffer_size = svp_acl_mdl_get_dataset_num_buffers(*acl_mdl_dataset);
|
||||
MS_CHECK_TRUE_MSG(dataset_buffer_size == mem_managed_by_tensor.size(), RET_ERROR,
|
||||
"dataset_buffer_size:" << dataset_buffer_size << " is not equal to mem_managed_by_tensor.size():"
|
||||
<< mem_managed_by_tensor.size());
|
||||
for (size_t i = 0; i < dataset_buffer_size; i++) {
|
||||
MS_CHECK_TRUE_MSG(mem_managed_by_tensor.find(i) != mem_managed_by_tensor.end(), RET_ERROR,
|
||||
"invalid dataset buffer index");
|
||||
svp_acl_data_buffer *acl_data_buffer = svp_acl_mdl_get_dataset_buffer(*acl_mdl_dataset, i);
|
||||
MS_CHECK_TRUE_MSG(acl_data_buffer != nullptr, RET_ERROR, "get acl data buffer failed.");
|
||||
if (!mem_managed_by_tensor.at(i)) {
|
||||
void *tmp = svp_acl_get_data_buffer_addr(acl_data_buffer);
|
||||
allocator->Free(tmp);
|
||||
}
|
||||
ret = svp_acl_destroy_data_buffer(acl_data_buffer);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl destroy data buffer failed.");
|
||||
acl_data_buffer = nullptr;
|
||||
}
|
||||
ret = svp_acl_mdl_destroy_dataset(*acl_mdl_dataset);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl destroy dataset failed.");
|
||||
*acl_mdl_dataset = nullptr;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
size_t GetDataTypeSize(svp_acl_mdl_desc *acl_mdl_desc, size_t index, AclDataInfo::DataMode data_mode) {
|
||||
svp_acl_data_type data_type;
|
||||
if (data_mode == AclDataInfo::Input) {
|
||||
data_type = svp_acl_mdl_get_input_data_type(acl_mdl_desc, index);
|
||||
} else {
|
||||
data_type = svp_acl_mdl_get_output_data_type(acl_mdl_desc, index);
|
||||
}
|
||||
return svp_acl_data_type_size(data_type) / kByteSize;
|
||||
}
|
||||
|
||||
int ComputeValidDetectBoxes(svp_acl_mdl_desc *acl_mdl_desc, svp_acl_mdl_dataset *acl_outputs,
|
||||
std::vector<std::vector<float>> *det_boxes) {
|
||||
MS_CHECK_TRUE_MSG(acl_mdl_desc != nullptr && acl_outputs != nullptr && det_boxes != nullptr, RET_ERROR,
|
||||
"input params contain nullptr.");
|
||||
// yolo/ssd output 0 is num, output 1 is bbox
|
||||
enum InputOutputId { kInputImgId = 0, kOutputNumId = 0, kOutputBboxId = 1 };
|
||||
// get valid box number
|
||||
svp_acl_mdl_io_dims acl_dims;
|
||||
std::vector<int> valid_box_num;
|
||||
int ret = svp_acl_mdl_get_output_dims(acl_mdl_desc, kOutputNumId, &acl_dims);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS && acl_dims.dim_count >= 1, RET_ERROR, "svp get output dims failed.");
|
||||
svp_acl_data_buffer *data_buffer = svp_acl_mdl_get_dataset_buffer(acl_outputs, kOutputNumId);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "get data buffer failed.");
|
||||
auto output_data = reinterpret_cast<float *>(svp_acl_get_data_buffer_addr(data_buffer));
|
||||
MS_CHECK_TRUE_MSG(output_data != nullptr, RET_ERROR, "data is nullptr.");
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(acl_dims.dims[acl_dims.dim_count - 1]); i++) {
|
||||
valid_box_num.push_back(*(output_data + i));
|
||||
}
|
||||
int total_valid_num = std::accumulate(valid_box_num.begin(), valid_box_num.end(), 0);
|
||||
if (total_valid_num == 0) {
|
||||
MS_LOG(INFO) << "total valid num is zero";
|
||||
return RET_OK;
|
||||
}
|
||||
// get x y score
|
||||
data_buffer = svp_acl_mdl_get_dataset_buffer(acl_outputs, kOutputBboxId);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "get data buffer failed.");
|
||||
output_data = reinterpret_cast<float *>(svp_acl_get_data_buffer_addr(data_buffer));
|
||||
svp_acl_mdl_get_output_dims(acl_mdl_desc, kOutputBboxId, &acl_dims);
|
||||
size_t w_stride_offset = svp_acl_mdl_get_output_default_stride(acl_mdl_desc, kOutputBboxId) / sizeof(float);
|
||||
|
||||
// box param include 6 part which is lx, ly, rx, ry, score, class id
|
||||
auto bbox_pararm_size = DetectBoxParam::kDetectBoxParamEnd - DetectBoxParam::kDetectBoxParamBegin;
|
||||
std::vector<float> bbox(bbox_pararm_size, 0.0f);
|
||||
for (int idx = 0; idx < total_valid_num; idx++) {
|
||||
float class_id = *(output_data + idx + kClassId * w_stride_offset);
|
||||
if (std::fabs(class_id) <= std::numeric_limits<float>::epsilon()) {
|
||||
continue; // skip class 0 back ground
|
||||
}
|
||||
for (size_t i = 0; i < bbox_pararm_size; i++) {
|
||||
bbox[i] = (*(output_data + idx + i * w_stride_offset));
|
||||
}
|
||||
det_boxes->push_back(bbox);
|
||||
}
|
||||
std::sort(det_boxes->begin(), det_boxes->end(), Cmp);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int WriteDetBoxesToTensorData(const std::vector<std::vector<float>> &det_boxes,
|
||||
mindspore::MSTensor *detect_boxes_tensor) {
|
||||
size_t total_box_num = det_boxes.size();
|
||||
auto bbox_pararm_size = DetectBoxParam::kDetectBoxParamEnd - DetectBoxParam::kDetectBoxParamBegin;
|
||||
MS_CHECK_TRUE_MSG(static_cast<size_t>(detect_boxes_tensor->ElementNum()) >= total_box_num * bbox_pararm_size,
|
||||
RET_ERROR, "detect box tensor element num is too few");
|
||||
auto *bbox_tensor_data = reinterpret_cast<float *>(detect_boxes_tensor->MutableData());
|
||||
MS_CHECK_TRUE_MSG(bbox_tensor_data != nullptr, RET_ERROR, "bbox_tensor_data is nullptr");
|
||||
for (size_t i = 0; i < total_box_num; i++) {
|
||||
for (size_t bbox_param_idx = 0; bbox_param_idx < bbox_pararm_size; bbox_param_idx++) {
|
||||
bbox_tensor_data[bbox_param_idx * total_box_num + i] = det_boxes[i][bbox_param_idx];
|
||||
}
|
||||
}
|
||||
detect_boxes_tensor->SetShape({1, static_cast<int64_t>(total_box_num * bbox_pararm_size)});
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclMalloc(void **buf, size_t size) {
|
||||
int ret = svp_acl_rt_malloc(buf, size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
return ret;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_MANAGER_ACL_MODEL_HELPER_H_
|
||||
#define DPICO_MANAGER_ACL_MODEL_HELPER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "include/svp_acl_mdl.h"
|
||||
#include "include/api/types.h"
|
||||
#include "include/lite_utils.h"
|
||||
#include "include/schema/model_generated.h"
|
||||
#include "common/custom_enum.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
struct AclDataInfo {
|
||||
enum DataMode { Input = 0, Output = 1 };
|
||||
DataMode data_mode{Input};
|
||||
size_t stride{0};
|
||||
size_t data_size{0};
|
||||
svp_acl_mdl_io_dims dim_info{};
|
||||
explicit AclDataInfo(DataMode input_mode) : data_mode(input_mode) {}
|
||||
};
|
||||
int GetAclModelType(const schema::Primitive *primitive, AclModelType *acl_model_type);
|
||||
int GetAclDataInfo(struct AclDataInfo *acl_data_info, svp_acl_mdl_desc *acl_mdl_desc, int index);
|
||||
int AddDatasetBuffer(svp_acl_mdl_dataset *acl_mdl_dataset, size_t data_buffer_size, size_t stride, void *data);
|
||||
int DestroyAclDataset(svp_acl_mdl_dataset **acl_mdl_dataset,
|
||||
const std::unordered_map<size_t, bool> &mem_managed_by_tensor, const AllocatorPtr &allocator_ptr);
|
||||
size_t GetDataTypeSize(svp_acl_mdl_desc *acl_mdl_desc, size_t index, AclDataInfo::DataMode data_mode);
|
||||
int ComputeValidDetectBoxes(svp_acl_mdl_desc *acl_mdl_desc, svp_acl_mdl_dataset *acl_outputs,
|
||||
std::vector<std::vector<float>> *boxes);
|
||||
int WriteDetBoxesToTensorData(const std::vector<std::vector<float>> &det_boxes,
|
||||
mindspore::MSTensor *detect_boxes_tensor);
|
||||
|
||||
int AclMalloc(void **buf, size_t size);
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_MANAGER_ACL_MODEL_HELPER_H_
|
|
@ -0,0 +1,495 @@
|
|||
/**
|
||||
* Copyright 2022 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 "manager/acl_model_manager.h"
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "include/errorcode.h"
|
||||
#include "common/check_base.h"
|
||||
#include "src/custom_allocator.h"
|
||||
#include "manager/acl_model_helper.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
AllocatorPtr AclModelManager::custom_allocator_ = std::make_shared<CustomAllocator>();
|
||||
CustomConfigManagerPtr AclModelManager::custom_config_manager_ptr_ = std::make_shared<CustomConfigManager>();
|
||||
AclContextManagerPtr AclModelManager::acl_context_manager_ = std::make_shared<AclContextManager>();
|
||||
namespace {
|
||||
constexpr size_t kNumOfInputOm = 1; // om parameter is the last input of MS Input tensor
|
||||
constexpr size_t kMinAclInputSize = 2; // {work_buf, task_buf}
|
||||
constexpr size_t kDetectParamNum = 4; // {nms_threshold, score_threshold,min_height,min_width}
|
||||
} // namespace
|
||||
AclModelManager::~AclModelManager() {
|
||||
int ret = UnloadModel();
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == RET_OK, "unload acl model failed.");
|
||||
ret = DestroyAclDataset(&acl_inputs_, inputs_mem_managed_by_tensor, custom_allocator_);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == RET_OK, "destroy acl inputs failed.");
|
||||
ret = DestroyAclDataset(&acl_outputs_, outputs_mem_managed_by_tensor, custom_allocator_);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == RET_OK, "destroy acl outputs failed.");
|
||||
inputs_mem_managed_by_tensor.clear();
|
||||
outputs_mem_managed_by_tensor.clear();
|
||||
}
|
||||
|
||||
int AclModelManager::LoadModel(const std::vector<mindspore::MSTensor> &input_tensors) {
|
||||
MS_CHECK_TRUE_MSG(!input_tensors.empty(), RET_ERROR, "input tensors is empty.");
|
||||
MS_CHECK_TRUE_MSG(acl_model_ptr_ == nullptr, RET_ERROR, "acl model ptr has been allocated.");
|
||||
auto acl_model_tensor = input_tensors[input_tensors.size() - kNumOfInputOm];
|
||||
auto model_mem_ptr = acl_model_tensor.MutableData();
|
||||
MS_CHECK_TRUE_MSG(model_mem_ptr != nullptr, RET_ERROR, "model_mem_ptr is nullptr.");
|
||||
int ret = AclMalloc(&acl_model_ptr_, acl_model_tensor.DataSize());
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "svp acl rt malloc model buffer failed.");
|
||||
memcpy(acl_model_ptr_, model_mem_ptr, acl_model_tensor.DataSize());
|
||||
ret = svp_acl_mdl_load_from_mem(acl_model_ptr_, acl_model_tensor.DataSize(), &acl_model_id_);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "svp acl mdl load from mem failed.";
|
||||
custom_allocator_->Free(acl_model_ptr_);
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::CreateModelDesc() {
|
||||
MS_CHECK_TRUE_MSG(acl_model_desc_ == nullptr, RET_ERROR, "model_desc has been created.");
|
||||
acl_model_desc_ = svp_acl_mdl_create_desc();
|
||||
MS_CHECK_TRUE_MSG(acl_model_desc_ != nullptr, RET_ERROR, "create model desc failed.");
|
||||
int ret = svp_acl_mdl_get_desc(acl_model_desc_, acl_model_id_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "get model desc failed.");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::SetDetectParams(void *data) {
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "detect param data is nullptr");
|
||||
auto param = reinterpret_cast<float *>(data);
|
||||
param[kNmsThreshold] = custom_config_manager_ptr_->NmsThreshold();
|
||||
param[kScoreThreshold] = custom_config_manager_ptr_->ScoreThreshold();
|
||||
param[kMinHeight] = custom_config_manager_ptr_->MinHeight();
|
||||
param[kMinWidth] = custom_config_manager_ptr_->MinWidth();
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::AddDetectParamInput() {
|
||||
void *data = nullptr;
|
||||
int ret = AclMalloc(&data, sizeof(float) * kDetectParamNum);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "svp acl rt malloc detect input buffer failed.");
|
||||
ret = SetDetectParams(data);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "set detect params failed.");
|
||||
AclDataInfo acl_data_info(AclDataInfo::Input);
|
||||
acl_data_info.data_size = sizeof(float) * kDetectParamNum;
|
||||
acl_data_info.stride = sizeof(float) * kDetectParamNum;
|
||||
ret = AddDatasetBuffer(acl_inputs_, acl_data_info.data_size, acl_data_info.stride, data);
|
||||
if (ret != RET_OK) {
|
||||
MS_LOG(ERROR) << "add dataset buffer failed.";
|
||||
custom_allocator_->Free(data);
|
||||
return RET_ERROR;
|
||||
}
|
||||
size_t cur_num_buffers = svp_acl_mdl_get_dataset_num_buffers(acl_inputs_);
|
||||
MS_CHECK_TRUE_MSG(cur_num_buffers - 1 == inputs_mem_managed_by_tensor.size(), RET_ERROR,
|
||||
"detect param index is invalid");
|
||||
inputs_mem_managed_by_tensor[cur_num_buffers - 1] = false;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::DetectPostProcess(mindspore::MSTensor *detect_output_tensor) {
|
||||
MS_CHECK_TRUE_MSG(detect_output_tensor != nullptr, RET_ERROR, "detect_output_tensor is nullptr.");
|
||||
std::vector<std::vector<float>> valid_det_boxes;
|
||||
int ret = ComputeValidDetectBoxes(acl_model_desc_, acl_outputs_, &valid_det_boxes);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "compute valid detect boxes failed.");
|
||||
ret = WriteDetBoxesToTensorData(valid_det_boxes, detect_output_tensor);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "write det boxes to detect output tensor data failed.");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::CreateTaskBufAndWorkBuf() {
|
||||
size_t input_size = svp_acl_mdl_get_num_inputs(acl_model_desc_);
|
||||
MS_CHECK_TRUE_MSG(input_size > kMinAclInputSize, RET_ERROR,
|
||||
"acl model input size should be greater than " << kMinAclInputSize);
|
||||
size_t cur_num_buffers = svp_acl_mdl_get_dataset_num_buffers(acl_inputs_);
|
||||
MS_CHECK_TRUE_MSG(cur_num_buffers > 0, RET_ERROR, "acl model input size should be greater than 0");
|
||||
for (size_t i = cur_num_buffers; i < input_size; i++) {
|
||||
void *data = nullptr;
|
||||
AclDataInfo acl_data_info(AclDataInfo::Input);
|
||||
int ret = GetAclDataInfo(&acl_data_info, acl_model_desc_, i);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "get acl data info failed.");
|
||||
ret = AclMalloc(&data, acl_data_info.data_size);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "svp acl rt malloc task and work buf failed.");
|
||||
ret = AddDatasetBuffer(acl_inputs_, acl_data_info.data_size, acl_data_info.stride, data);
|
||||
if (ret != RET_OK) {
|
||||
MS_LOG(ERROR) << "add dataset buffer failed.";
|
||||
custom_allocator_->Free(data);
|
||||
return RET_ERROR;
|
||||
}
|
||||
inputs_mem_managed_by_tensor[i] = false;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::CopyTensorDataToAclInputs(const std::vector<mindspore::MSTensor> &input_tensors) {
|
||||
for (size_t i = 0; i < input_tensors.size() - kNumOfInputOm; i++) {
|
||||
MS_CHECK_TRUE_MSG(inputs_mem_managed_by_tensor.find(i) != inputs_mem_managed_by_tensor.end(), RET_ERROR,
|
||||
"invalid input index");
|
||||
if (inputs_mem_managed_by_tensor[i]) {
|
||||
MS_LOG(INFO) << "input tensor data is managed by tensor already, no need to copy";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto input_tensor = input_tensors.at(i);
|
||||
AclDataInfo acl_data_info{AclDataInfo::Input};
|
||||
int ret = GetAclDataInfo(&acl_data_info, acl_model_desc_, i);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "get acl data info failed.");
|
||||
auto *input_tensor_data = input_tensor.MutableData();
|
||||
MS_CHECK_TRUE_MSG(input_tensor_data != nullptr, RET_ERROR, "input tensor data is nullptr.");
|
||||
|
||||
MS_CHECK_TRUE_MSG(!input_tensor.Shape().empty(), RET_ERROR, "input tensor shape is empty");
|
||||
size_t input_tensor_last_dim = input_tensor.Shape().back();
|
||||
size_t type_size = GetDataTypeSize(acl_model_desc_, i, acl_data_info.data_mode);
|
||||
auto input_tensor_stride = input_tensor_last_dim * type_size;
|
||||
|
||||
auto *acl_data_buffer = svp_acl_mdl_get_dataset_buffer(acl_inputs_, i);
|
||||
MS_CHECK_TRUE_MSG(acl_data_buffer != nullptr, RET_ERROR, "get acl data buffer failed.");
|
||||
auto *acl_data = svp_acl_get_data_buffer_addr(acl_data_buffer);
|
||||
MS_CHECK_TRUE_MSG(acl_data != nullptr, RET_ERROR, "acl data is nullptr.");
|
||||
|
||||
MS_CHECK_TRUE_MSG(acl_data_info.stride != 0, RET_ERROR, "acl stride cannot be 0");
|
||||
int64_t loop_times = acl_data_info.data_size * actual_batch_size_ / acl_data_info.stride;
|
||||
if (acl_model_type_ == AclModelType::kRecurrent) {
|
||||
if (i == 0) { // e.g: tensor shape is (3, 1, 29), acl dims is (1, 1, 1024)
|
||||
loop_times = loop_times / acl_data_info.dim_info.dims[0] * custom_config_manager_ptr_->GTotalT();
|
||||
} else if (i == 1) { // e.g: tensor shape is (3, 1, 1), acl dims is (1024, 1, 1)
|
||||
input_tensor_stride = custom_config_manager_ptr_->GTotalT() * type_size;
|
||||
}
|
||||
}
|
||||
|
||||
// copy tensor data to acl inputs with the last dim(bytes) as a unit
|
||||
for (int64_t loop = 0; loop < loop_times; loop++) {
|
||||
memcpy(reinterpret_cast<uint8_t *>(acl_data) + loop * acl_data_info.stride,
|
||||
reinterpret_cast<uint8_t *>(input_tensor_data) + loop * input_tensor_stride, input_tensor_stride);
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::CopyAclOutputsToTensorData(const std::vector<mindspore::MSTensor> &output_tensors) {
|
||||
for (size_t i = 0; i < output_tensors.size(); i++) {
|
||||
MS_CHECK_TRUE_MSG(outputs_mem_managed_by_tensor.find(i) != outputs_mem_managed_by_tensor.end(), RET_ERROR,
|
||||
"invalid output index");
|
||||
if (i == 1 && custom_config_manager_ptr_->NeedDetectPostProcess() && acl_model_type_ == kRoi) {
|
||||
constexpr size_t kMinDetectOutputSize = 2;
|
||||
MS_CHECK_TRUE_MSG(output_tensors.size() >= kMinDetectOutputSize, RET_ERROR,
|
||||
"detection net output size shouldn't be less than " << kMinDetectOutputSize);
|
||||
auto detect_boxes_tensor = output_tensors.at(i);
|
||||
int ret = DetectPostProcess(&detect_boxes_tensor);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "detect net post process failed.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outputs_mem_managed_by_tensor[i]) {
|
||||
MS_LOG(INFO) << "output tensor data is managed by tensor already, no need to copy";
|
||||
continue;
|
||||
}
|
||||
auto output_tensor = output_tensors.at(i);
|
||||
AclDataInfo acl_data_info{AclDataInfo::Output};
|
||||
int ret = GetAclDataInfo(&acl_data_info, acl_model_desc_, i);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "get acl data info failed.");
|
||||
auto *output_tensor_data = output_tensor.MutableData();
|
||||
MS_CHECK_TRUE_MSG(output_tensor_data != nullptr, RET_ERROR, "output tensor data is nullptr.");
|
||||
|
||||
MS_CHECK_TRUE_MSG(!output_tensor.Shape().empty(), RET_ERROR, "output tensor shape is empty");
|
||||
size_t output_tensor_last_dim = output_tensor.Shape().back();
|
||||
size_t type_size = GetDataTypeSize(acl_model_desc_, i, acl_data_info.data_mode);
|
||||
auto output_tensor_stride = output_tensor_last_dim * type_size;
|
||||
|
||||
auto *acl_data_buffer = svp_acl_mdl_get_dataset_buffer(acl_outputs_, i);
|
||||
MS_CHECK_TRUE_MSG(acl_data_buffer != nullptr, RET_ERROR, "get acl data buffer failed.");
|
||||
auto *acl_data = svp_acl_get_data_buffer_addr(acl_data_buffer);
|
||||
MS_CHECK_TRUE_MSG(acl_data != nullptr, RET_ERROR, "acl data is nullptr.");
|
||||
|
||||
MS_CHECK_TRUE_MSG(acl_data_info.stride != 0, RET_ERROR, "acl stride cannot be 0");
|
||||
int64_t loop_times = acl_data_info.data_size * actual_batch_size_ / acl_data_info.stride;
|
||||
if (acl_model_type_ == AclModelType::kRecurrent && i == 0) { // RNN input_0's dims[0] isn't equal to gTotalT
|
||||
loop_times = loop_times / acl_data_info.dim_info.dims[0] * custom_config_manager_ptr_->GTotalT();
|
||||
}
|
||||
for (int64_t loop = 0; loop < loop_times; loop++) {
|
||||
memcpy(reinterpret_cast<uint8_t *>(output_tensor_data) + loop * output_tensor_stride,
|
||||
reinterpret_cast<uint8_t *>(acl_data) + loop * acl_data_info.stride, output_tensor_stride);
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::FlushAclInputsAndOutputs() {
|
||||
// flush acl inputs
|
||||
auto dataset_buffer_size = svp_acl_mdl_get_dataset_num_buffers(acl_inputs_);
|
||||
for (size_t i = 0; i < dataset_buffer_size; i++) {
|
||||
if (!inputs_mem_managed_by_tensor[i]) {
|
||||
continue;
|
||||
}
|
||||
auto *acl_data_buffer = svp_acl_mdl_get_dataset_buffer(acl_inputs_, i);
|
||||
MS_CHECK_TRUE_MSG(acl_data_buffer != nullptr, RET_ERROR, "get acl data buffer failed.");
|
||||
auto input_size = svp_acl_get_data_buffer_size(acl_data_buffer);
|
||||
void *data = svp_acl_get_data_buffer_addr(acl_data_buffer);
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "acl data is nullptr");
|
||||
auto ret = svp_acl_rt_mem_flush(data, input_size);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "flush input tensor failed.");
|
||||
}
|
||||
|
||||
// flush acl outputs
|
||||
dataset_buffer_size = svp_acl_mdl_get_dataset_num_buffers(acl_outputs_);
|
||||
for (size_t i = 0; i < dataset_buffer_size; i++) {
|
||||
if (!outputs_mem_managed_by_tensor[i]) {
|
||||
continue;
|
||||
}
|
||||
auto *acl_data_buffer = svp_acl_mdl_get_dataset_buffer(acl_outputs_, i);
|
||||
MS_CHECK_TRUE_MSG(acl_data_buffer != nullptr, RET_ERROR, "get acl data buffer failed.");
|
||||
auto output_size = svp_acl_get_data_buffer_size(acl_data_buffer);
|
||||
void *data = svp_acl_get_data_buffer_addr(acl_data_buffer);
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "acl data is nullptr");
|
||||
auto ret = svp_acl_rt_mem_invalidate(data, output_size);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "invalidate input tensor failed.");
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::AclModelRun(const std::vector<mindspore::MSTensor> &input_tensors) {
|
||||
int ret;
|
||||
if (acl_model_type_ != AclModelType::kRecurrent) {
|
||||
size_t index;
|
||||
ret = svp_acl_mdl_get_input_index_by_name(acl_model_desc_, SVP_ACL_DYNAMIC_TENSOR_NAME, &index);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl get input index by name failed.");
|
||||
|
||||
ret = svp_acl_mdl_set_dynamic_batch_size(acl_model_id_, acl_inputs_, index, actual_batch_size_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl set dynamic batch size failed.");
|
||||
} else {
|
||||
ret = svp_acl_mdl_set_total_t(acl_model_id_, acl_inputs_, custom_config_manager_ptr_->GTotalT());
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl set total t failed.");
|
||||
}
|
||||
ret = svp_acl_rt_set_current_context(acl_context_manager_->GetAclRuntimeContext());
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "acl set current context failed.");
|
||||
|
||||
ret = svp_acl_mdl_execute(acl_model_id_, acl_inputs_, acl_outputs_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl execute failed.");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::UnloadModel() {
|
||||
int ret = svp_acl_mdl_unload(acl_model_id_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl unload model failed");
|
||||
if (acl_model_desc_ != nullptr) {
|
||||
ret = svp_acl_mdl_destroy_desc(acl_model_desc_);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp acl destroy model desc failed.");
|
||||
acl_model_desc_ = nullptr;
|
||||
}
|
||||
if (acl_model_ptr_ != nullptr) {
|
||||
custom_allocator_->Free(acl_model_ptr_);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::Init(const std::map<std::string, std::string> &dpico_config, const schema::Primitive *primitive,
|
||||
const std::vector<mindspore::MSTensor> &input_tensors,
|
||||
const std::vector<mindspore::MSTensor> &output_tensors) {
|
||||
MS_CHECK_TRUE_MSG(acl_context_manager_ != nullptr, RET_ERROR, "acl_context_manager_ is nullptr.");
|
||||
MS_CHECK_TRUE_MSG(custom_config_manager_ptr_ != nullptr, RET_ERROR, "custom_config_manager_ptr_ is nullptr.");
|
||||
if (custom_config_manager_ptr_->Init(dpico_config) != RET_OK) {
|
||||
MS_LOG(ERROR) << "custom config manager init failed";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (acl_context_manager_->Init(custom_config_manager_ptr_->AclConfigFile()) != RET_OK) {
|
||||
MS_LOG(ERROR) << "acl context manager init failed.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (GetAclModelType(primitive, &acl_model_type_) != RET_OK) {
|
||||
MS_LOG(ERROR) << "get acl model type failed.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (LoadModel(input_tensors) != RET_OK) {
|
||||
MS_LOG(ERROR) << "load acl model failed.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (CreateModelDesc() != RET_OK) {
|
||||
MS_LOG(ERROR) << "create model desc failed.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::UpdateBatchSize(const std::vector<mindspore::MSTensor> &input_tensors) {
|
||||
auto input_tensor = input_tensors.front();
|
||||
auto input_shape = input_tensor.Shape();
|
||||
if (input_shape.empty()) {
|
||||
MS_LOG(ERROR) << "input shape is empty. " << input_tensor.Name();
|
||||
return RET_ERROR;
|
||||
}
|
||||
auto new_batch = static_cast<size_t>(input_shape.front());
|
||||
if (acl_model_type_ == AclModelType::kRecurrent) {
|
||||
custom_config_manager_ptr_->SetGTotalT(new_batch);
|
||||
} else {
|
||||
actual_batch_size_ = new_batch;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::PrepareAclInputs(std::vector<mindspore::MSTensor> *input_tensors) {
|
||||
MS_CHECK_TRUE_MSG(acl_model_desc_ != nullptr, RET_ERROR, "acl model desc is nullptr.");
|
||||
MS_CHECK_TRUE_MSG(custom_allocator_ != nullptr, RET_ERROR, "custom allocator is nullptr.");
|
||||
MS_CHECK_TRUE_MSG(input_tensors != nullptr, RET_ERROR, "input_tensors is nullptr.");
|
||||
int ret;
|
||||
if (acl_inputs_ != nullptr) {
|
||||
ret = DestroyAclDataset(&acl_inputs_, inputs_mem_managed_by_tensor, custom_allocator_);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "destroy acl input dataset failed.");
|
||||
inputs_mem_managed_by_tensor.clear();
|
||||
}
|
||||
acl_inputs_ = svp_acl_mdl_create_dataset();
|
||||
MS_CHECK_TRUE_MSG(acl_inputs_ != nullptr, RET_ERROR, "create acl model input dataset failed.");
|
||||
for (size_t i = 0; i < input_tensors->size() - kNumOfInputOm; i++) {
|
||||
AclDataInfo acl_data_info(AclDataInfo::Input);
|
||||
ret = GetAclDataInfo(&acl_data_info, acl_model_desc_, i);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "get acl data info failed.");
|
||||
void *data = nullptr;
|
||||
if (acl_data_info.data_size * actual_batch_size_ != input_tensors->at(i).DataSize()) {
|
||||
inputs_mem_managed_by_tensor[i] = false;
|
||||
ret = AclMalloc(&data, acl_data_info.data_size * actual_batch_size_);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "svp acl rt malloc acl input buffer failed.");
|
||||
} else {
|
||||
inputs_mem_managed_by_tensor[i] = true;
|
||||
input_tensors->at(i).SetAllocator(custom_allocator_);
|
||||
data = input_tensors->at(i).MutableData(); // svp malloc memory for ms tensor
|
||||
}
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "get data ptr failed.");
|
||||
ret = AddDatasetBuffer(acl_inputs_, acl_data_info.data_size * actual_batch_size_, acl_data_info.stride, data);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "add dataset buffer failed.");
|
||||
}
|
||||
if (acl_model_type_ == AclModelType::kRoi) {
|
||||
ret = AddDetectParamInput();
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "add detect param input failed.");
|
||||
}
|
||||
ret = CreateTaskBufAndWorkBuf();
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "create task buf and work buf failed.");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::PrepareAclOutputs(std::vector<mindspore::MSTensor> *output_tensors) {
|
||||
MS_CHECK_TRUE_MSG(acl_model_desc_ != nullptr, RET_ERROR, "acl model desc is nullptr.");
|
||||
MS_CHECK_TRUE_MSG(custom_allocator_ != nullptr, RET_ERROR, "custom allocator is nullptr.");
|
||||
MS_CHECK_TRUE_MSG(output_tensors != nullptr, RET_ERROR, "output_tensors is nullptr.");
|
||||
int ret;
|
||||
if (acl_outputs_ != nullptr) {
|
||||
ret = DestroyAclDataset(&acl_outputs_, outputs_mem_managed_by_tensor, custom_allocator_);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "destroy acl output dataset failed.");
|
||||
outputs_mem_managed_by_tensor.clear();
|
||||
}
|
||||
acl_outputs_ = svp_acl_mdl_create_dataset();
|
||||
MS_CHECK_TRUE_MSG(acl_outputs_ != nullptr, RET_ERROR, "create acl model output dataset failed.");
|
||||
size_t output_size = svp_acl_mdl_get_num_outputs(acl_model_desc_);
|
||||
MS_CHECK_TRUE_MSG(output_size == output_tensors->size(), RET_ERROR,
|
||||
"acl output size should be equal to ms output tensor size");
|
||||
for (size_t i = 0; i < output_size; i++) {
|
||||
AclDataInfo acl_data_info(AclDataInfo::Output);
|
||||
ret = GetAclDataInfo(&acl_data_info, acl_model_desc_, i);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "get acl data info failed.");
|
||||
void *data = nullptr;
|
||||
if (acl_data_info.data_size * actual_batch_size_ != output_tensors->at(i).DataSize()) {
|
||||
outputs_mem_managed_by_tensor[i] = false;
|
||||
ret = AclMalloc(&data, acl_data_info.data_size * actual_batch_size_);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "svp acl rt malloc acl output buffer failed.");
|
||||
} else {
|
||||
outputs_mem_managed_by_tensor[i] = true;
|
||||
output_tensors->at(i).SetAllocator(custom_allocator_);
|
||||
data = output_tensors->at(i).MutableData(); // svp malloc memory for ms tensor
|
||||
}
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "get data ptr failed.");
|
||||
ret = AddDatasetBuffer(acl_outputs_, acl_data_info.data_size * actual_batch_size_, acl_data_info.stride, data);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "add dataset buffer failed.");
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::UpdateKernelConfig(const std::map<std::string, std::string> &dpico_config) {
|
||||
int ret = custom_config_manager_ptr_->UpdateConfig(dpico_config);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "update custom config success");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::UpdateAclInputs(std::vector<mindspore::MSTensor> *input_tensors) {
|
||||
MS_CHECK_TRUE_MSG(input_tensors != nullptr, RET_ERROR, "input_tensors is nullptr.");
|
||||
for (size_t i = 0; i < input_tensors->size() - kNumOfInputOm; i++) {
|
||||
MS_CHECK_TRUE_MSG(inputs_mem_managed_by_tensor.find(i) != inputs_mem_managed_by_tensor.end(), RET_ERROR,
|
||||
"invalid input index: " << i);
|
||||
auto input_tensor = input_tensors->at(i);
|
||||
if (!inputs_mem_managed_by_tensor[i]) {
|
||||
MS_LOG(INFO)
|
||||
<< "input data isn't managed by tensor, which hasn't been freed, no need to update input tensor addr. "
|
||||
<< input_tensor.Name();
|
||||
continue;
|
||||
}
|
||||
auto data_buffer = svp_acl_mdl_get_dataset_buffer(acl_inputs_, i);
|
||||
svp_acl_get_data_buffer_size(data_buffer);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "data_buffer is nullptr.");
|
||||
auto stride = svp_acl_mdl_get_input_default_stride(acl_model_desc_, i);
|
||||
auto ret = svp_acl_update_data_buffer(data_buffer, input_tensors->at(i).MutableData(),
|
||||
input_tensors->at(i).DataSize(), stride);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp update data buffer failed. " << input_tensor.Name());
|
||||
}
|
||||
|
||||
if (acl_model_type_ == AclModelType::kRoi) {
|
||||
size_t detect_param_index = input_tensors->size();
|
||||
auto data_buffer = svp_acl_mdl_get_dataset_buffer(acl_inputs_, detect_param_index);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "data_buffer is nullptr.");
|
||||
void *data = svp_acl_get_data_buffer_addr(data_buffer);
|
||||
MS_CHECK_TRUE_MSG(data != nullptr, RET_ERROR, "detect param data is nullptr.");
|
||||
auto ret = SetDetectParams(data);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "set detect params failed.");
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::UpdateAclOutputs(std::vector<mindspore::MSTensor> *output_tensors) {
|
||||
MS_CHECK_TRUE_MSG(output_tensors != nullptr, RET_ERROR, "output_tensors is nullptr.");
|
||||
for (size_t i = 0; i < output_tensors->size(); i++) {
|
||||
MS_CHECK_TRUE_MSG(outputs_mem_managed_by_tensor.find(i) != outputs_mem_managed_by_tensor.end(), RET_ERROR,
|
||||
"invalid output index: " << i);
|
||||
auto output_tensor = output_tensors->at(i);
|
||||
if (!outputs_mem_managed_by_tensor[i]) {
|
||||
MS_LOG(INFO)
|
||||
<< "output data isn't managed by tensor, which hasn't been freed, no need to update output tensor addr. "
|
||||
<< output_tensor.Name();
|
||||
continue;
|
||||
}
|
||||
auto data_buffer = svp_acl_mdl_get_dataset_buffer(acl_outputs_, i);
|
||||
MS_CHECK_TRUE_MSG(data_buffer != nullptr, RET_ERROR, "data_buffer is nullptr.");
|
||||
auto stride = svp_acl_mdl_get_output_default_stride(acl_model_desc_, i);
|
||||
auto ret = svp_acl_update_data_buffer(data_buffer, output_tensor.MutableData(), output_tensor.DataSize(), stride);
|
||||
MS_CHECK_TRUE_MSG(ret == SVP_ACL_SUCCESS, RET_ERROR, "svp update data buffer failed. " << output_tensor.Name());
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int AclModelManager::Execute(const std::vector<mindspore::MSTensor> &input_tensors,
|
||||
const std::vector<mindspore::MSTensor> &output_tensors) {
|
||||
int ret = CopyTensorDataToAclInputs(input_tensors);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "copy input tensor data to acl inputs failed.");
|
||||
|
||||
ret = FlushAclInputsAndOutputs();
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "flush input and output tensor data failed.");
|
||||
|
||||
ret = AclModelRun(input_tensors);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "acl model run failed.");
|
||||
|
||||
ret = CopyAclOutputsToTensorData(output_tensors);
|
||||
MS_CHECK_TRUE_MSG(ret == RET_OK, RET_ERROR, "copy acl outputs to output tensor data failed.");
|
||||
return RET_OK;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_MANAGER_ACL_MODEL_MANAGER_H_
|
||||
#define DPICO_MANAGER_ACL_MODEL_MANAGER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "include/api/types.h"
|
||||
#include "include/svp_acl_base.h"
|
||||
#include "include/svp_acl_mdl.h"
|
||||
#include "include/lite_utils.h"
|
||||
#include "manager/acl_context_manager.h"
|
||||
#include "manager/custom_config_manager.h"
|
||||
#include "common/custom_enum.h"
|
||||
#include "include/schema/model_generated.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
class AclModelManager {
|
||||
public:
|
||||
AclModelManager() = default;
|
||||
~AclModelManager();
|
||||
|
||||
int Init(const std::map<std::string, std::string> &dpico_config, const schema::Primitive *primitive,
|
||||
const std::vector<mindspore::MSTensor> &input_tensors,
|
||||
const std::vector<mindspore::MSTensor> &output_tensors);
|
||||
int UpdateBatchSize(const std::vector<mindspore::MSTensor> &input_tensors);
|
||||
int PrepareAclInputs(std::vector<mindspore::MSTensor> *input_tensors);
|
||||
int PrepareAclOutputs(std::vector<mindspore::MSTensor> *output_tensors);
|
||||
int UpdateKernelConfig(const std::map<std::string, std::string> &dpico_config);
|
||||
int UpdateAclInputs(std::vector<mindspore::MSTensor> *input_tensors);
|
||||
int UpdateAclOutputs(std::vector<mindspore::MSTensor> *output_tensors);
|
||||
int Execute(const std::vector<mindspore::MSTensor> &input_tensors,
|
||||
const std::vector<mindspore::MSTensor> &output_tensors);
|
||||
|
||||
private:
|
||||
int LoadModel(const std::vector<mindspore::MSTensor> &input_tensors);
|
||||
int CreateModelDesc();
|
||||
int SetDetectParams(void *data);
|
||||
int AddDetectParamInput();
|
||||
int DetectPostProcess(mindspore::MSTensor *output_tensors);
|
||||
int CreateTaskBufAndWorkBuf();
|
||||
int CopyTensorDataToAclInputs(const std::vector<mindspore::MSTensor> &input_tensors);
|
||||
int CopyAclOutputsToTensorData(const std::vector<mindspore::MSTensor> &output_tensors);
|
||||
int FlushAclInputsAndOutputs();
|
||||
int AclModelRun(const std::vector<mindspore::MSTensor> &input_tensors);
|
||||
int UnloadModel();
|
||||
|
||||
private:
|
||||
static AllocatorPtr custom_allocator_;
|
||||
static CustomConfigManagerPtr custom_config_manager_ptr_;
|
||||
static AclContextManagerPtr acl_context_manager_;
|
||||
|
||||
std::unordered_map<size_t, bool> inputs_mem_managed_by_tensor; // <acl inputs idx, memory managed flag>
|
||||
std::unordered_map<size_t, bool> outputs_mem_managed_by_tensor; // <acl outputs idx, memory managed flag>
|
||||
|
||||
size_t actual_batch_size_{1};
|
||||
/** acl related variables */
|
||||
uint32_t acl_model_id_{0};
|
||||
AclModelType acl_model_type_{kCnn};
|
||||
void *acl_model_ptr_{nullptr};
|
||||
svp_acl_mdl_desc *acl_model_desc_{nullptr};
|
||||
svp_acl_mdl_dataset *acl_inputs_{nullptr};
|
||||
svp_acl_mdl_dataset *acl_outputs_{nullptr};
|
||||
};
|
||||
using AclModelManagerPtr = std::shared_ptr<AclModelManager>;
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
#endif // DPICO_MANAGER_ACL_MODEL_MANAGER_H_
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Copyright 2022 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 "common/string_util.h"
|
||||
#include "common/op_attr.h"
|
||||
#include "manager/custom_config_manager.h"
|
||||
#include "common/log_util.h"
|
||||
#include "include/errorcode.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
int CustomConfigManager::Init(const std::map<std::string, std::string> &dpico_config) {
|
||||
if (inited_) {
|
||||
MS_LOG(INFO) << "device only needs to init once.";
|
||||
return RET_OK;
|
||||
}
|
||||
if (UpdateConfig(dpico_config) != RET_OK) {
|
||||
MS_LOG(ERROR) << "init custom config failed.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
int CustomConfigManager::UpdateConfig(const std::map<std::string, std::string> &dpico_config) {
|
||||
// parse float params
|
||||
std::map<std::string, float *> float_params = {{kNmsThreshold, &nms_threshold_},
|
||||
{kScoreThreshold, &score_threshold_},
|
||||
{kMinHeight, &min_height_},
|
||||
{kMinWidth, &min_width_}};
|
||||
for (const auto ¶m : float_params) {
|
||||
if (dpico_config.find(param.first) != dpico_config.end()) {
|
||||
if (IsValidDoubleNum(dpico_config.at(param.first))) {
|
||||
*param.second = std::stof(dpico_config.at(param.first));
|
||||
} else {
|
||||
MS_LOG(WARNING) << param.first
|
||||
<< " param in config is invalid, will use default or last value:" << *param.second;
|
||||
}
|
||||
} else {
|
||||
MS_LOG(INFO) << param.first << " param isn't configured, will use default or last value:" << *param.second;
|
||||
}
|
||||
}
|
||||
|
||||
// parse size_t params
|
||||
std::map<std::string, size_t *> unsigned_params = {{kMaxRoiNum, &max_roi_num_}, {kGTotalT, &g_total_t_}};
|
||||
for (const auto ¶m : unsigned_params) {
|
||||
if (dpico_config.find(param.first) != dpico_config.end()) {
|
||||
if (IsValidUnsignedNum(dpico_config.at(param.first))) {
|
||||
*param.second = std::stoul(dpico_config.at(param.first));
|
||||
} else {
|
||||
MS_LOG(WARNING) << param.first
|
||||
<< " param in config is invalid, will use default or last value:" << *param.second;
|
||||
}
|
||||
} else {
|
||||
MS_LOG(INFO) << param.first << " param isn't configured, will use default or last value:" << *param.second;
|
||||
}
|
||||
}
|
||||
|
||||
// parse bool params
|
||||
if (dpico_config.find(kDetectionPostProcess) != dpico_config.end()) {
|
||||
if (dpico_config.at(kDetectionPostProcess) == "on") {
|
||||
detect_post_process_ = true;
|
||||
} else if (dpico_config.at(kDetectionPostProcess) == "off") {
|
||||
detect_post_process_ = false;
|
||||
} else {
|
||||
MS_LOG(WARNING) << kDetectionPostProcess
|
||||
<< " param in config is invalid, will use default or last value: " << detect_post_process_;
|
||||
}
|
||||
} else {
|
||||
MS_LOG(INFO) << kDetectionPostProcess
|
||||
<< " param isn't configured, will use default or last value: " << detect_post_process_;
|
||||
}
|
||||
|
||||
// parse string params
|
||||
if (dpico_config.find(kAclConfigPath) != dpico_config.end()) {
|
||||
acl_config_file_ = dpico_config.at(kAclConfigPath);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright 2022 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 DPICO_MANAGER_CUSTOM_CONFIG_MANAGER_H_
|
||||
#define DPICO_MANAGER_CUSTOM_CONFIG_MANAGER_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
class CustomConfigManager {
|
||||
public:
|
||||
CustomConfigManager() = default;
|
||||
~CustomConfigManager() = default;
|
||||
|
||||
int Init(const std::map<std::string, std::string> &dpico_config);
|
||||
int UpdateConfig(const std::map<std::string, std::string> &dpico_config);
|
||||
size_t MaxRoiNum() const { return max_roi_num_; }
|
||||
float NmsThreshold() const { return nms_threshold_; }
|
||||
float ScoreThreshold() const { return score_threshold_; }
|
||||
float MinHeight() const { return min_height_; }
|
||||
float MinWidth() const { return min_width_; }
|
||||
int GTotalT() const { return g_total_t_; }
|
||||
void SetGTotalT(size_t g_total_t) { g_total_t_ = g_total_t; }
|
||||
bool NeedDetectPostProcess() const { return detect_post_process_; }
|
||||
const std::string &AclConfigFile() const { return acl_config_file_; }
|
||||
|
||||
private:
|
||||
float nms_threshold_{0.9f};
|
||||
float score_threshold_{0.08f};
|
||||
float min_height_{1.0f};
|
||||
float min_width_{1.0f};
|
||||
size_t g_total_t_{0};
|
||||
size_t max_roi_num_{300};
|
||||
bool detect_post_process_{false};
|
||||
std::string acl_config_file_;
|
||||
bool inited_{false};
|
||||
};
|
||||
using CustomConfigManagerPtr = std::shared_ptr<CustomConfigManager>;
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DPICO_MANAGER_CUSTOM_CONFIG_MANAGER_H_
|
|
@ -1,342 +0,0 @@
|
|||
/**
|
||||
* Copyright 2021 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 "src/common_utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "include/svp_acl_rt.h"
|
||||
#include "include/svp_acl.h"
|
||||
#include "include/svp_acl_ext.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
namespace {
|
||||
constexpr int32_t kDeviceId = 0;
|
||||
constexpr size_t kMaxSize = 1024;
|
||||
bool kThreadRunning = false;
|
||||
|
||||
bool IsValidDoubleNum(const std::string &num_str) {
|
||||
if (num_str.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::istringstream iss(num_str);
|
||||
double d;
|
||||
iss >> std::noskipws >> d;
|
||||
return iss.eof() && !iss.fail();
|
||||
}
|
||||
|
||||
void AicpuThread() {
|
||||
MS_LOG(INFO) << "create aicpu thread success";
|
||||
while (kThreadRunning) {
|
||||
svp_acl_error ret = svp_acl_ext_process_aicpu_task(1000); // 1000 ms
|
||||
if (ret != SVP_ACL_SUCCESS && ret != SVP_ACL_ERROR_RT_REPORT_TIMEOUT) {
|
||||
MS_LOG(ERROR) << "create aicpu thread failed!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
MS_LOG(INFO) << "end to destroy aicpu thread";
|
||||
return;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool InferDone(const std::vector<mindspore::MSTensor> &tensors) {
|
||||
for (auto &tensor : tensors) {
|
||||
auto shape = tensor.Shape();
|
||||
if (std::find(shape.begin(), shape.end(), -1) != shape.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExtractAttrsFromPrimitive(const mindspore::schema::Primitive *primitive,
|
||||
std::map<std::string, std::string> *attrs) {
|
||||
if (primitive == nullptr || attrs == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto custom_holder = primitive->value_as_Custom();
|
||||
if (custom_holder == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto attrs_holder = custom_holder->attr();
|
||||
if (attrs_holder == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < attrs_holder->size(); i++) {
|
||||
if (attrs_holder->Get(i) == nullptr || attrs_holder->Get(i)->name() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto attr_name = attrs_holder->Get(i)->name()->str();
|
||||
std::string attr;
|
||||
auto attr_data = attrs_holder->Get(i)->data();
|
||||
if (attr_data != nullptr) {
|
||||
if (attr_data->size() >= kMaxSize) {
|
||||
MS_LOG(WARNING) << "attr size too big, which is out of 1024 character. Obtain " << attr_name.c_str()
|
||||
<< " failed.";
|
||||
} else {
|
||||
for (size_t j = 0; j < attr_data->size(); j++) {
|
||||
attr.push_back(static_cast<char>(attr_data->Get(j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
attrs->emplace(attr_name, attr);
|
||||
}
|
||||
}
|
||||
|
||||
void *ReadBinFile(const std::string &fileName, uint32_t *fileSize) {
|
||||
if (fileSize == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
struct stat sBuf;
|
||||
int fileStatus = stat(fileName.data(), &sBuf);
|
||||
if (fileStatus == -1) {
|
||||
MS_LOG(ERROR) << "failed to get file " << fileName.c_str();
|
||||
return nullptr;
|
||||
}
|
||||
if (S_ISREG(sBuf.st_mode) == 0) {
|
||||
MS_LOG(ERROR) << fileName.c_str() << " is not a file, please enter a file";
|
||||
return nullptr;
|
||||
}
|
||||
std::ifstream binFile(fileName, std::ifstream::binary);
|
||||
if (!binFile.is_open()) {
|
||||
MS_LOG(ERROR) << "open file " << fileName.c_str() << " failed";
|
||||
return nullptr;
|
||||
}
|
||||
binFile.seekg(0, binFile.end);
|
||||
uint32_t binFileBufferLen = binFile.tellg();
|
||||
if (binFileBufferLen == 0) {
|
||||
MS_LOG(ERROR) << "binfile is empty, filename is " << fileName.c_str();
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
binFile.seekg(0, binFile.beg);
|
||||
void *binFileBufferData = nullptr;
|
||||
svp_acl_error ret = SVP_ACL_SUCCESS;
|
||||
ret = svp_acl_rt_malloc(&binFileBufferData, binFileBufferLen, SVP_ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "malloc device buffer failed. size is " << binFileBufferLen;
|
||||
binFile.close();
|
||||
return nullptr;
|
||||
}
|
||||
binFile.read(static_cast<char *>(binFileBufferData), binFileBufferLen);
|
||||
binFile.close();
|
||||
*fileSize = binFileBufferLen;
|
||||
return binFileBufferData;
|
||||
}
|
||||
|
||||
size_t GetMaxMallocSize() {
|
||||
size_t max_malloc_size = 0;
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof(status);
|
||||
GlobalMemoryStatusEx(&status);
|
||||
max_malloc_size = static_cast<size_t>(status.ullTotalPhys);
|
||||
#else
|
||||
max_malloc_size = static_cast<size_t>(sysconf(_SC_PHYS_PAGES)) * static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
#endif
|
||||
return max_malloc_size;
|
||||
}
|
||||
|
||||
Result JudgeOmNetType(const schema::Primitive &primitive, OmNetType *net_type) {
|
||||
auto op = primitive.value_as_Custom();
|
||||
if (op == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
if (op->attr() == nullptr) {
|
||||
MS_LOG(ERROR) << "op attr is nullptr.";
|
||||
return FAILED;
|
||||
}
|
||||
if (op->attr()->size() < 1) {
|
||||
MS_LOG(ERROR) << "There are at least 1 attribute of Custom";
|
||||
return FAILED;
|
||||
}
|
||||
std::string net_type_str = "";
|
||||
for (size_t i = 0; i < op->attr()->size(); i++) {
|
||||
if (op->attr()->Get(i) == nullptr || op->attr()->Get(i)->name() == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
if (op->attr()->Get(i)->name()->str() == kNetType) {
|
||||
auto output_info = op->attr()->Get(i)->data();
|
||||
if (output_info == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
int attr_size = static_cast<int>(output_info->size());
|
||||
for (int j = 0; j < attr_size; j++) {
|
||||
net_type_str.push_back(static_cast<char>(output_info->Get(j)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (net_type_str.empty()) {
|
||||
*net_type = OmNetType_CNN;
|
||||
return SUCCESS;
|
||||
}
|
||||
if (!IsValidUnsignedNum(net_type_str)) {
|
||||
MS_LOG(ERROR) << "net_type attr data is invalid.";
|
||||
return FAILED;
|
||||
}
|
||||
int net_type_val = stoi(net_type_str);
|
||||
if (net_type_val == OmNetType_ROI) {
|
||||
*net_type = OmNetType_ROI;
|
||||
} else if (net_type_val == OmNetType_RECURRENT) {
|
||||
*net_type = OmNetType_RECURRENT;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void DpicoConfigParamExtractor::InitDpicoConfigParam(const kernel::Kernel &kernel) {
|
||||
if (has_init_) {
|
||||
return;
|
||||
}
|
||||
has_init_ = true;
|
||||
UpdateDpicoConfigParam(kernel);
|
||||
}
|
||||
|
||||
void DpicoConfigParamExtractor::UpdateDpicoConfigParam(const kernel::Kernel &kernel) {
|
||||
auto dpico_arg = kernel.GetConfig("dpico");
|
||||
if (dpico_arg.find("MaxRoiNum") != dpico_arg.end()) {
|
||||
if (IsValidUnsignedNum(dpico_arg.at("MaxRoiNum"))) {
|
||||
max_roi_num_ = stoi(dpico_arg.at("MaxRoiNum"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("NmsThreshold") != dpico_arg.end()) {
|
||||
if (IsValidDoubleNum(dpico_arg.at("NmsThreshold"))) {
|
||||
nms_threshold_ = stof(dpico_arg.at("NmsThreshold"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("ScoreThreshold") != dpico_arg.end()) {
|
||||
if (IsValidDoubleNum(dpico_arg.at("ScoreThreshold"))) {
|
||||
score_threshold_ = stof(dpico_arg.at("ScoreThreshold"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("MinHeight") != dpico_arg.end()) {
|
||||
if (IsValidDoubleNum(dpico_arg.at("MinHeight"))) {
|
||||
min_height_ = stof(dpico_arg.at("MinHeight"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("MinWidth") != dpico_arg.end()) {
|
||||
if (IsValidDoubleNum(dpico_arg.at("MinWidth"))) {
|
||||
min_width_ = stof(dpico_arg.at("MinWidth"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("GTotalT") != dpico_arg.end()) {
|
||||
if (IsValidUnsignedNum(dpico_arg.at("GTotalT"))) {
|
||||
g_total_t_ = stoi(dpico_arg.at("GTotalT"));
|
||||
}
|
||||
}
|
||||
|
||||
if (dpico_arg.find("DetectionPostProcess") != dpico_arg.end()) {
|
||||
if (dpico_arg.at("DetectionPostProcess") == "on") {
|
||||
dpico_detection_post_process_ = 1;
|
||||
}
|
||||
}
|
||||
if (dpico_arg.find("ConfigPath") != dpico_arg.end()) {
|
||||
dpico_dump_config_file_ = dpico_arg.at("ConfigPath");
|
||||
}
|
||||
}
|
||||
|
||||
Result DpicoContextManager::InitContext(std::string dpico_dump_config_file) {
|
||||
if (svp_context_ != nullptr) {
|
||||
return SUCCESS;
|
||||
}
|
||||
int ret = SUCCESS;
|
||||
if (dpico_dump_config_file == "") {
|
||||
ret = svp_acl_init(NULL);
|
||||
} else {
|
||||
MS_LOG(INFO)
|
||||
<< "dump according to dump config file " << dpico_dump_config_file.c_str()
|
||||
<< ", if not dump data, please check weather the path exists, or whether add [online_model_type] 4, or model "
|
||||
"name is not the same with instruction_name in converter cfg, default inst, muti seg custom_i";
|
||||
ret = svp_acl_init(dpico_dump_config_file.c_str());
|
||||
}
|
||||
if (ret != SUCCESS) {
|
||||
MS_LOG(ERROR) << "acl init failed";
|
||||
return FAILED;
|
||||
}
|
||||
MS_LOG(INFO) << "acl init success";
|
||||
// open device
|
||||
ret = svp_acl_rt_set_device(kDeviceId);
|
||||
if (ret != SUCCESS) {
|
||||
MS_LOG(ERROR) << "acl open device " << kDeviceId << " failed";
|
||||
return FAILED;
|
||||
}
|
||||
MS_LOG(INFO) << "open device " << kDeviceId << " success";
|
||||
|
||||
// create context (set current)
|
||||
ret = svp_acl_rt_create_context(&svp_context_, kDeviceId);
|
||||
if (ret != SUCCESS || svp_context_ == nullptr) {
|
||||
MS_LOG(ERROR) << "acl create context failed";
|
||||
return FAILED;
|
||||
}
|
||||
MS_LOG(INFO) << "create context success";
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void DpicoContextManager::DestroyContext() {
|
||||
if (svp_context_ != nullptr) {
|
||||
auto ret = svp_acl_rt_destroy_context(svp_context_);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "destroy context failed";
|
||||
}
|
||||
svp_context_ = nullptr;
|
||||
}
|
||||
|
||||
MS_LOG(INFO) << "end to destroy context";
|
||||
auto ret = svp_acl_rt_reset_device(kDeviceId);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "reset device failed";
|
||||
}
|
||||
MS_LOG(INFO) << "end to reset device is " << kDeviceId;
|
||||
|
||||
ret = svp_acl_finalize();
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "finalize acl failed";
|
||||
}
|
||||
MS_LOG(INFO) << "end to finalize acl";
|
||||
}
|
||||
|
||||
void DpicoAicpuThreadManager::CreateAicpuThread(uint32_t model_id) {
|
||||
uint32_t aicpu_task_num = 0;
|
||||
svp_acl_ext_get_mdl_aicpu_task_num(model_id, &aicpu_task_num);
|
||||
all_aicpu_task_num_ += aicpu_task_num;
|
||||
if (all_aicpu_task_num_ > 0 && !is_aicpu_thread_activity_) {
|
||||
kThreadRunning = true;
|
||||
aicpu_thread_ = std::thread(AicpuThread);
|
||||
is_aicpu_thread_activity_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DpicoAicpuThreadManager::DestroyAicpuThread() {
|
||||
if (all_aicpu_task_num_ > 0 && is_aicpu_thread_activity_) {
|
||||
kThreadRunning = false;
|
||||
aicpu_thread_.join();
|
||||
all_aicpu_task_num_ = 0;
|
||||
is_aicpu_thread_activity_ = false;
|
||||
}
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
|
@ -1,125 +0,0 @@
|
|||
/**
|
||||
* Copyright 2021 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 MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_COMMON_UTILS_H_
|
||||
#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_COMMON_UTILS_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "include/api/context.h"
|
||||
#include "include/api/kernel.h"
|
||||
#include "include/svp_acl_base.h"
|
||||
#include "schema/model_generated.h"
|
||||
#include "src/custom_log.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
inline constexpr size_t kMinInputSize = 2;
|
||||
inline constexpr auto kNetType = "net_type";
|
||||
|
||||
typedef enum Result : int { SUCCESS = 0, FAILED = 1 } Result;
|
||||
typedef enum OmNetType : int { OmNetType_CNN = 0, OmNetType_ROI = 1, OmNetType_RECURRENT = 2 } OmNetType;
|
||||
|
||||
#define MS_CHECK_FALSE_MSG(value, errcode, msg) \
|
||||
do { \
|
||||
if ((value)) { \
|
||||
MS_LOG(ERROR) << #msg; \
|
||||
return errcode; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Check whether value is true, if not return 'errcode'
|
||||
// and print error string msg
|
||||
#define MS_CHECK_TRUE_MSG(value, errcode, msg) \
|
||||
do { \
|
||||
if (!(value)) { \
|
||||
MS_LOG(ERROR) << msg; \
|
||||
return errcode; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
inline bool IsValidUnsignedNum(const std::string &num_str) {
|
||||
return !num_str.empty() && std::all_of(num_str.begin(), num_str.end(), ::isdigit);
|
||||
}
|
||||
|
||||
bool InferDone(const std::vector<mindspore::MSTensor> &tensors);
|
||||
|
||||
void ExtractAttrsFromPrimitive(const mindspore::schema::Primitive *primitive,
|
||||
std::map<std::string, std::string> *attrs);
|
||||
|
||||
void *ReadBinFile(const std::string &fileName, uint32_t *fileSize);
|
||||
|
||||
Result JudgeOmNetType(const schema::Primitive &primitive, OmNetType *net_type);
|
||||
|
||||
size_t GetMaxMallocSize();
|
||||
|
||||
class DpicoConfigParamExtractor {
|
||||
public:
|
||||
DpicoConfigParamExtractor() = default;
|
||||
~DpicoConfigParamExtractor() = default;
|
||||
void InitDpicoConfigParam(const kernel::Kernel &kernel);
|
||||
void UpdateDpicoConfigParam(const kernel::Kernel &kernel);
|
||||
size_t GetMaxRoiNum() { return max_roi_num_; }
|
||||
float GetNmsThreshold() { return nms_threshold_; }
|
||||
float GetScoreThreshold() { return score_threshold_; }
|
||||
float GetMinHeight() { return min_height_; }
|
||||
float GetMinWidth() { return min_width_; }
|
||||
int GetGTotalT() { return g_total_t_; }
|
||||
int GetDpicoDetectionPostProcess() { return dpico_detection_post_process_; }
|
||||
std::string GetDpicoDumpConfigFile() { return dpico_dump_config_file_; }
|
||||
|
||||
private:
|
||||
size_t max_roi_num_{400};
|
||||
float nms_threshold_{0.9f};
|
||||
float score_threshold_{0.08f};
|
||||
float min_height_{1.0f};
|
||||
float min_width_{1.0f};
|
||||
int g_total_t_{0};
|
||||
int dpico_detection_post_process_{0};
|
||||
bool has_init_{false};
|
||||
std::string dpico_dump_config_file_{""};
|
||||
};
|
||||
|
||||
class DpicoContextManager {
|
||||
public:
|
||||
DpicoContextManager() = default;
|
||||
~DpicoContextManager() = default;
|
||||
Result InitContext(std::string dpico_dump_config_file);
|
||||
void DestroyContext();
|
||||
svp_acl_rt_context GetSvpContext() { return svp_context_; }
|
||||
|
||||
private:
|
||||
svp_acl_rt_context svp_context_{nullptr};
|
||||
};
|
||||
|
||||
class DpicoAicpuThreadManager {
|
||||
public:
|
||||
DpicoAicpuThreadManager() = default;
|
||||
~DpicoAicpuThreadManager() = default;
|
||||
void CreateAicpuThread(uint32_t model_id);
|
||||
void DestroyAicpuThread();
|
||||
|
||||
private:
|
||||
uint32_t all_aicpu_task_num_{0};
|
||||
bool is_aicpu_thread_activity_{false};
|
||||
std::thread aicpu_thread_;
|
||||
};
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // LITE_COMMON_UTILS_H
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2022 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -15,83 +15,85 @@
|
|||
*/
|
||||
|
||||
#include "src/custom_allocator.h"
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include "include/svp_acl.h"
|
||||
#include "include/svp_acl_ext.h"
|
||||
#include "src/custom_log.h"
|
||||
#include "src/common_utils.h"
|
||||
#include "include/svp_acl_rt.h"
|
||||
#include "common/check_base.h"
|
||||
#include "common/log_util.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dpico {
|
||||
CustomAllocator::CustomAllocator(size_t aligned_size) { aligned_size_ = aligned_size; }
|
||||
namespace lite {
|
||||
namespace {
|
||||
size_t GetMaxMallocSize() {
|
||||
static size_t max_malloc_size =
|
||||
static_cast<size_t>(sysconf(_SC_PHYS_PAGES)) * static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
return max_malloc_size;
|
||||
}
|
||||
} // namespace
|
||||
CustomAllocator::CustomAllocator(size_t aligned_size) {
|
||||
aligned_size_ = aligned_size;
|
||||
max_malloc_size_ = GetMaxMallocSize();
|
||||
}
|
||||
|
||||
CustomAllocator::~CustomAllocator() { Clear(); }
|
||||
|
||||
void CustomAllocator::SetContext(const AllocatorContext &ctx) {
|
||||
lockFlag_ = ctx.lockFlag;
|
||||
shiftFactor_ = static_cast<unsigned>(ctx.shiftFactor);
|
||||
lock_flag_ = ctx.lockFlag;
|
||||
shift_factor_ = static_cast<unsigned>(ctx.shiftFactor);
|
||||
}
|
||||
|
||||
void CustomAllocator::Lock() {
|
||||
if (lockFlag_) {
|
||||
if (lock_flag_) {
|
||||
lock_.lock();
|
||||
}
|
||||
}
|
||||
|
||||
void CustomAllocator::UnLock() {
|
||||
if (lockFlag_) {
|
||||
if (lock_flag_) {
|
||||
lock_.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool CustomAllocator::ReuseMemory(size_t free_size, size_t size) const {
|
||||
return free_size >= size &&
|
||||
(free_size <= (size >= UINT32_MAX / (1ul << shiftFactor_) ? UINT32_MAX : size << shiftFactor_));
|
||||
(free_size <= (size >= UINT32_MAX / (1ul << shift_factor_) ? UINT32_MAX : size << shift_factor_));
|
||||
}
|
||||
|
||||
void *CustomAllocator::Malloc(size_t size) {
|
||||
if (size > lite::GetMaxMallocSize()) {
|
||||
MS_LOG(ERROR) << "MallocData out of max_size, size: " << size;
|
||||
return nullptr;
|
||||
}
|
||||
if (this->total_size_ >= lite::GetMaxMallocSize()) {
|
||||
MS_LOG(ERROR) << "Memory pool is exhausted";
|
||||
return nullptr;
|
||||
}
|
||||
MS_CHECK_TRUE_MSG(size <= max_malloc_size_, nullptr, "MallocData out of max_size, size: " << size);
|
||||
MS_CHECK_TRUE_MSG(total_size_ < max_malloc_size_, nullptr, "memory pool is exhausted");
|
||||
Lock();
|
||||
auto iter = freeList_.lower_bound(size);
|
||||
if (iter != freeList_.end() && ReuseMemory(iter->second->size, size)) {
|
||||
auto iter = free_list_.lower_bound(size);
|
||||
if (iter != free_list_.end() && ReuseMemory(iter->second->size, size)) {
|
||||
auto membuf = iter->second;
|
||||
membuf->ref_count_ = 0;
|
||||
(void)freeList_.erase(iter);
|
||||
allocatedList_[membuf->buf] = membuf;
|
||||
(void)free_list_.erase(iter);
|
||||
allocated_list_[membuf->buf] = membuf;
|
||||
UnLock();
|
||||
return membuf->buf;
|
||||
}
|
||||
|
||||
void *mem_ptr = nullptr;
|
||||
svp_acl_error ret =
|
||||
svp_acl_rt_malloc_cached(&mem_ptr, sizeof(MemBuf) + size + aligned_size_, SVP_ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
int ret = svp_acl_rt_malloc_cached(&mem_ptr, sizeof(MemBuf) + size + aligned_size_, SVP_ACL_MEM_MALLOC_NORMAL_ONLY);
|
||||
if (ret != SVP_ACL_SUCCESS) {
|
||||
MS_LOG(ERROR) << "malloc data failed.";
|
||||
MS_LOG(ERROR) << "svp acl rt malloc cached failed.";
|
||||
UnLock();
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<MemBuf> membuf(reinterpret_cast<MemBuf *>(mem_ptr));
|
||||
if (membuf == nullptr) {
|
||||
MS_LOG(ERROR) << "malloc membuf return nullptr";
|
||||
svp_acl_rt_free(mem_ptr);
|
||||
UnLock();
|
||||
return nullptr;
|
||||
}
|
||||
this->total_size_ += size;
|
||||
membuf->ref_count_ = 0;
|
||||
membuf->size = size;
|
||||
membuf->buf = reinterpret_cast<void *>(
|
||||
membuf->buf = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<uintptr_t>(membuf.get()) + sizeof(MemBuf) + aligned_size_ - 1) & (~(aligned_size_ - 1)));
|
||||
auto bufPtr = membuf->buf;
|
||||
allocatedList_[bufPtr] = membuf.release();
|
||||
auto buf_ptr = membuf->buf;
|
||||
allocated_list_[buf_ptr] = membuf.release();
|
||||
UnLock();
|
||||
return bufPtr;
|
||||
return buf_ptr;
|
||||
}
|
||||
|
||||
void CustomAllocator::Free(void *buf) {
|
||||
|
@ -99,17 +101,19 @@ void CustomAllocator::Free(void *buf) {
|
|||
return;
|
||||
}
|
||||
Lock();
|
||||
auto iter = allocatedList_.find(buf);
|
||||
if (iter != allocatedList_.end()) {
|
||||
auto iter = allocated_list_.find(buf);
|
||||
if (iter != allocated_list_.end()) {
|
||||
auto membuf = iter->second;
|
||||
membuf->ref_count_ = 0;
|
||||
(void)allocatedList_.erase(iter);
|
||||
(void)freeList_.insert(std::make_pair(membuf->size, membuf));
|
||||
(void)allocated_list_.erase(iter);
|
||||
(void)free_list_.insert(std::make_pair(membuf->size, membuf));
|
||||
UnLock();
|
||||
return;
|
||||
}
|
||||
UnLock();
|
||||
svp_acl_rt_free(buf);
|
||||
int ret = svp_acl_rt_free(buf);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "svp acl rt free failed.");
|
||||
buf = nullptr;
|
||||
}
|
||||
|
||||
int CustomAllocator::RefCount(void *buf) {
|
||||
|
@ -117,8 +121,8 @@ int CustomAllocator::RefCount(void *buf) {
|
|||
return -1;
|
||||
}
|
||||
Lock();
|
||||
auto iter = allocatedList_.find(buf);
|
||||
if (iter != allocatedList_.end()) {
|
||||
auto iter = allocated_list_.find(buf);
|
||||
if (iter != allocated_list_.end()) {
|
||||
auto membuf = iter->second;
|
||||
int ref_count = std::atomic_load(&membuf->ref_count_);
|
||||
UnLock();
|
||||
|
@ -132,8 +136,8 @@ int CustomAllocator::SetRefCount(void *buf, int ref_count) {
|
|||
return -1;
|
||||
}
|
||||
Lock();
|
||||
auto iter = allocatedList_.find(buf);
|
||||
if (iter != allocatedList_.end()) {
|
||||
auto iter = allocated_list_.find(buf);
|
||||
if (iter != allocated_list_.end()) {
|
||||
auto membuf = iter->second;
|
||||
std::atomic_store(&membuf->ref_count_, ref_count);
|
||||
UnLock();
|
||||
|
@ -147,8 +151,8 @@ int CustomAllocator::IncRefCount(void *buf, int ref_count) {
|
|||
return -1;
|
||||
}
|
||||
Lock();
|
||||
auto iter = allocatedList_.find(buf);
|
||||
if (iter != allocatedList_.end()) {
|
||||
auto iter = allocated_list_.find(buf);
|
||||
if (iter != allocated_list_.end()) {
|
||||
auto membuf = iter->second;
|
||||
auto ref = std::atomic_fetch_add(&membuf->ref_count_, ref_count);
|
||||
UnLock();
|
||||
|
@ -162,8 +166,8 @@ int CustomAllocator::DecRefCount(void *buf, int ref_count) {
|
|||
return -1;
|
||||
}
|
||||
Lock();
|
||||
auto iter = allocatedList_.find(buf);
|
||||
if (iter != allocatedList_.end()) {
|
||||
auto iter = allocated_list_.find(buf);
|
||||
if (iter != allocated_list_.end()) {
|
||||
auto membuf = iter->second;
|
||||
auto ref = std::atomic_fetch_sub(&membuf->ref_count_, ref_count);
|
||||
UnLock();
|
||||
|
@ -174,17 +178,21 @@ int CustomAllocator::DecRefCount(void *buf, int ref_count) {
|
|||
}
|
||||
void CustomAllocator::Clear() {
|
||||
Lock();
|
||||
|
||||
for (auto &it : allocatedList_) {
|
||||
svp_acl_rt_free(it.second);
|
||||
int ret;
|
||||
for (auto &it : allocated_list_) {
|
||||
ret = svp_acl_rt_free(it.second);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "svp acl rt free failed.");
|
||||
it.second = nullptr;
|
||||
}
|
||||
allocatedList_.clear();
|
||||
allocated_list_.clear();
|
||||
|
||||
for (auto &it : freeList_) {
|
||||
svp_acl_rt_free(it.second);
|
||||
for (auto &it : free_list_) {
|
||||
ret = svp_acl_rt_free(it.second);
|
||||
MS_CHECK_TRUE_MSG_VOID(ret == SVP_ACL_SUCCESS, "svp acl rt free failed.");
|
||||
it.second = nullptr;
|
||||
}
|
||||
freeList_.clear();
|
||||
free_list_.clear();
|
||||
UnLock();
|
||||
}
|
||||
} // namespace dpico
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2022 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -28,7 +28,7 @@
|
|||
#include "include/api/allocator.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dpico {
|
||||
namespace lite {
|
||||
struct AllocatorContext {
|
||||
int shiftFactor;
|
||||
bool lockFlag;
|
||||
|
@ -45,7 +45,7 @@ class CustomAllocator : public Allocator {
|
|||
int SetRefCount(void *ptr, int ref_count) override;
|
||||
int DecRefCount(void *ptr, int ref_count) override;
|
||||
int IncRefCount(void *ptr, int ref_count) override;
|
||||
size_t total_size() { return this->total_size_; }
|
||||
size_t total_size() const { return this->total_size_; }
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
|
@ -61,16 +61,16 @@ class CustomAllocator : public Allocator {
|
|||
std::mutex lock_;
|
||||
size_t total_size_ = 0;
|
||||
// <membuf->buf, membuf>
|
||||
std::unordered_map<void *, MemBuf *> allocatedList_;
|
||||
std::multimap<size_t, MemBuf *> freeList_;
|
||||
std::unordered_map<void *, MemBuf *> allocated_list_;
|
||||
std::multimap<size_t, MemBuf *> free_list_;
|
||||
// 6 is empirical value
|
||||
unsigned shiftFactor_ = 6;
|
||||
bool lockFlag_ = true;
|
||||
unsigned shift_factor_ = 6;
|
||||
bool lock_flag_ = true;
|
||||
size_t max_malloc_size_ = 0;
|
||||
};
|
||||
|
||||
using CustomAllocatorPtr = std::shared_ptr<CustomAllocator>;
|
||||
constexpr int64_t MAX_MALLOC_SIZE = static_cast<size_t>(2000) * 1024 * 1024;
|
||||
constexpr int64_t MAX_THREAD_POOL_SIZE = static_cast<size_t>(3000) * 1024 * 1024;
|
||||
} // namespace dpico
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DPICO_SRC_CUSTOM_ALLOCATOR_H_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
* Copyright 2021-2022 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.
|
||||
|
@ -17,113 +17,36 @@
|
|||
#ifndef DPICO_SRC_CUSTOM_FP32_H_
|
||||
#define DPICO_SRC_CUSTOM_FP32_H_
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "include/api/kernel.h"
|
||||
#include "include/svp_acl.h"
|
||||
#include "include/svp_acl_mdl.h"
|
||||
#include "include/svp_acl_ext.h"
|
||||
#include "src/common_utils.h"
|
||||
#include "src/custom_infer.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "manager/acl_model_manager.h"
|
||||
|
||||
using mindspore::kernel::Kernel;
|
||||
|
||||
using mindspore::lite::RET_ERROR;
|
||||
using mindspore::lite::RET_OK;
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
class CustomCPUKernel : public Kernel {
|
||||
public:
|
||||
CustomCPUKernel(const std::vector<MSTensor> &inputs, const std::vector<MSTensor> &outputs,
|
||||
const mindspore::schema::Primitive *primitive, const mindspore::Context *ctx)
|
||||
: Kernel(inputs, outputs, primitive, ctx) {
|
||||
std::map<std::string, std::string> attrs;
|
||||
ExtractAttrsFromPrimitive(primitive, &attrs);
|
||||
for (auto &item : attrs) {
|
||||
SetAttr(item.first, item.second);
|
||||
}
|
||||
num_of_om_model_++;
|
||||
}
|
||||
: Kernel(inputs, outputs, primitive, ctx) {}
|
||||
|
||||
~CustomCPUKernel() override;
|
||||
~CustomCPUKernel() = default;
|
||||
|
||||
int Prepare() override;
|
||||
int ReSize() override;
|
||||
int Execute() override;
|
||||
|
||||
private:
|
||||
Result DetermineBatchSize();
|
||||
int LoadModelAndInitResource();
|
||||
Result LoadModel();
|
||||
Result PrepareDevice();
|
||||
Result CreateInputs();
|
||||
Result CreateOutputs();
|
||||
Result SetDetParas();
|
||||
Result InitInputsLinkMap();
|
||||
Result InitOutputsLinkMap();
|
||||
Result MallocOutputsData();
|
||||
Result UpdateInputDataset();
|
||||
Result UpdateOutputDataset();
|
||||
Result FlushInputsData();
|
||||
Result InvalidateOutputsData();
|
||||
Result GetStrideParam(size_t *devSize, int index, size_t *stride, svp_acl_mdl_io_dims *dims);
|
||||
Result CreateInput(void *inputDataBuffer, size_t bufferSize, int stride);
|
||||
void *GetDeviceBufferOfTensor(const svp_acl_mdl_io_dims &dims, const size_t &stride);
|
||||
Result CreateTaskBufAndWorkBuf();
|
||||
Result CreateBuf(int index);
|
||||
Result GetInputDims(int index, svp_acl_mdl_io_dims *dims);
|
||||
size_t GetInputDataSize(int index);
|
||||
|
||||
Result PreExecute();
|
||||
Result DeviceExecute();
|
||||
Result CopyTensorsToNpuWithStride();
|
||||
void DumpModelOutputResultToTensor();
|
||||
void WriteOutputToTensor(size_t index, size_t output_tensor_index);
|
||||
void OutputModelResult();
|
||||
void PrintResultToTensor(const std::vector<std::vector<float>> &boxValue);
|
||||
void UpdateDetParas();
|
||||
|
||||
void UnloadModel();
|
||||
void DestroyInput();
|
||||
void DestroyOutput();
|
||||
void TerminateDevice();
|
||||
bool InferShapeDone() const;
|
||||
int PreProcess();
|
||||
|
||||
private:
|
||||
uint32_t model_id_ = 0;
|
||||
void *model_mem_ptr_ = nullptr;
|
||||
bool load_flag_ = false; // model load flag
|
||||
svp_acl_mdl_desc *model_desc_ = nullptr;
|
||||
svp_acl_mdl_dataset *input_dataset_ = nullptr;
|
||||
svp_acl_mdl_dataset *output_dataset_ = nullptr;
|
||||
|
||||
svp_acl_rt_stream stream_;
|
||||
|
||||
std::vector<void *> inputs_data_in_npu_;
|
||||
std::unordered_map<size_t, size_t> inputs_link_map_; // <tensor_input_idx, om_input_idx>
|
||||
std::unordered_map<size_t, size_t> outputs_link_map_; // <tensor_output_idx, om_output_idx>
|
||||
std::unordered_map<size_t, bool> inputs_mem_aligned_flag_; // <tensor_output_idx, is_mem_already_aligned>
|
||||
std::unordered_map<size_t, bool> outputs_mem_aligned_flag_; // <tensor_input_idx, is_mem_already_aligned>
|
||||
size_t recurrent_total_t = 1;
|
||||
bool is_recurrent_net_ = false; // true: batch is 1, false: not support Total_t
|
||||
bool is_detection_net_ = false;
|
||||
size_t batch_size_ = 1;
|
||||
bool prepared_ = false;
|
||||
float *det_param_buf_float_ = nullptr;
|
||||
static size_t num_of_om_model_;
|
||||
static std::shared_ptr<Allocator> custom_allocator_;
|
||||
static dpico::CustomInterface custom_infershape_;
|
||||
static DpicoConfigParamExtractor dpico_config_param_extractor_;
|
||||
static DpicoContextManager dpico_context_manager_;
|
||||
static DpicoAicpuThreadManager dpico_aicpu_thread_manager_;
|
||||
AclModelManagerPtr acl_model_manager_{nullptr};
|
||||
};
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DPICO_SRC_CUSTOM_FP32_H_
|
||||
|
|
|
@ -1,280 +0,0 @@
|
|||
/**
|
||||
* Copyright 2021 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 "src/custom_infer.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "include/api/format.h"
|
||||
#include "include/registry/register_kernel_interface.h"
|
||||
#include "src/common_utils.h"
|
||||
|
||||
using mindspore::kernel::KernelInterface;
|
||||
using mindspore::schema::PrimitiveType_Custom;
|
||||
|
||||
namespace mindspore {
|
||||
namespace dpico {
|
||||
namespace {
|
||||
constexpr int kDecimal = 10;
|
||||
constexpr auto kInputShape = "inputs_shape";
|
||||
constexpr auto kOutputShape = "outputs_shape";
|
||||
constexpr auto kOutputsFormat = "outputs_format";
|
||||
std::vector<std::string> SplitString(const std::string &raw_str, char delimiter) {
|
||||
if (raw_str.empty()) {
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> res;
|
||||
std::string::size_type last_pos = 0;
|
||||
auto cur_pos = raw_str.find(delimiter);
|
||||
while (cur_pos != std::string::npos) {
|
||||
res.push_back(raw_str.substr(last_pos, cur_pos - last_pos));
|
||||
cur_pos++;
|
||||
last_pos = cur_pos;
|
||||
cur_pos = raw_str.find(delimiter, cur_pos);
|
||||
}
|
||||
if (last_pos < raw_str.size()) {
|
||||
res.push_back(raw_str.substr(last_pos, raw_str.size() - last_pos + 1));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Status GetCustomShape(const std::map<std::string, std::string> &attrs, const std::string &attr_name,
|
||||
std::vector<std::vector<int64_t>> *shapes) {
|
||||
if (shapes == nullptr) {
|
||||
MS_LOG(ERROR) << "the function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto attr = attrs.at(attr_name);
|
||||
if (attr.empty()) {
|
||||
MS_LOG(ERROR) << attr_name.c_str() << " data is empty.";
|
||||
return kLiteError;
|
||||
}
|
||||
char delims[] = ",";
|
||||
char *res = nullptr;
|
||||
char *save_ptr = nullptr;
|
||||
res = strtok_r(attr.data(), delims, &save_ptr);
|
||||
while (res != nullptr) {
|
||||
int64_t ndims = strtol(res, &res, kDecimal);
|
||||
int j = 0;
|
||||
std::vector<int64_t> shape;
|
||||
shape.resize(ndims);
|
||||
for (; j < ndims; j++) {
|
||||
res = strtok_r(NULL, delims, &save_ptr);
|
||||
shape[j] = static_cast<int64_t>(strtol(res, &res, kDecimal));
|
||||
}
|
||||
shapes->push_back(shape);
|
||||
|
||||
res = strtok_r(NULL, delims, &save_ptr);
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status DetermineBatchSize(const std::vector<int64_t> &input_shape_lite, const std::vector<int64_t> &input_shape_dpico,
|
||||
int *resize_num, bool *is_resize) {
|
||||
if (resize_num == nullptr || is_resize == nullptr) {
|
||||
MS_LOG(ERROR) << "the function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (input_shape_lite.size() != input_shape_dpico.size()) {
|
||||
MS_LOG(ERROR) << "both input shape from lite and dpico cannot match.";
|
||||
return kLiteError;
|
||||
}
|
||||
for (size_t i = 0; i < input_shape_dpico.size(); i++) {
|
||||
if (input_shape_dpico[i] != input_shape_lite[i]) {
|
||||
if (i == 0) {
|
||||
*is_resize = true;
|
||||
*resize_num = input_shape_lite[i];
|
||||
} else {
|
||||
MS_LOG(ERROR) << "Custom of DPICO only support batch_num resize.";
|
||||
return kLiteError;
|
||||
}
|
||||
}
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status SetOutputFormat(const std::map<std::string, std::string> &attrs, std::vector<mindspore::MSTensor> *outputs) {
|
||||
if (outputs == nullptr) {
|
||||
MS_LOG(ERROR) << "the function input parameter is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (attrs.find(kOutputsFormat) == attrs.end()) {
|
||||
MS_LOG(ERROR) << "custom node should have " << kOutputsFormat << " attr.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto output_format_str = attrs.at(kOutputsFormat);
|
||||
auto output_format = SplitString(output_format_str, ',');
|
||||
if (output_format.size() > outputs->size()) {
|
||||
MS_LOG(ERROR) << "output format attr is invalid, the number of which is out of range.";
|
||||
return kLiteError;
|
||||
}
|
||||
for (size_t i = 0; i < output_format.size(); ++i) {
|
||||
if (!lite::IsValidUnsignedNum(output_format[i])) {
|
||||
MS_LOG(ERROR) << "output format must be an unsigned int.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto format = std::stoi(output_format[i]);
|
||||
if (format != NHWC && format != NCHW) {
|
||||
MS_LOG(ERROR) << "output format is invalid, which should be NHWC or NCHW.";
|
||||
return kLiteError;
|
||||
}
|
||||
outputs->at(i).SetFormat(static_cast<Format>(format));
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<KernelInterface> CustomInferCreater() {
|
||||
auto infer = new (std::nothrow) CustomInterface();
|
||||
if (infer == nullptr) {
|
||||
MS_LOG(ERROR) << "new custom infer is nullptr";
|
||||
return nullptr;
|
||||
}
|
||||
return std::shared_ptr<KernelInterface>(infer);
|
||||
}
|
||||
|
||||
Status CustomInterface::InferShapeJudge(std::vector<mindspore::MSTensor> *inputs,
|
||||
const std::vector<std::vector<int64_t>> &inputs_shape) const {
|
||||
size_t inputs_size_without_om_model = inputs->size() - 1;
|
||||
if (inputs_shape.size() != inputs_size_without_om_model) {
|
||||
MS_LOG(ERROR) << "inputs num diff inputs_shape num.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (inputs_shape[0].size() != (*inputs)[0].Shape().size()) {
|
||||
MS_LOG(ERROR) << "shape size err. " << inputs_shape[0].size() << ", " << (*inputs)[0].Shape().size();
|
||||
return kLiteError;
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status CustomInterface::InferRecurrentTwoOutputProcess(const mindspore::schema::Primitive *primitive,
|
||||
const kernel::Kernel *kernel,
|
||||
std::vector<std::vector<int64_t>> *outputs_shape) const {
|
||||
if (primitive == nullptr || outputs_shape == nullptr) {
|
||||
return kLiteError;
|
||||
}
|
||||
lite::OmNetType net_type{lite::OmNetType_CNN};
|
||||
if (kernel != nullptr) {
|
||||
auto net_type_str = kernel->GetAttr(lite::kNetType);
|
||||
if (!net_type_str.empty()) {
|
||||
if (!lite::IsValidUnsignedNum(net_type_str)) {
|
||||
MS_LOG(ERROR) << "net_type must be an unsigned int.";
|
||||
return kLiteError;
|
||||
}
|
||||
auto net_type_int = std::stoi(net_type_str);
|
||||
if (net_type_int < lite::OmNetType_CNN || net_type_int > lite::OmNetType_RECURRENT) {
|
||||
MS_LOG(ERROR) << "net_type attr is invalid, value is " << net_type_int;
|
||||
return kLiteError;
|
||||
}
|
||||
net_type = static_cast<lite::OmNetType>(net_type_int);
|
||||
}
|
||||
} else {
|
||||
auto ret = JudgeOmNetType(*primitive, &net_type);
|
||||
if (ret != lite::SUCCESS) {
|
||||
MS_LOG(ERROR) << "get model attr failed";
|
||||
return kLiteError;
|
||||
}
|
||||
}
|
||||
if (net_type == lite::OmNetType_RECURRENT && outputs_shape->size() > 1) {
|
||||
if ((*outputs_shape)[1].empty()) {
|
||||
return kLiteError;
|
||||
}
|
||||
(*outputs_shape)[1][0] = 1;
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
Status CustomInterface::Infer(std::vector<mindspore::MSTensor> *inputs, std::vector<mindspore::MSTensor> *outputs,
|
||||
const mindspore::schema::Primitive *primitive, const kernel::Kernel *kernel) {
|
||||
if (inputs->size() < lite::kMinInputSize) {
|
||||
MS_LOG(ERROR) << "Inputs size is less than 2";
|
||||
return kLiteError;
|
||||
}
|
||||
if (outputs->empty()) {
|
||||
MS_LOG(ERROR) << "Outputs size 0";
|
||||
return kLiteError;
|
||||
}
|
||||
std::map<std::string, std::string> attrs;
|
||||
schema::PrimitiveType type;
|
||||
if (kernel != nullptr) {
|
||||
attrs.emplace(kInputShape, kernel->GetAttr(kInputShape));
|
||||
attrs.emplace(kOutputShape, kernel->GetAttr(kOutputShape));
|
||||
attrs.emplace(kOutputsFormat, kernel->GetAttr(kOutputsFormat));
|
||||
type = kernel->type();
|
||||
} else {
|
||||
if (primitive == nullptr) {
|
||||
MS_LOG(ERROR) << "primitive is nullptr.";
|
||||
return kLiteError;
|
||||
}
|
||||
lite::ExtractAttrsFromPrimitive(primitive, &attrs);
|
||||
type = primitive->value_type();
|
||||
}
|
||||
if (type != mindspore::schema::PrimitiveType_Custom) {
|
||||
MS_LOG(ERROR) << "Primitive type is not PrimitiveType_Custom";
|
||||
return kLiteError;
|
||||
}
|
||||
for (size_t i = 0; i < outputs->size(); i++) {
|
||||
(*outputs)[i].SetDataType(DataType::kNumberTypeFloat32);
|
||||
(*outputs)[i].SetFormat(Format::NCHW);
|
||||
}
|
||||
if (SetOutputFormat(attrs, outputs) != kSuccess) {
|
||||
MS_LOG(ERROR) << "set output format failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (!lite::InferDone(*inputs)) {
|
||||
return kLiteInferInvalid;
|
||||
}
|
||||
std::vector<std::vector<int64_t>> inputs_shape;
|
||||
if (GetCustomShape(attrs, "inputs_shape", &inputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "parser inputs_shape attribute err.";
|
||||
return kLiteError;
|
||||
}
|
||||
std::vector<std::vector<int64_t>> outputs_shape;
|
||||
if (GetCustomShape(attrs, "outputs_shape", &outputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "parser outputs_shape attribute err.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (InferShapeJudge(inputs, inputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "input shape err.";
|
||||
return kLiteError;
|
||||
}
|
||||
bool resize_flag = false;
|
||||
int resize_num = 1;
|
||||
if (DetermineBatchSize((*inputs)[0].Shape(), inputs_shape[0], &resize_num, &resize_flag) != kSuccess) {
|
||||
MS_LOG(ERROR) << "determine batch size failed.";
|
||||
return kLiteError;
|
||||
}
|
||||
if (resize_flag) {
|
||||
for (auto &output_shape : outputs_shape) {
|
||||
output_shape[0] = resize_num;
|
||||
}
|
||||
}
|
||||
if (InferRecurrentTwoOutputProcess(primitive, kernel, &outputs_shape) != kSuccess) {
|
||||
MS_LOG(ERROR) << "Infer Recurrent Two Output Process err.";
|
||||
return kLiteError;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < outputs->size(); i++) {
|
||||
(*outputs)[i].SetShape(outputs_shape[i]);
|
||||
}
|
||||
return kSuccess;
|
||||
}
|
||||
} // namespace dpico
|
||||
} // namespace mindspore
|
||||
namespace mindspore {
|
||||
namespace kernel {
|
||||
REGISTER_CUSTOM_KERNEL_INTERFACE(DPICO, DPICO, dpico::CustomInferCreater);
|
||||
} // namespace kernel
|
||||
} // namespace mindspore
|
|
@ -25,7 +25,7 @@ if(TARGET_HIMIX)
|
|||
elseif(TARGET_MIX210)
|
||||
set(CMAKE_SKIP_BUILD_RPATH on)
|
||||
set(BENCHMARK_LINK_LIB ${BENCHMARK_LINK_LIB} mindspore::json pthread
|
||||
dpico_acl_adapter svp_acl dl securec protobuf-c stdc++)
|
||||
dpico_acl_adapter stdc++)
|
||||
if(${MSLITE_REGISTRY_DEVICE} STREQUAL "SD3403")
|
||||
add_subdirectory(${PROVIDERS_DIR}/dpico dpico)
|
||||
message("SD3403_SDK_PATH:${SD3403_SDK_PATH}.")
|
||||
|
|
Loading…
Reference in New Issue