!19180 [lite]demo tutorial for extend api

Merge pull request !19180 from 徐安越/master_core
This commit is contained in:
i-robot 2021-07-05 10:22:04 +00:00 committed by Gitee
commit 164d430246
14 changed files with 860 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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