!34390 [MS][LITE] dpico runtime refactoring

Merge pull request !34390 from jianghui58/dpico_runtime_0512
This commit is contained in:
i-robot 2022-05-17 09:35:55 +00:00 committed by Gitee
commit fa43506432
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
28 changed files with 1910 additions and 2065 deletions

View File

@ -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})

View File

@ -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_

View File

@ -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_

View File

@ -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 &param_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

View File

@ -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 &param_name);
} // namespace lite
} // namespace mindspore
#endif // DPICO_COMMON_INFER_UTIL_H_

View File

@ -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 {

View File

@ -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_

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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 &param : 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 &param : 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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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}.")