forked from huawei/mindspore2022
!19180 [lite]demo tutorial for extend api
Merge pull request !19180 from 徐安越/master_core
This commit is contained in:
commit
164d430246
|
|
@ -0,0 +1,34 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
project(ConverterExtendTutorial)
|
||||
add_definitions(-DUSE_GLOG)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3.0)
|
||||
message(FATAL_ERROR "GCC version ${CMAKE_CXX_COMPILER_VERSION} must not be less than 7.3.0")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
|
||||
# Add directory to include search path
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/core)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/third_party)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/third_party/eigen3)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/third_party/securec)
|
||||
|
||||
# Add directory to linker search path
|
||||
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
|
||||
file(GLOB_RECURSE CONVERTER_REGISTRY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc)
|
||||
add_library(converter_extend_tutorial SHARED ${CONVERTER_REGISTRY_SRC})
|
||||
|
||||
target_link_libraries(converter_extend_tutorial
|
||||
mslite_converter_plugin
|
||||
-Wl,--whole-archive mindspore_core -Wl,--no-whole-archive
|
||||
mindspore_gvar
|
||||
crypto
|
||||
securec
|
||||
glog
|
||||
protobuf
|
||||
dl
|
||||
)
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
BASEPATH=$(cd "$(dirname $0)" || exit; pwd)
|
||||
get_version() {
|
||||
VERSION_MAJOR=$(grep "const int ms_version_major =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_MINOR=$(grep "const int ms_version_minor =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_REVISION=$(grep "const int ms_version_revision =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_STR=${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
|
||||
}
|
||||
get_version
|
||||
MODEL_DOWNLOAD_URL="https://download.mindspore.cn/model_zoo/official/lite/quick_start/add.tflite"
|
||||
MINDSPORE_FILE_NAME="mindspore-lite-${VERSION_STR}-linux-x64"
|
||||
MINDSPORE_FILE="${MINDSPORE_FILE_NAME}.tar.gz"
|
||||
MINDSPORE_LITE_DOWNLOAD_URL="https://ms-release.obs.cn-north-4.myhuaweicloud.com/${VERSION_STR}/MindSpore/lite/release/linux/${MINDSPORE_FILE}"
|
||||
|
||||
mkdir -p build
|
||||
mkdir -p model
|
||||
if [ ! -e ${BASEPATH}/model/add.tflite ]; then
|
||||
wget -c -O ${BASEPATH}/model/add.tflite --no-check-certificate ${MODEL_DOWNLOAD_URL}
|
||||
fi
|
||||
if [ ! -e ${BASEPATH}/build/${MINDSPORE_FILE} ]; then
|
||||
wget -c -O ${BASEPATH}/build/${MINDSPORE_FILE} --no-check-certificate ${MINDSPORE_LITE_DOWNLOAD_URL}
|
||||
fi
|
||||
tar -xzf ${BASEPATH}/build/${MINDSPORE_FILE}
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/tools/converter/lib ${BASEPATH}/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/tools/converter/include ${BASEPATH}/
|
||||
cd ${BASEPATH}/build || exit
|
||||
cmake ${BASEPATH}
|
||||
make
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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_common.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "include/registry/kernel_interface.h"
|
||||
|
||||
namespace mindspore {
|
||||
/**
|
||||
* CustomAddInfer is a child class to infer current node output's information, including format, data_type and shape.
|
||||
* if inputs' shape exist -1, don't worry, which shows that shape will be inferred when running.
|
||||
*/
|
||||
class CustomAddInfer : public kernel::KernelInterface {
|
||||
public:
|
||||
CustomAddInfer() = default;
|
||||
~CustomAddInfer() = default;
|
||||
|
||||
int Infer(const std::vector<tensor::MSTensor *> &inputs, const std::vector<tensor::MSTensor *> &outputs,
|
||||
const schema::Primitive *primitive) override {
|
||||
outputs[0]->set_format(inputs[0]->format());
|
||||
outputs[0]->set_data_type(inputs[0]->data_type());
|
||||
auto ret = common::CheckInputs(inputs);
|
||||
if (ret != lite::RET_OK) {
|
||||
outputs[0]->set_shape({-1}); // shape{-1} shows that shape need to be inferred when running.
|
||||
return ret;
|
||||
}
|
||||
outputs[0]->set_shape(inputs[0]->shape());
|
||||
return lite::RET_OK;
|
||||
}
|
||||
};
|
||||
std::shared_ptr<kernel::KernelInterface> CustomAddInferCreator() { return std::make_shared<CustomAddInfer>(); }
|
||||
REGISTER_CUSTOM_KERNEL_INTERFACE(CustomOpTutorial, Custom_Add, CustomAddInferCreator)
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* 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_common.h"
|
||||
#include <vector>
|
||||
|
||||
namespace mindspore {
|
||||
namespace common {
|
||||
int CheckInputs(const std::vector<tensor::MSTensor *> &inputs) {
|
||||
for (auto &input : inputs) {
|
||||
auto input_shape = input->shape();
|
||||
if (std::find(input_shape.begin(), input_shape.end(), -1) != input_shape.end()) {
|
||||
return lite::RET_INFER_INVALID;
|
||||
}
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
|
||||
int CheckOutputs(const std::vector<tensor::MSTensor *> &outputs) {
|
||||
for (auto &output : outputs) {
|
||||
auto output_shape = output->shape();
|
||||
if (std::find(output_shape.begin(), output_shape.end(), -1) != output_shape.end()) {
|
||||
return lite::RET_INFER_INVALID;
|
||||
}
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
} // namespace common
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
#define MINDSPORE_LITE_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
|
||||
#include <vector>
|
||||
#include "include/errorcode.h"
|
||||
#include "include/ms_tensor.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace common {
|
||||
// verify that the inputs' shape is inferred successfully when inferring current node.
|
||||
int CheckInputs(const std::vector<tensor::MSTensor *> &inputs);
|
||||
|
||||
// versify that the outputs' shape is inferred successfully when running current node.
|
||||
int CheckOutputs(const std::vector<tensor::MSTensor *> &outputs);
|
||||
} // namespace common
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_LITE_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* 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/pass_registry_tutorial.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "include/registry/pass_registry.h"
|
||||
#include "ops/custom.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace opt {
|
||||
namespace {
|
||||
// check a certain node is designated node's type.
|
||||
bool CheckPrimitiveTypeTutorial(const AnfNodePtr &node, const PrimitivePtr &primitive_type) {
|
||||
if (node == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (node->isa<CNode>()) {
|
||||
auto cnode = node->cast<CNodePtr>();
|
||||
return IsPrimitive(cnode->input(0), primitive_type);
|
||||
} else if (node->isa<ValueNode>()) {
|
||||
return IsPrimitive(node, primitive_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// convert addn to custom op
|
||||
AnfNodePtr PassTutorial::CreateCustomOp(const FuncGraphPtr func_graph, const CNodePtr &cnode) {
|
||||
if (cnode == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
auto primc = std::make_shared<ops::Custom>();
|
||||
if (primc == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
primc->set_type("Custom_Add");
|
||||
std::map<std::string, std::vector<uint8_t>> custom_attrs;
|
||||
std::string input_num = std::to_string(2);
|
||||
std::vector<uint8_t> input_num_attr(input_num.begin(), input_num.end());
|
||||
custom_attrs["input_num"] = input_num_attr;
|
||||
std::string op_kind = "custom op";
|
||||
std::vector<uint8_t> op_kind_attr(op_kind.begin(), op_kind.end());
|
||||
custom_attrs["op_kind"] = op_kind_attr;
|
||||
primc->set_attr(custom_attrs);
|
||||
auto inputs = cnode->inputs();
|
||||
inputs.erase(inputs.begin());
|
||||
auto custom_cnode = func_graph->NewCNode(primc, inputs);
|
||||
custom_cnode->set_fullname_with_scope(cnode->fullname_with_scope());
|
||||
custom_cnode->set_abstract(cnode->abstract()->Clone());
|
||||
return custom_cnode;
|
||||
}
|
||||
|
||||
bool PassTutorial::Run(const FuncGraphPtr &func_graph) {
|
||||
if (func_graph == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// generate a func_graph manager.
|
||||
auto manager = Manage(func_graph, true);
|
||||
if (manager == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto node_list = TopoSort(func_graph->get_return());
|
||||
for (auto &node : node_list) {
|
||||
if (!utils::isa<CNode>(node)) {
|
||||
continue;
|
||||
}
|
||||
if (!CheckPrimitiveTypeTutorial(node, prim::kPrimAddFusion)) {
|
||||
continue;
|
||||
}
|
||||
auto cnode = node->cast<CNodePtr>();
|
||||
auto custome_cnode = CreateCustomOp(func_graph, cnode);
|
||||
if (custome_cnode == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// use new node to replace old node by func_graph manager.
|
||||
manager->Replace(node, custome_cnode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// register customed Pass
|
||||
REG_PASS(POSITION_BEGIN, PassTutorial)
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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_EXAMPLES_CONVERTER_REGISTER_SRC_PASS_REGISTRY_TUTORIAL_H
|
||||
#define MINDSPORE_LITE_EXAMPLES_CONVERTER_REGISTER_SRC_PASS_REGISTRY_TUTORIAL_H
|
||||
|
||||
#include "include/pass.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace opt {
|
||||
class PassTutorial : public Pass {
|
||||
public:
|
||||
PassTutorial() : Pass("pass_tutorial") {}
|
||||
|
||||
bool Run(const FuncGraphPtr &func_graph) override;
|
||||
|
||||
private:
|
||||
AnfNodePtr CreateCustomOp(const FuncGraphPtr func_graph, const CNodePtr &cnode);
|
||||
};
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_LITE_EXAMPLES_CONVERTER_REGISTER_SRC_PASS_REGISTRY_TUTORIAL_H
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
project(RuntimeExtendTutorial)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3.0)
|
||||
message(FATAL_ERROR "GCC version ${CMAKE_CXX_COMPILER_VERSION} must not be less than 7.3.0")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
|
||||
# Add directory to include search path
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/third_party)
|
||||
|
||||
# Add directory to linker search path
|
||||
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
|
||||
file(GLOB_RECURSE RUNTIME_REGISTRY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
|
||||
add_executable(runtime_extend_tutorial ${RUNTIME_REGISTRY_SRC})
|
||||
|
||||
target_link_libraries(
|
||||
runtime_extend_tutorial
|
||||
-Wl,--whole-archive mindspore-lite -Wl,--no-whole-archive
|
||||
pthread
|
||||
dl
|
||||
)
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
# 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.
|
||||
# ============================================================================
|
||||
|
||||
BASEPATH=$(cd "$(dirname $0)" || exit; pwd)
|
||||
get_version() {
|
||||
VERSION_MAJOR=$(grep "const int ms_version_major =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_MINOR=$(grep "const int ms_version_minor =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_REVISION=$(grep "const int ms_version_revision =" ${BASEPATH}/../../include/version.h | tr -dc "[0-9]")
|
||||
VERSION_STR=${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
|
||||
}
|
||||
get_version
|
||||
MODEL_DOWNLOAD_URL="https://download.mindspore.cn/model_zoo/official/lite/quick_start/model_extend.ms"
|
||||
MINDSPORE_FILE_NAME="mindspore-lite-${VERSION_STR}-linux-x64"
|
||||
MINDSPORE_FILE="${MINDSPORE_FILE_NAME}.tar.gz"
|
||||
MINDSPORE_LITE_DOWNLOAD_URL="https://ms-release.obs.cn-north-4.myhuaweicloud.com/${VERSION_STR}/MindSpore/lite/release/linux/${MINDSPORE_FILE}"
|
||||
|
||||
mkdir -p build
|
||||
mkdir -p lib
|
||||
mkdir -p include
|
||||
mkdir -p model
|
||||
if [ ! -e ${BASEPATH}/model/model_extend.ms ]; then
|
||||
wget -c -O ${BASEPATH}/model/model_extend.ms --no-check-certificate ${MODEL_DOWNLOAD_URL}
|
||||
fi
|
||||
if [ ! -e ${BASEPATH}/build/${MINDSPORE_FILE} ]; then
|
||||
wget -c -O ${BASEPATH}/build/${MINDSPORE_FILE} --no-check-certificate ${MINDSPORE_LITE_DOWNLOAD_URL}
|
||||
fi
|
||||
tar -xzf ${BASEPATH}/build/${MINDSPORE_FILE}
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/lib/libmindspore-lite.a ${BASEPATH}/lib/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/include/*.h ${BASEPATH}/include/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/include/ir ${BASEPATH}/include/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/include/registry ${BASEPATH}/include/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/include/schema ${BASEPATH}/include/
|
||||
cp -r ${BASEPATH}/build/${MINDSPORE_FILE_NAME}/runtime/include/third_party ${BASEPATH}/include/
|
||||
cd ${BASEPATH}/build || exit
|
||||
cmake ${BASEPATH}
|
||||
make
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/**
|
||||
* 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 <algorithm>
|
||||
#include <random>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "include/errorcode.h"
|
||||
#include "include/model.h"
|
||||
#include "include/context.h"
|
||||
#include "include/lite_session.h"
|
||||
namespace mindspore {
|
||||
namespace lite {
|
||||
namespace {
|
||||
constexpr int kNumPrintOfOutData = 20;
|
||||
std::string RealPath(const char *path) {
|
||||
const size_t max = 4096;
|
||||
if (path == nullptr) {
|
||||
std::cerr << "path is nullptr" << std::endl;
|
||||
return "";
|
||||
}
|
||||
if ((strlen(path)) >= max) {
|
||||
std::cerr << "path is too long" << std::endl;
|
||||
return "";
|
||||
}
|
||||
auto resolved_path = std::make_unique<char[]>(max);
|
||||
if (resolved_path == nullptr) {
|
||||
std::cerr << "new resolved_path failed" << std::endl;
|
||||
return "";
|
||||
}
|
||||
#ifdef _WIN32
|
||||
char *real_path = _fullpath(resolved_path.get(), path, 1024);
|
||||
#else
|
||||
char *real_path = realpath(path, resolved_path.get());
|
||||
#endif
|
||||
if (real_path == nullptr || strlen(real_path) == 0) {
|
||||
std::cerr << "file path is not valid : " << path << std::endl;
|
||||
return "";
|
||||
}
|
||||
std::string res = resolved_path.get();
|
||||
return res;
|
||||
}
|
||||
|
||||
char *ReadFile(const char *file, size_t *size) {
|
||||
if (file == nullptr) {
|
||||
std::cerr << "file is nullptr." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::ifstream ifs(file);
|
||||
if (!ifs.good()) {
|
||||
std::cerr << "file: " << file << " is not exist." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ifs.is_open()) {
|
||||
std::cerr << "file: " << file << " open failed." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ifs.seekg(0, std::ios::end);
|
||||
*size = ifs.tellg();
|
||||
std::unique_ptr<char[]> buf(new (std::nothrow) char[*size]);
|
||||
if (buf == nullptr) {
|
||||
std::cerr << "malloc buf failed, file: " << file << std::endl;
|
||||
ifs.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
ifs.read(buf.get(), *size);
|
||||
ifs.close();
|
||||
|
||||
return buf.release();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename T, typename Distribution>
|
||||
void GenerateRandomData(int size, void *data, Distribution distribution) {
|
||||
std::mt19937 random_engine;
|
||||
int elements_num = size / sizeof(T);
|
||||
(void)std::generate_n(static_cast<T *>(data), elements_num,
|
||||
[&distribution, &random_engine]() { return static_cast<T>(distribution(random_engine)); });
|
||||
}
|
||||
|
||||
int GenerateInputDataWithRandom(std::vector<mindspore::tensor::MSTensor *> inputs) {
|
||||
for (auto tensor : inputs) {
|
||||
auto input_data = tensor->MutableData();
|
||||
if (input_data == nullptr) {
|
||||
std::cerr << "MallocData for inTensor failed." << std::endl;
|
||||
return RET_ERROR;
|
||||
}
|
||||
GenerateRandomData<float>(tensor->Size(), input_data, std::uniform_real_distribution<float>(1.0f, 1.0f));
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int Run(mindspore::session::LiteSession *session) {
|
||||
auto inputs = session->GetInputs();
|
||||
|
||||
// Generate random data as input data.
|
||||
auto ret = GenerateInputDataWithRandom(inputs);
|
||||
if (ret != RET_OK) {
|
||||
std::cerr << "Generate Random Input Data failed." << std::endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Run Inference.
|
||||
ret = session->RunGraph();
|
||||
if (ret != RET_OK) {
|
||||
std::cerr << "Inference error " << ret << std::endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get Output Tensor Data.
|
||||
auto out_tensors = session->GetOutputs();
|
||||
for (auto tensor : out_tensors) {
|
||||
std::cout << "tensor name is:" << tensor.first << " tensor size is:" << tensor.second->Size()
|
||||
<< " tensor elements num is:" << tensor.second->ElementsNum() << std::endl;
|
||||
auto out_data = reinterpret_cast<float *>(tensor.second->MutableData());
|
||||
std::cout << "output data is:";
|
||||
for (int i = 0; i < tensor.second->ElementsNum() && i <= kNumPrintOfOutData; i++) {
|
||||
std::cout << out_data[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
mindspore::session::LiteSession *Compile(mindspore::lite::Model *model) {
|
||||
// Create and init context.
|
||||
auto context = std::make_shared<Context>();
|
||||
if (context == nullptr) {
|
||||
std::cerr << "New context failed while." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
context->device_list_[0].provider_ = "Tutorial";
|
||||
context->device_list_[0].provider_device_ = "Tutorial";
|
||||
// Create the session.
|
||||
auto *session = mindspore::session::LiteSession::CreateSession(context.get());
|
||||
if (session == nullptr) {
|
||||
std::cerr << "CreateSession failed while running." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Compile graph.
|
||||
auto ret = session->CompileGraph(model);
|
||||
if (ret != RET_OK) {
|
||||
delete session;
|
||||
std::cerr << "Compile failed while running." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
int CompileAndRun(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Model file must be provided.\n";
|
||||
return RET_ERROR;
|
||||
}
|
||||
// Read model file.
|
||||
auto model_path = RealPath(argv[1]);
|
||||
if (model_path.empty()) {
|
||||
std::cerr << "model path " << argv[1] << " is invalid.";
|
||||
return RET_ERROR;
|
||||
}
|
||||
size_t size = 0;
|
||||
char *model_buf = ReadFile(model_path.c_str(), &size);
|
||||
if (model_buf == nullptr) {
|
||||
std::cerr << "Read model file failed." << std::endl;
|
||||
return RET_ERROR;
|
||||
}
|
||||
// Load the .ms model.
|
||||
auto model = Model::Import(model_buf, size);
|
||||
delete[](model_buf);
|
||||
if (model == nullptr) {
|
||||
std::cerr << "Import model file failed." << std::endl;
|
||||
return RET_ERROR;
|
||||
}
|
||||
// Compile MindSpore Lite model.
|
||||
auto session = Compile(model);
|
||||
if (session == nullptr) {
|
||||
delete model;
|
||||
std::cerr << "Create session failed." << std::endl;
|
||||
return RET_ERROR;
|
||||
}
|
||||
// Run inference.
|
||||
auto ret = Run(session);
|
||||
if (ret != RET_OK) {
|
||||
delete model;
|
||||
delete session;
|
||||
std::cerr << "MindSpore Lite run failed." << std::endl;
|
||||
return RET_ERROR;
|
||||
}
|
||||
// Delete model buffer.
|
||||
delete model;
|
||||
// Delete session buffer.
|
||||
delete session;
|
||||
return RET_OK;
|
||||
}
|
||||
} // namespace lite
|
||||
} // namespace mindspore
|
||||
|
||||
int main(int argc, const char **argv) { return mindspore::lite::CompileAndRun(argc, argv); }
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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_common.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "include/registry/kernel_interface.h"
|
||||
|
||||
namespace mindspore {
|
||||
/**
|
||||
* CustomAddInfer is a child class to infer current node output's information, including format, data_type and shape.
|
||||
* if inputs' shape exist -1, don't worry, which shows that shape will be inferred when running.
|
||||
*/
|
||||
class CustomAddInfer : public kernel::KernelInterface {
|
||||
public:
|
||||
CustomAddInfer() = default;
|
||||
~CustomAddInfer() = default;
|
||||
|
||||
int Infer(const std::vector<tensor::MSTensor *> &inputs, const std::vector<tensor::MSTensor *> &outputs,
|
||||
const schema::Primitive *primitive) override {
|
||||
outputs[0]->set_format(inputs[0]->format());
|
||||
outputs[0]->set_data_type(inputs[0]->data_type());
|
||||
auto ret = common::CheckInputs(inputs);
|
||||
if (ret != lite::RET_OK) {
|
||||
outputs[0]->set_shape({-1}); // shape{-1} shows that shape need to be inferred when running.
|
||||
return ret;
|
||||
}
|
||||
outputs[0]->set_shape(inputs[0]->shape());
|
||||
return lite::RET_OK;
|
||||
}
|
||||
};
|
||||
std::shared_ptr<kernel::KernelInterface> CustomAddInferCreator() { return std::make_shared<CustomAddInfer>(); }
|
||||
REGISTER_CUSTOM_KERNEL_INTERFACE(Tutorial, Custom_Add, CustomAddInferCreator)
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* 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 <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "src/custom_common.h"
|
||||
#include "include/errorcode.h"
|
||||
#include "include/registry/kernel_interface.h"
|
||||
#include "include/registry/register_kernel.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace kernel {
|
||||
class CustomAddKernel : public Kernel {
|
||||
public:
|
||||
CustomAddKernel(const std::vector<tensor::MSTensor *> &inputs, const std::vector<tensor::MSTensor *> &outputs,
|
||||
const schema::Primitive *primitive, const lite::Context *ctx)
|
||||
: Kernel(inputs, outputs, primitive, ctx) {}
|
||||
// Prepare will be called during graph compilation
|
||||
int Prepare() override { return lite::RET_OK; }
|
||||
|
||||
// Execute is called to compute.
|
||||
int Execute() override {
|
||||
if (inputs_.size() != 2) {
|
||||
return lite::RET_PARAM_INVALID;
|
||||
}
|
||||
PreProcess();
|
||||
ParseAttrData();
|
||||
float *in0 = static_cast<float *>(inputs_[0]->data());
|
||||
float *in1 = static_cast<float *>(inputs_[1]->data());
|
||||
float *out = static_cast<float *>(outputs_[0]->data());
|
||||
auto num = outputs_[0]->ElementsNum();
|
||||
for (int i = 0; i < num; ++i) {
|
||||
out[i] = in0[i] + in1[i];
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
|
||||
// Resize is used to update some parameters if current node can change along with inputs.
|
||||
int ReSize() override { return lite::RET_OK; }
|
||||
|
||||
private:
|
||||
// if output shape exists value -1, need to be inferred before applying memory for output tensor.
|
||||
int PreProcess() {
|
||||
if (common::CheckOutputs(outputs_) != lite::RET_OK) {
|
||||
auto ret = RegisterKernelInterface::GetKernelInterface({}, primitive_)->Infer(inputs_, outputs_, primitive_);
|
||||
if (ret != lite::RET_OK) {
|
||||
std::cerr << "infer failed." << std::endl;
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
ret = ReSize();
|
||||
if (ret != lite::RET_OK) {
|
||||
std::cerr << "resize failed." << std::endl;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
for (auto *output : outputs_) {
|
||||
// malloc data for output tensor
|
||||
auto data = output->MutableData();
|
||||
if (data == nullptr) {
|
||||
std::cerr << "Get data failed" << std::endl;
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
|
||||
// fetch attributes if user need.
|
||||
void ParseAttrData() {
|
||||
auto prim = primitive_->value_as_Custom();
|
||||
if (prim->attr()->size() < 1) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < prim->attr()->size(); ++i) {
|
||||
auto attr = prim->attr()->Get(0);
|
||||
auto attr_key = attr->name()->str();
|
||||
auto data_bytes = attr->data();
|
||||
auto data_size = data_bytes->size();
|
||||
char buf[100];
|
||||
for (size_t j = 0; j < data_size; ++j) {
|
||||
buf[j] = static_cast<char>(data_bytes->Get(j));
|
||||
}
|
||||
buf[data_size] = 0;
|
||||
attrs_[attr_key] = std::string(buf);
|
||||
}
|
||||
}
|
||||
std::map<std::string, std::string> attrs_;
|
||||
};
|
||||
|
||||
std::shared_ptr<Kernel> CustomAddCreator(const std::vector<tensor::MSTensor *> &inputs,
|
||||
const std::vector<tensor::MSTensor *> &outputs,
|
||||
const schema::Primitive *primitive, const lite::Context *ctx) {
|
||||
return std::make_shared<CustomAddKernel>(inputs, outputs, primitive, ctx);
|
||||
}
|
||||
REGISTER_CUSTOM_KERNEL(CPU, Tutorial, kNumberTypeFloat32, Custom_Add, CustomAddCreator)
|
||||
} // namespace kernel
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* 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_common.h"
|
||||
#include <vector>
|
||||
|
||||
namespace mindspore {
|
||||
namespace common {
|
||||
int CheckInputs(const std::vector<tensor::MSTensor *> &inputs) {
|
||||
for (auto &input : inputs) {
|
||||
auto input_shape = input->shape();
|
||||
if (std::find(input_shape.begin(), input_shape.end(), -1) != input_shape.end()) {
|
||||
return lite::RET_INFER_INVALID;
|
||||
}
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
|
||||
int CheckOutputs(const std::vector<tensor::MSTensor *> &outputs) {
|
||||
for (auto &output : outputs) {
|
||||
auto output_shape = output->shape();
|
||||
if (std::find(output_shape.begin(), output_shape.end(), -1) != output_shape.end()) {
|
||||
return lite::RET_INFER_INVALID;
|
||||
}
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
} // namespace common
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
#define MINDSPORE_LITE_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
|
||||
#include <vector>
|
||||
#include "include/errorcode.h"
|
||||
#include "include/ms_tensor.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace common {
|
||||
// verify that the inputs' shape is inferred successfully when inferring current node.
|
||||
int CheckInputs(const std::vector<tensor::MSTensor *> &inputs);
|
||||
|
||||
// versify that the outputs' shape is inferred successfully when running current node.
|
||||
int CheckOutputs(const std::vector<tensor::MSTensor *> &outputs);
|
||||
} // namespace common
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_LITE_EXAMPLES_RUNTIME_REGISTRY_SRC_CUSTOM_COMMON_H
|
||||
Loading…
Reference in New Issue