sync kernel executor code.

This commit is contained in:
wangpingan2 2022-10-24 15:30:59 +08:00
parent f696a828cf
commit 20d6596026
9 changed files with 1019 additions and 104 deletions

View File

@ -609,20 +609,6 @@ if(PLATFORM_ARM64)
endif()
endif()
endif()
if(MSLITE_ENABLE_KERNEL_EXECUTOR)
install(DIRECTORY ${TOP_DIR}/mindspore/core/ops/ DESTINATION ${RUNTIME_INC_DIR}/core/ops
COMPONENT ${RUNTIME_COMPONENT_NAME} FILES_MATCHING PATTERN "*.h")
install(DIRECTORY ${TOP_DIR}/mindspore/core/mindapi/ DESTINATION ${RUNTIME_INC_DIR}/core/mindapi
COMPONENT ${RUNTIME_COMPONENT_NAME} FILES_MATCHING PATTERN "*.h")
install(FILES ${TOP_DIR}/mindspore/lite/src/litert/cxx_api/kernel_executor/kernel_executor.h DESTINATION
${RUNTIME_INC_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS kernel_executor DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS mindspore_core DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
if(MSLITE_ENABLE_CONVERTER)
install(FILES ${glog_LIBPATH}/libmindspore_glog.so.0.4.0 DESTINATION ${GLOG_DIR}
RENAME libmindspore_glog.so.0 COMPONENT ${RUNTIME_COMPONENT_NAME})
endif()
endif()
elseif(PLATFORM_ARM32)
if(SUPPORT_NPU)
install(FILES ${DDK_LIB_PATH}/libhiai.so DESTINATION ${RUNTIME_DIR}/third_party/hiai_ddk/lib
@ -1014,19 +1000,66 @@ else()
endif()
endif()
endif()
if(MSLITE_ENABLE_KERNEL_EXECUTOR)
install(DIRECTORY ${TOP_DIR}/mindspore/core/ops/ DESTINATION ${RUNTIME_INC_DIR}/core/ops
COMPONENT ${RUNTIME_COMPONENT_NAME} FILES_MATCHING PATTERN "*.h")
install(DIRECTORY ${TOP_DIR}/mindspore/core/mindapi/ DESTINATION ${RUNTIME_INC_DIR}/core/mindapi
COMPONENT ${RUNTIME_COMPONENT_NAME} FILES_MATCHING PATTERN "*.h")
install(FILES ${TOP_DIR}/mindspore/lite/src/litert/cxx_api/kernel_executor/kernel_executor.h DESTINATION
${RUNTIME_INC_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS kernel_executor DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS mindspore_core DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
if(MSLITE_ENABLE_CONVERTER)
install(FILES ${glog_LIBPATH}/libmindspore_glog.so.0.4.0
DESTINATION ${GLOG_DIR} RENAME libmindspore_glog.so.0 COMPONENT ${RUNTIME_COMPONENT_NAME})
endif()
endif()
if(MSLITE_ENABLE_KERNEL_EXECUTOR)
install(FILES
${TOP_DIR}/mindspore/core/ops/abs.h
${TOP_DIR}/mindspore/core/ops/batch_norm.h
${TOP_DIR}/mindspore/core/ops/ceil.h
${TOP_DIR}/mindspore/core/ops/concat.h
${TOP_DIR}/mindspore/core/ops/equal.h
${TOP_DIR}/mindspore/core/ops/flatten.h
${TOP_DIR}/mindspore/core/ops/gather.h
${TOP_DIR}/mindspore/core/ops/gather_nd.h
${TOP_DIR}/mindspore/core/ops/maximum.h
${TOP_DIR}/mindspore/core/ops/minimum.h
${TOP_DIR}/mindspore/core/ops/reshape.h
${TOP_DIR}/mindspore/core/ops/softmax.h
${TOP_DIR}/mindspore/core/ops/strided_slice.h
${TOP_DIR}/mindspore/core/ops/transpose.h
${TOP_DIR}/mindspore/core/ops/base_operator.h
${TOP_DIR}/mindspore/core/ops/custom.h
${TOP_DIR}/mindspore/core/ops/add.h
${TOP_DIR}/mindspore/core/ops/arg_max.h
${TOP_DIR}/mindspore/core/ops/arg_min.h
${TOP_DIR}/mindspore/core/ops/avg_pool.h
${TOP_DIR}/mindspore/core/ops/conv2d.h
${TOP_DIR}/mindspore/core/ops/conv2d_transpose.h
${TOP_DIR}/mindspore/core/ops/div.h
${TOP_DIR}/mindspore/core/ops/mat_mul.h
${TOP_DIR}/mindspore/core/ops/max_pool.h
${TOP_DIR}/mindspore/core/ops/mul.h
${TOP_DIR}/mindspore/core/ops/pad.h
${TOP_DIR}/mindspore/core/ops/prelu.h
${TOP_DIR}/mindspore/core/ops/topk.h
${TOP_DIR}/mindspore/core/ops/relu.h
${TOP_DIR}/mindspore/core/ops/sigmoid.h
DESTINATION ${RUNTIME_INC_DIR}/ops
COMPONENT ${RUNTIME_COMPONENT_NAME})
install(FILES
${TOP_DIR}/mindspore/core/mindapi/base/format.h
${TOP_DIR}/mindspore/core/mindapi/base/type_id.h
${TOP_DIR}/mindspore/core/mindapi/base/types.h
${TOP_DIR}/mindspore/core/mindapi/base/macros.h
${TOP_DIR}/mindspore/core/mindapi/base/shared_ptr.h
${TOP_DIR}/mindspore/core/mindapi/base/type_traits.h
${TOP_DIR}/mindspore/core/mindapi/base/base.h
DESTINATION ${RUNTIME_INC_DIR}/mindapi/base
COMPONENT ${RUNTIME_COMPONENT_NAME})
install(FILES
${TOP_DIR}/mindspore/core/mindapi/ir/common.h
${TOP_DIR}/mindspore/core/mindapi/ir/primitive.h
${TOP_DIR}/mindspore/core/mindapi/ir/value.h
DESTINATION ${RUNTIME_INC_DIR}/mindapi/ir
COMPONENT ${RUNTIME_COMPONENT_NAME})
install(FILES ${TOP_DIR}/mindspore/lite/src/litert/cxx_api/kernel_executor/kernel_executor.h DESTINATION
${RUNTIME_INC_DIR}/api COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS kernel_executor DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
install(TARGETS mindspore_core DESTINATION ${RUNTIME_LIB_DIR} COMPONENT ${RUNTIME_COMPONENT_NAME})
if(MSLITE_ENABLE_CONVERTER)
install(FILES ${glog_LIBPATH}/libmindspore_glog.so.0.4.0 DESTINATION ${RUNTIME_LIB_DIR}
RENAME libmindspore_glog.so.0 COMPONENT ${RUNTIME_COMPONENT_NAME})
endif()
endif()

View File

@ -15,6 +15,7 @@ endif()
add_library(kernel_executor SHARED
${CMAKE_CURRENT_SOURCE_DIR}/kernel_executor.cc
${CMAKE_CURRENT_SOURCE_DIR}/kernel_executor_impl.cc
${CMAKE_CURRENT_SOURCE_DIR}/op_converter.cc
${TOP_DIR}/mindspore/lite/src/common/ops/ops_utils.cc
${TOP_DIR}/mindspore/lite/src/common/primitive_t_utils.cc
${TOP_DIR}/mindspore/lite/src/common/ops/ops_def.cc)
@ -25,7 +26,6 @@ target_link_libraries(kernel_executor
mindspore-lite
mindspore_core
mindspore::json
mindspore::protobuf
mindspore::flatbuffers)
if(USE_GLOG)

View File

@ -59,7 +59,7 @@ class MS_API KernelExecutor {
const std::shared_ptr<Context> &ms_context, const int output_num);
/// \brief ReSize KernelExecutor. Change the shape and data type of inputs.
/// Notice: Conv2DFusion can't update weight and bias by this method.
/// Notice: Conv2D can't update weight and bias by this method.
///
/// \param[in] inputs A vector where single operator inputs are arranged in sequence.
///
@ -69,7 +69,9 @@ class MS_API KernelExecutor {
/// \brief Execute KernelExecutor.
///
/// \param[in] inputs A vector where single operator inputs are arranged in sequence.
/// Notices: inputs Tensor should be freed by user.
/// \param[in] outputs Which is a pointer to a vector.The outputs are filled in the container in sequence.
/// Notices: outputs Tensor will be freed by ~KernelExecutorImpl(), user needn't free it.
///
/// \return Status.
Status Execute(const std::vector<MSTensor> &inputs, std::vector<MSTensor> *outputs);

View File

@ -27,25 +27,31 @@
#include "src/litert/infer_manager.h"
#include "src/litert/kernel_registry.h"
#include "src/litert/cxx_api/kernel_executor/kernel_executor_impl.h"
#include "src/litert/cxx_api/kernel_executor/op_converter.h"
#include "src/litert/cpu_info.h"
namespace mindspore {
namespace {
constexpr size_t INITIAL_SIZE = 1024;
std::unordered_set<std::string> support_ops = {
"Abs", "Activation", "AddFusion", "ArgMaxFusion", "ArgMinFusion", "AvgPoolFusion",
"BatchNorm", "Ceil", "Concat", "Custom", "Conv2DFusion", "Conv2dTransposeFusion",
"DivFusion", "Equal", "Flatten", "Gather", "GatherNd", "MatMulFusion",
"Maximum", "MaxPoolFusion", "Minimum", "MulFusion", "PadFusion", "PReLUFusion",
"Range", "Reshape", "Resize", "Softmax", "StridedSlice", "TopKFusion",
"Transpose", "Where",
"Abs", "ReLU", "Sigmoid", "Add", "Argmax", "Argmin", "AvgPool",
"BatchNorm", "Ceil", "Concat", "Custom", "Conv2D", "Conv2DTranspose", "Div",
"Equal", "Flatten", "Gather", "GatherNd", "MatMul", "Maximum", "MaxPool",
"Minimum", "Mul", "Pad", "PReLU", "Reshape", "Softmax", "StridedSlice",
"TopK", "Transpose",
};
std::unordered_map<std::string, int> ops_output_num = {
{"ArgMaxFusion", 2},
{"ArgMinFusion", 2},
{"TopKFusion", 2},
{"TopK", 2},
};
} // namespace
KernelExecutorImpl::KernelExecutorImpl() {
fbb_ = std::make_shared<flatbuffers::FlatBufferBuilder>();
#if defined(ENABLE_ARM) && defined(ENABLE_FP16)
lite::CpuInfo cpu_info;
support_fp16_ = cpu_info.ArmIsSupportFp16();
#endif
}
KernelExecutorImpl::~KernelExecutorImpl() {
FreeAllResource();
inputs_.clear();
@ -67,7 +73,10 @@ Status KernelExecutorImpl::Build(const std::shared_ptr<ops::BaseOperator> &op, c
return kLiteError;
} else {
int output_num = ops_output_num.find(op_name) != ops_output_num.end() ? ops_output_num.at(op_name) : 1;
InitTensors(inputs, output_num);
status = InitTensors(inputs, output_num);
if (status != kSuccess) {
return status;
}
status = GetCpuKernel(ms_context);
}
@ -95,7 +104,10 @@ Status KernelExecutorImpl::Build(const std::shared_ptr<ops::Custom> &op, const s
if (status != kSuccess) {
return status;
}
InitTensors(inputs, output_num);
status = InitTensors(inputs, output_num);
if (status != kSuccess) {
return status;
}
status = GetCustomKernel(ms_context);
if (status != kSuccess) {
MS_LOG(ERROR) << "get custom kernel error.";
@ -120,7 +132,10 @@ Status KernelExecutorImpl::ReSize(const std::vector<MSTensor> &inputs) {
MS_LOG(ERROR) << "wrong inputs size.";
return kLiteError;
}
InitTensors(inputs, 0);
auto status = InitTensors(inputs, 0);
if (status != kSuccess) {
return status;
}
kernel_->set_in_tensors(inputs_);
kernel_->set_out_tensors(outputs_);
int ret;
@ -131,6 +146,7 @@ Status KernelExecutorImpl::ReSize(const std::vector<MSTensor> &inputs) {
}
if (ret != RET_OK) {
MS_LOG(ERROR) << "do infer shape error.";
FreeAllResource();
return static_cast<StatusCode>(ret);
}
ret = kernel_->ReSize();
@ -169,6 +185,7 @@ Status KernelExecutorImpl::Execute(const std::vector<MSTensor> &inputs, std::vec
}
auto lite_impl = std::static_pointer_cast<LiteTensorImpl>(user_input.impl());
inputs_[i] = static_cast<lite::Tensor *>(lite_impl->lite_tensor());
inputs_[i]->set_category(lite::Category::GRAPH_INPUT);
}
kernel_->set_in_tensors(inputs_);
int ret = kernel_->Execute();
@ -197,15 +214,24 @@ Status KernelExecutorImpl::BuildInit(const std::shared_ptr<ops::BaseOperator> &o
return kLiteNullptr;
}
FreeAllResource();
data_type_ = static_cast<enum TypeId>(inputs[FIRST_INPUT].DataType());
if (data_type_ != kNumberTypeInt8 && data_type_ != kNumberTypeFloat16 && data_type_ != kNumberTypeFloat32) {
MS_LOG(ERROR) << "unsupported datatype.";
return kLiteNullptr;
auto converter_op = op;
auto op_creator = lite::OpsConverterRegistry::GetInstance()->GetOpsConverterCreator(op->name());
if (op_creator != nullptr) {
converter_op = op_creator(op);
}
std::unique_ptr<mindspore::schema::PrimitiveT> prim_t = lite::GetPrimitiveT(op);
flatbuffers::FlatBufferBuilder fbb(INITIAL_SIZE);
primitive_ = lite::ConvertToPrimitive(prim_t.get(), &fbb);
fbb.Clear();
data_type_ = static_cast<enum TypeId>(inputs[FIRST_INPUT].DataType());
if (op->name() != "Custom") {
if (data_type_ != kNumberTypeFloat32 && data_type_ != kNumberTypeFloat16) {
MS_LOG(ERROR) << "unsupported datatype.";
return kLiteError;
} else if (data_type_ == kNumberTypeFloat16 && !support_fp16_) {
MS_LOG(ERROR) << "inputs dataType is Fp16 but Hw cap NOT support FP16.";
return kLiteError;
}
}
std::unique_ptr<mindspore::schema::PrimitiveT> prim_t = lite::GetPrimitiveT(converter_op);
primitive_ = lite::ConvertToPrimitive(prim_t.get(), fbb_.get());
if (primitive_ == nullptr) {
MS_LOG(ERROR) << "convert to primitive nullptr.";
return kLiteNullptr;
@ -255,14 +281,17 @@ Status KernelExecutorImpl::GetCustomKernel(const std::shared_ptr<Context> &ms_co
get_kernel = lite::KernelRegistry::GetInstance()->GetKernelExec(inputs_, outputs_, context_.get(), ms_context.get(),
desc, nullptr, &kernel_, primitive_);
}
// if found kernel, do infershape
if (get_kernel == RET_OK) {
int ret = KernelInferShape(inputs_, outputs_, primitive_, context_->GetProviders(), schema_version_);
return static_cast<StatusCode>(ret);
if (get_kernel != RET_OK) {
MS_LOG(ERROR) << "get custom KernelExec error.";
return static_cast<StatusCode>(get_kernel);
}
return static_cast<StatusCode>(get_kernel);
int ret = KernelInferShape(inputs_, outputs_, primitive_, context_->GetProviders(), schema_version_);
if (ret != RET_OK) {
MS_LOG(ERROR) << "custom kernel infer shape error. please check inputs size and shape.";
return static_cast<StatusCode>(ret);
}
return kSuccess;
}
Status KernelExecutorImpl::GetCpuKernel(const std::shared_ptr<Context> &ms_context) {
@ -274,38 +303,40 @@ Status KernelExecutorImpl::GetCpuKernel(const std::shared_ptr<Context> &ms_conte
kernel::KernelKey desc{kernel::KERNEL_ARCH::kCPU, data_type_, NHWC, prim_type_};
int get_kernel = lite::KernelRegistry::GetInstance()->GetKernelExec(inputs_, outputs_, context_.get(),
ms_context.get(), desc, parameter_, &kernel_);
if (get_kernel == RET_OK) {
int ret = KernelInferShape(inputs_, outputs_, parameter_);
return static_cast<StatusCode>(ret);
if (get_kernel != RET_OK) {
MS_LOG(ERROR) << "get cpu KernelExec error.";
return static_cast<StatusCode>(get_kernel);
}
return static_cast<StatusCode>(get_kernel);
int ret = KernelInferShape(inputs_, outputs_, parameter_);
if (ret != RET_OK) {
MS_LOG(ERROR) << "cpu kernel infer shape error. please check inputs size and shape.";
return static_cast<StatusCode>(ret);
}
return kSuccess;
}
void KernelExecutorImpl::InitTensors(const std::vector<MSTensor> &inputs, const int output_num) {
Status KernelExecutorImpl::InitTensors(const std::vector<MSTensor> &inputs, const int output_num) {
inputs_.clear();
for (const auto &tensor : inputs) {
if (tensor.impl() == nullptr) {
MS_LOG(ERROR) << "Tensor " << tensor.Name() << " is nullptr.";
return kLiteNullptr;
}
auto lite_impl = std::static_pointer_cast<LiteTensorImpl>(tensor.impl());
auto lite_tensor = static_cast<lite::Tensor *>(lite_impl->lite_tensor());
if (data_type_ == kNumberTypeInt8 && lite_tensor->quant_params().empty()) {
Int8TensorAddQuantParam(lite_tensor);
}
inputs_.emplace_back(lite_tensor);
}
for (int i = 0; i < output_num; ++i) {
lite::Tensor *output_tensor = new (std::nothrow) lite::Tensor();
if (output_tensor == nullptr) {
MS_LOG(ERROR) << "Failed to allocate tensor.";
return kLiteNullptr;
}
output_tensor->set_category(lite::Category::VAR);
if (data_type_ == kNumberTypeInt8) {
Int8TensorAddQuantParam(output_tensor);
}
outputs_.emplace_back(output_tensor);
}
return kSuccess;
}
void KernelExecutorImpl::FreeAllResource() {
@ -374,11 +405,4 @@ bool KernelExecutorImpl::TensorIsValid(const MSTensor &ms_tensor, const lite::Te
}
return true;
}
void KernelExecutorImpl::Int8TensorAddQuantParam(lite::Tensor *lite_tensor) {
lite::LiteQuantParam quant_param;
quant_param.scale = 1;
quant_param.zeroPoint = 0;
lite_tensor->set_quant_params({quant_param});
}
} // namespace mindspore

View File

@ -26,7 +26,7 @@
namespace mindspore {
class KernelExecutorImpl {
public:
KernelExecutorImpl() = default;
KernelExecutorImpl();
~KernelExecutorImpl();
Status Build(const std::shared_ptr<ops::BaseOperator> &op, const std::vector<MSTensor> &inputs,
const std::shared_ptr<Context> &ms_context);
@ -41,11 +41,10 @@ class KernelExecutorImpl {
Status GetCustomKernel(const std::shared_ptr<Context> &ms_context);
Status GetCpuKernel(const std::shared_ptr<Context> &ms_context);
Status GetOpParameter();
void InitTensors(const std::vector<MSTensor> &inputs, const int output_num);
Status InitTensors(const std::vector<MSTensor> &inputs, const int output_num);
void FreeAllResource();
std::vector<MSTensor> GetOutputs();
bool TensorIsValid(const MSTensor &ms_tensor, const lite::Tensor *lite_tensor);
void Int8TensorAddQuantParam(lite::Tensor *lite_tensor);
private:
const schema::Primitive *primitive_ = nullptr;
@ -57,6 +56,8 @@ class KernelExecutorImpl {
std::vector<lite::Tensor *> inputs_;
std::vector<lite::Tensor *> outputs_;
int schema_version_ = lite::SCHEMA_VERSION::SCHEMA_CUR;
std::shared_ptr<flatbuffers::FlatBufferBuilder> fbb_;
bool support_fp16_ = false;
};
} // namespace mindspore
#endif // MINDSPORE_LITE_SRC_RUNTIME_CXX_API_KERNEL_EXECUTOR_KERNEL_EXECUTOR_IMPL_H_

View File

@ -0,0 +1,106 @@
/**
* 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 "src/litert/cxx_api/kernel_executor/op_converter.h"
#include "ops/relu.h"
#include "ops/fusion/activation.h"
#include "ops/fusion/add_fusion.h"
#include "ops/fusion/arg_max_fusion.h"
#include "ops/fusion/arg_min_fusion.h"
#include "ops/fusion/avg_pool_fusion.h"
#include "ops/fused_batch_norm.h"
#include "ops/batch_norm.h"
#include "ops/fusion/conv2d_fusion.h"
#include "ops/fusion/conv2d_transpose_fusion.h"
#include "ops/fusion/div_fusion.h"
#include "ops/fusion/mat_mul_fusion.h"
#include "ops/fusion/max_pool_fusion.h"
#include "ops/fusion/mul_fusion.h"
#include "ops/fusion/pad_fusion.h"
#include "ops/fusion/prelu_fusion.h"
#include "ops/fusion/topk_fusion.h"
namespace mindspore {
namespace lite {
std::shared_ptr<ops::BaseOperator> ReLUConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_converter = std::make_shared<ops::Activation>();
op_converter->set_activation_type(ActivationType::RELU);
return op_converter;
}
std::shared_ptr<ops::BaseOperator> SigmoidConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_converter = std::make_shared<ops::Activation>();
op_converter->set_activation_type(ActivationType::SIGMOID);
return op_converter;
}
template <class T, class T2>
std::shared_ptr<ops::BaseOperator> CommonConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_cast = std::dynamic_pointer_cast<T>(op);
auto op_converter = std::make_shared<T2>();
op_converter->SetAttrs(op_cast->attrs());
return op_converter;
}
std::shared_ptr<ops::BaseOperator> ArgMinConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_converter = CommonConverterCreators<ops::ArgMin, ops::ArgMinFusion>(op);
auto op_arg = std::dynamic_pointer_cast<ops::ArgMinFusion>(op_converter);
op_arg->set_top_k(1);
op_arg->set_keep_dims(true);
return op_converter;
}
std::shared_ptr<ops::BaseOperator> ArgMaxConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_converter = CommonConverterCreators<ops::Argmax, ops::ArgMaxFusion>(op);
auto op_arg = std::dynamic_pointer_cast<ops::ArgMaxFusion>(op_converter);
op_arg->set_top_k(1);
op_arg->set_keep_dims(true);
return op_converter;
}
std::shared_ptr<ops::BaseOperator> TopKConverterCreators(const std::shared_ptr<ops::BaseOperator> &op) {
auto op_converter = CommonConverterCreators<ops::TopK, ops::TopKFusion>(op);
auto op_topk = std::dynamic_pointer_cast<ops::TopKFusion>(op_converter);
op_topk->set_axis(-1);
return op_converter;
}
static RegistryOpsConverter g_ReLUConverterCreatorRegistry("ReLU", ReLUConverterCreators);
static RegistryOpsConverter g_SigmoidConverterCreatorRegistry("Sigmoid", SigmoidConverterCreators);
static RegistryOpsConverter g_AddConverterCreatorRegistry("Add", CommonConverterCreators<ops::Add, ops::AddFusion>);
static RegistryOpsConverter g_ArgmaxConverterCreatorRegistry("Argmax", ArgMaxConverterCreators);
static RegistryOpsConverter g_ArgminConverterCreatorRegistry("Argmin", ArgMinConverterCreators);
static RegistryOpsConverter g_AvgPoolConverterCreatorRegistry(
"AvgPool", CommonConverterCreators<ops::AvgPool, ops::AvgPoolFusion>);
static RegistryOpsConverter g_BatchNormConverterCreatorRegistry(
"BatchNorm", CommonConverterCreators<ops::BatchNorm, ops::FusedBatchNorm>);
static RegistryOpsConverter g_Conv2DConverterCreatorRegistry("Conv2D",
CommonConverterCreators<ops::Conv2D, ops::Conv2DFusion>);
static RegistryOpsConverter g_Conv2DTransposeConverterCreatorRegistry(
"Conv2DTranspose", CommonConverterCreators<ops::Conv2DTranspose, ops::Conv2dTransposeFusion>);
static RegistryOpsConverter g_DivConverterCreatorRegistry("Div", CommonConverterCreators<ops::Div, ops::DivFusion>);
static RegistryOpsConverter g_MatMulConverterCreatorRegistry("MatMul",
CommonConverterCreators<ops::MatMul, ops::MatMulFusion>);
static RegistryOpsConverter g_MaxPoolConverterCreatorRegistry(
"MaxPool", CommonConverterCreators<ops::MaxPool, ops::MaxPoolFusion>);
static RegistryOpsConverter g_MulConverterCreatorRegistry("Mul", CommonConverterCreators<ops::Mul, ops::MulFusion>);
static RegistryOpsConverter g_PadConverterCreatorRegistry("Pad", CommonConverterCreators<ops::Pad, ops::PadFusion>);
static RegistryOpsConverter g_PReLUConverterCreatorRegistry("PReLU",
CommonConverterCreators<ops::PReLU, ops::PReLUFusion>);
static RegistryOpsConverter g_TopkConverterCreatorRegistry("TopK", TopKConverterCreators);
} // namespace lite
} // namespace mindspore

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.
*/
#ifndef MINDSPORE_LITE_SRC_RUNTIME_CXX_API_KERNEL_EXECUTOR_OP_CONVERTER_H_
#define MINDSPORE_LITE_SRC_RUNTIME_CXX_API_KERNEL_EXECUTOR_OP_CONVERTER_H_
#include <string>
#include <memory>
#include <map>
#include "ops/base_operator.h"
#include "src/common/log_adapter.h"
#include "include/api/types.h"
namespace mindspore {
namespace lite {
typedef std::shared_ptr<mindspore::ops::BaseOperator> (*OpsConverterCreator)(
const std::shared_ptr<mindspore::ops::BaseOperator> &op);
class OpsConverterRegistry {
public:
static OpsConverterRegistry *GetInstance() {
static OpsConverterRegistry registry;
return &registry;
}
void InsertOpsMap(const std::string &name, OpsConverterCreator creator) { ops_converter_creators_[name] = creator; }
OpsConverterCreator GetOpsConverterCreator(const std::string &name) {
if (ops_converter_creators_.find(name) != ops_converter_creators_.end()) {
return ops_converter_creators_[name];
} else {
return nullptr;
}
}
protected:
std::map<std::string, OpsConverterCreator> ops_converter_creators_ = {};
};
class RegistryOpsConverter {
public:
RegistryOpsConverter(const std::string &name, OpsConverterCreator creator) noexcept {
OpsConverterRegistry::GetInstance()->InsertOpsMap(name, creator);
}
~RegistryOpsConverter() = default;
};
} // namespace lite
} // namespace mindspore
#endif

View File

@ -173,3 +173,8 @@ if [ "$MSLITE_ENABLE_SERVER_INFERENCE" = on ];then
echo 'run ModelParallelRunner api ut test'
./lite-test --gtest_filter="ModelParallelRunnerTest.*"
fi
if [ "$MSLITE_ENABLE_KERNEL_EXECUTOR" = on ];then
echo 'run kernel executor api ut test'
./lite-test --gtest_filter="KernelExecutorTest.*"
fi

View File

@ -13,76 +13,761 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vector>
#include "common/common_test.h"
#include "include/registry/register_kernel_interface.h"
#include "include/registry/register_kernel.h"
#include "src/litert/cxx_api/kernel_executor/kernel_executor.h"
#include "ops/add.h"
#include "ops/transpose.h"
#include "ops/arg_max.h"
#include "ops/batch_norm.h"
#include "ops/conv2d.h"
#include "ops/mat_mul.h"
#include "ops/topk.h"
#include "ops/arg_min.h"
#include "ops/avg_pool.h"
#include "ops/ceil.h"
#include "ops/concat.h"
#include "ops/conv2d_transpose.h"
#include "ops/flatten.h"
#include "ops/gather.h"
#include "ops/gather_nd.h"
#include "ops/maximum.h"
#include "ops/max_pool.h"
#include "ops/minimum.h"
#include "ops/mul.h"
#include "ops/pad.h"
#include "ops/prelu.h"
#include "ops/reshape.h"
#include "ops/softmax.h"
#include "ops/strided_slice.h"
#include "ops/abs.h"
#include "ops/div.h"
#include "ops/equal.h"
#include "ops/relu.h"
#include "ops/base_operator.h"
#include "ops/sigmoid.h"
#include "ops/addn.h"
namespace mindspore {
class KernelExecutorTest : public mindspore::CommonTest {
public:
KernelExecutorTest();
~KernelExecutorTest();
~KernelExecutorTest() = default;
protected:
std::shared_ptr<mindspore::ops::Abs> op_ = std::make_shared<mindspore::ops::Abs>();
std::shared_ptr<mindspore::Context> context_ = std::make_shared<mindspore::Context>();
float *input_data_;
std::shared_ptr<mindspore::KernelExecutor> kernel_executor_;
std::shared_ptr<mindspore::Context> context_;
std::vector<float> input_data_;
};
KernelExecutorTest::KernelExecutorTest() {
kernel_executor_ = std::make_shared<mindspore::KernelExecutor>();
context_ = std::make_shared<mindspore::Context>();
auto cpu_context = std::make_shared<mindspore::CPUDeviceInfo>();
context_->MutableDeviceInfo().push_back(cpu_context);
context_->SetThreadNum(1);
input_data_ = new float[12]{-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12};
input_data_ = {-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12};
}
KernelExecutorTest::~KernelExecutorTest() { delete[] input_data_; }
namespace {
const auto kFloat32 = DataType::kNumberTypeFloat32;
class CustomAddKernel : public kernel::Kernel {
public:
CustomAddKernel(const std::vector<MSTensor> &inputs, const std::vector<MSTensor> &outputs,
const schema::Primitive *primitive, const mindspore::Context *ctx)
: Kernel(inputs, outputs, primitive, ctx) {}
~CustomAddKernel() = default;
int Prepare() override { return static_cast<int>(kSuccess); }
int Execute() override {
const float *in0 = static_cast<const float *>(inputs_[0].Data().get());
const float *in1 = static_cast<const float *>(inputs_[1].Data().get());
float *out = static_cast<float *>(outputs_[0].MutableData());
auto num = outputs_[0].ElementNum();
for (int i = 0; i < num; ++i) {
out[i] = in0[i] + in1[i];
}
return static_cast<int>(kSuccess);
}
int ReSize() override { return static_cast<int>(kSuccess); }
};
std::shared_ptr<kernel::Kernel> CustomAddCreator(const std::vector<MSTensor> &inputs,
const std::vector<MSTensor> &outputs,
const schema::Primitive *primitive, const mindspore::Context *ctx) {
return std::make_shared<CustomAddKernel>(inputs, outputs, primitive, ctx);
}
REGISTER_CUSTOM_KERNEL(CPU, Tutorial, kFloat32, Custom_Add, CustomAddCreator)
class CustomAddInfer : public kernel::KernelInterface {
public:
CustomAddInfer() = default;
~CustomAddInfer() = default;
Status Infer(std::vector<mindspore::MSTensor> *inputs, std::vector<mindspore::MSTensor> *outputs,
const schema::Primitive *primitive) override {
(*outputs)[0].SetFormat((*inputs)[0].format());
(*outputs)[0].SetDataType((*inputs)[0].DataType());
(*outputs)[0].SetShape((*inputs)[0].Shape());
return kSuccess;
}
};
std::shared_ptr<kernel::KernelInterface> CustomAddInferCreator() { return std::make_shared<CustomAddInfer>(); }
REGISTER_CUSTOM_KERNEL_INTERFACE(CustomOpTurial, Custom_Add, CustomAddInferCreator)
} // namespace
TEST_F(KernelExecutorTest, TestBuild) {
auto kernel_executor = std::make_shared<mindspore::KernelExecutor>();
auto op = std::make_shared<ops::Abs>();
std::vector<mindspore::MSTensor> inputs_abs;
mindspore::MSTensor tensor_abs("Abs", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 3},
reinterpret_cast<void *>(input_data_), 12 * sizeof(float));
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs_abs.emplace_back(tensor_abs);
ASSERT_EQ(kernel_executor->Build(nullptr, {}, nullptr), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor->Build(op_, {}, nullptr), mindspore::kLiteError);
ASSERT_EQ(kernel_executor->Build(op_, inputs_abs, nullptr), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor->Build(op_, inputs_abs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Build(nullptr, {}, nullptr), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor_->Build(op, {}, nullptr), mindspore::kLiteError);
ASSERT_EQ(kernel_executor_->Build(op, inputs_abs, nullptr), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor_->Build(op, inputs_abs, context_), mindspore::kSuccess);
auto addn = std::make_shared<ops::AddN>();
ASSERT_EQ(kernel_executor_->Build(addn, inputs_abs, context_), mindspore::kLiteError);
tensor_abs.SetDataType(mindspore::DataType::kNumberTypeInt8);
ASSERT_EQ(kernel_executor_->Build(op, inputs_abs, context_), mindspore::kLiteError);
tensor_abs.SetDataType(mindspore::DataType::kNumberTypeFloat16);
ASSERT_EQ(kernel_executor_->Build(op, inputs_abs, context_), mindspore::kLiteError);
}
TEST_F(KernelExecutorTest, TestResize) {
auto kernel_executor = std::make_shared<mindspore::KernelExecutor>();
auto op = std::make_shared<ops::Abs>();
std::vector<mindspore::MSTensor> inputs_abs;
mindspore::MSTensor tensor_abs("Abs", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_), 12 * sizeof(float));
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs_abs.emplace_back(tensor_abs);
std::vector<mindspore::MSTensor> inputs_abs_resize;
mindspore::MSTensor tensor_abs_resize("Abs", mindspore::DataType::kNumberTypeFloat32, {1, 4, 3},
reinterpret_cast<void *>(input_data_), 12 * sizeof(float));
inputs_abs.emplace_back(tensor_abs_resize);
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs_abs_resize.emplace_back(tensor_abs_resize);
ASSERT_EQ(kernel_executor->ReSize({}), mindspore::kLiteNullptr);
kernel_executor->Build(op_, inputs_abs, context_);
ASSERT_EQ(kernel_executor->ReSize({}), mindspore::kLiteError);
ASSERT_EQ(kernel_executor->ReSize(inputs_abs_resize), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->ReSize({}), mindspore::kLiteNullptr);
kernel_executor_->Build(nullptr, {}, nullptr);
ASSERT_EQ(kernel_executor_->ReSize({}), mindspore::kLiteNullptr);
kernel_executor_->Build(op, inputs_abs, context_);
ASSERT_EQ(kernel_executor_->ReSize({}), mindspore::kLiteError);
ASSERT_EQ(kernel_executor_->ReSize(inputs_abs_resize), mindspore::kSuccess);
}
TEST_F(KernelExecutorTest, TestExecute) {
auto kernel_executor = std::make_shared<mindspore::KernelExecutor>();
auto op = std::make_shared<ops::Abs>();
std::vector<mindspore::MSTensor> inputs_abs;
std::vector<mindspore::MSTensor> outputs_abs;
mindspore::MSTensor tensor_abs("Abs", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_), 12 * sizeof(float));
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs_abs.emplace_back(tensor_abs);
ASSERT_EQ(kernel_executor->Execute(inputs_abs, &outputs_abs), mindspore::kLiteNullptr);
kernel_executor->Build(nullptr, inputs_abs, nullptr);
ASSERT_EQ(kernel_executor->Execute(inputs_abs, &outputs_abs), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor_->Execute(inputs_abs, &outputs_abs), mindspore::kLiteNullptr);
kernel_executor_->Build(nullptr, inputs_abs, nullptr);
ASSERT_EQ(kernel_executor_->Execute(inputs_abs, &outputs_abs), mindspore::kLiteNullptr);
kernel_executor->Build(op_, inputs_abs, context_);
ASSERT_EQ(kernel_executor->Execute(inputs_abs, &outputs_abs), mindspore::kSuccess);
kernel_executor_->Build(op, inputs_abs, context_);
ASSERT_EQ(kernel_executor_->Execute(inputs_abs, nullptr), mindspore::kLiteNullptr);
ASSERT_EQ(kernel_executor_->Execute(inputs_abs, &outputs_abs), mindspore::kSuccess);
float correct[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs_abs[0].MutableData()), correct,
outputs_abs[0].ElementNum(), 0.0001));
std::vector<mindspore::MSTensor> inputs_other;
mindspore::MSTensor tensor_other("other", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs_other.emplace_back(tensor_other);
tensor_other.SetShape({3, 1, 2, 2});
ASSERT_EQ(kernel_executor_->Execute(inputs_other, &outputs_abs), mindspore::kLiteError);
tensor_other.SetShape({1, 3, 4});
ASSERT_EQ(kernel_executor_->Execute(inputs_other, &outputs_abs), mindspore::kLiteError);
tensor_other.SetFormat(mindspore::NCHW);
ASSERT_EQ(kernel_executor_->Execute(inputs_other, &outputs_abs), mindspore::kLiteError);
tensor_other.SetDataType(mindspore::DataType::kNumberTypeFloat16);
ASSERT_EQ(kernel_executor_->Execute(inputs_other, &outputs_abs), mindspore::kLiteError);
inputs_other.emplace_back(tensor_abs);
ASSERT_EQ(kernel_executor_->Execute(inputs_other, &outputs_abs), mindspore::kLiteError);
}
TEST_F(KernelExecutorTest, TestCustom) {
auto op = std::make_shared<ops::Custom>();
auto kernel_executor = std::make_shared<mindspore::KernelExecutor>();
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor tensor("Custom", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs.emplace_back(tensor);
inputs.emplace_back(tensor);
ASSERT_EQ(kernel_executor->Build(op, inputs, context_, 0), mindspore::kLiteError);
ASSERT_EQ(kernel_executor->Build(op, inputs, context_), mindspore::kLiteError);
ASSERT_EQ(kernel_executor->Build(op, inputs, context_, 1), mindspore::kLiteNotSupport);
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;
op->Init("Custom_Add", custom_attrs);
ASSERT_EQ(kernel_executor->Build(op, inputs, context_, 1), mindspore::kSuccess);
ASSERT_EQ(kernel_executor->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-2, 4, -6, 8, -10, 12, -14, 16, -18, 20, -22, 24};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestRelu) {
auto op = std::make_shared<ops::ReLU>();
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor tensor("Relu", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs.emplace_back(tensor);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestSigmoid) {
auto op = std::make_shared<ops::Sigmoid>();
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
std::vector<float> input_data{1, 2, 3, 4, 5};
mindspore::MSTensor tensor("Sigmoid", mindspore::DataType::kNumberTypeFloat32, {5},
reinterpret_cast<void *>(input_data.data()), 5 * sizeof(float));
inputs.emplace_back(tensor);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {0.731059, 0.88081, 0.952574, 0.982015, 0.993307};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestAdd) {
auto op = std::make_shared<ops::Add>();
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor tensor("Add", mindspore::DataType::kNumberTypeFloat32, {1, 3, 2, 2},
reinterpret_cast<void *>(input_data_.data()), 12 * sizeof(float));
inputs.emplace_back(tensor);
inputs.emplace_back(tensor);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-2, 4, -6, 8, -10, 12, -14, 16, -18, 20, -22, 24};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestArgMax) {
auto op = std::make_shared<ops::Argmax>();
op->Init(-1);
std::vector<float> argmax_data{1, 20, 5, 67, 8, 9, 130, 24, 15};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor tensor("Argmax", mindspore::DataType::kNumberTypeFloat32, {3, 3},
reinterpret_cast<void *>(argmax_data.data()), 9 * sizeof(float));
inputs.emplace_back(tensor);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
int32_t correct[] = {1, 0, 0};
ASSERT_EQ(
0, CompareOutputData(reinterpret_cast<int32_t *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(), 0));
}
TEST_F(KernelExecutorTest, TestArgMin) {
auto op = std::make_shared<ops::ArgMin>();
op->Init();
std::vector<float> input_data{2.0, 3.1, 1.2};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
int32_t correct[] = {2};
ASSERT_EQ(
0, CompareOutputData(reinterpret_cast<int32_t *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(), 0));
}
TEST_F(KernelExecutorTest, TestAvgPool) {
auto op = std::make_shared<ops::AvgPool>();
op->Init({2, 2}, {1, 1});
std::vector<float> input_data{0, 12, 24, 1, 13, 25, 2, 14, 26, 3, 15, 27, 4, 16, 28, 5, 17, 29,
6, 18, 30, 7, 19, 31, 8, 20, 32, 9, 21, 33, 10, 22, 34, 11, 23, 35};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 3, 4, 3},
reinterpret_cast<void *>(input_data.data()), 36 * sizeof(float));
input.SetFormat(mindspore::Format::NHWC);
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {2.5, 14.5, 26.5, 3.5, 15.5, 27.5, 4.5, 16.5, 28.5,
6.5, 18.5, 30.5, 7.5, 19.5, 31.5, 8.5, 20.5, 32.5};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestBatchNorm) {
auto op = std::make_shared<ops::BatchNorm>();
op->Init(true);
std::vector<float> input_data{1, 1, 1, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 1, 2, 2},
reinterpret_cast<void *>(input_data.data()), 4 * sizeof(float));
mindspore::MSTensor scale("input", mindspore::DataType::kNumberTypeFloat32, {2},
reinterpret_cast<void *>(input_data.data()), 2 * sizeof(float));
mindspore::MSTensor bias("input", mindspore::DataType::kNumberTypeFloat32, {2},
reinterpret_cast<void *>(input_data.data()), 2 * sizeof(float));
mindspore::MSTensor mean("input", mindspore::DataType::kNumberTypeFloat32, {2},
reinterpret_cast<void *>(input_data.data()), 2 * sizeof(float));
mindspore::MSTensor variance("input", mindspore::DataType::kNumberTypeFloat32, {2},
reinterpret_cast<void *>(input_data.data()), 2 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(scale);
inputs.emplace_back(bias);
inputs.emplace_back(mean);
inputs.emplace_back(variance);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {1, 1, 1, 1};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestCeil) {
auto op = std::make_shared<ops::Ceil>();
std::vector<float> input_data{1.1, 2.5, -1.5};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {2, 3, -1};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestConcat) {
auto op = std::make_shared<ops::Concat>();
op->Init(1);
std::vector<float> input_data{0, 1, 2, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 2},
reinterpret_cast<void *>(input_data.data()), 4 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {0, 1, 0, 1, 2, 1, 2, 1};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestConv2D) {
auto op = std::make_shared<ops::Conv2D>();
op->Init(32, {3, 3});
std::vector<float> input_data(10 * 32 * 32 * 32, 1);
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {10, 32, 32, 32},
reinterpret_cast<void *>(input_data.data()), 10 * 32 * 32 * 32 * sizeof(float));
mindspore::MSTensor weight("input", mindspore::DataType::kNumberTypeFloat32, {32, 3, 3, 32},
reinterpret_cast<void *>(input_data.data()), 32 * 3 * 3 * 32 * sizeof(float));
input.SetFormat(mindspore::Format::NHWC);
weight.SetFormat(mindspore::Format::NHWC);
inputs.emplace_back(input);
inputs.emplace_back(weight);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
std::vector<int64_t> shape{10, 30, 30, 32};
ASSERT_EQ(outputs[0].Shape(), shape);
}
TEST_F(KernelExecutorTest, TestConv2DTranspose) {
auto op = std::make_shared<ops::Conv2DTranspose>();
op->Init(32, 32, {3, 3});
std::vector<float> input_data(10 * 32 * 32 * 32, 1);
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {10, 30, 30, 32},
reinterpret_cast<void *>(input_data.data()), 10 * 30 * 30 * 32 * sizeof(float));
mindspore::MSTensor weight("input", mindspore::DataType::kNumberTypeFloat32, {32, 3, 3, 32},
reinterpret_cast<void *>(input_data.data()), 32 * 3 * 3 * 32 * sizeof(float));
input.SetFormat(mindspore::Format::NHWC);
weight.SetFormat(mindspore::Format::NHWC);
inputs.emplace_back(input);
inputs.emplace_back(weight);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
std::vector<int64_t> shape{10, 32, 32, 32};
ASSERT_EQ(outputs[0].Shape(), shape);
}
TEST_F(KernelExecutorTest, TestDiv) {
auto op = std::make_shared<ops::Div>();
std::vector<float> input_data{-4, 5, 6};
std::vector<float> input_data2{3, 2, 3};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-1.33333, 2.5, 2};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestEqual) {
auto op = std::make_shared<ops::Equal>();
std::vector<float> input_data{1, 2, 3};
std::vector<float> input_data2{2};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {1},
reinterpret_cast<void *>(input_data2.data()), 1 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
}
TEST_F(KernelExecutorTest, TestFlatten) {
auto op = std::make_shared<ops::Flatten>();
std::vector<float> input_data(24, 1);
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 2, 3, 4},
reinterpret_cast<void *>(input_data.data()), 24 * sizeof(float));
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
std::vector<int64_t> shape{1, 24};
ASSERT_EQ(outputs[0].Shape(), shape);
}
TEST_F(KernelExecutorTest, TestGather) {
auto op = std::make_shared<ops::Gather>();
std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
std::vector<float> input_data2{0, 2, 4, 2, 6};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3, 4},
reinterpret_cast<void *>(input_data.data()), 12 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {2},
reinterpret_cast<void *>(input_data2.data()), 2 * sizeof(float));
mindspore::MSTensor input3("input", mindspore::DataType::kNumberTypeFloat32, {1},
reinterpret_cast<void *>(input_data2.data()), 1 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
inputs.emplace_back(input3);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {1, 2, 3, 4, 9, 10, 11, 12};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestGatherNd) {
auto op = std::make_shared<ops::GatherNd>();
std::vector<float> input_data{-0.1, 0.3, 3.6, 0.4, 0.5, -3.2};
std::vector<int32_t> input_data2{0, 0, 1, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 3},
reinterpret_cast<void *>(input_data.data()), 6 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {2, 2},
reinterpret_cast<void *>(input_data2.data()), 4 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-0.1, 0.5};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestMatMul) {
auto op = std::make_shared<ops::MatMul>();
std::vector<float> input_data(12, 1);
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3, 4},
reinterpret_cast<void *>(input_data.data()), 12 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {3, 3, 3, 3};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestMaximum) {
auto op = std::make_shared<ops::Maximum>();
std::vector<float> input_data{1, 5, 3};
std::vector<float> input_data2{4, 2, 6};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {4, 5, 6};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestMaxPool) {
auto op = std::make_shared<ops::MaxPool>();
op->Init({2, 2}, {1, 1});
std::vector<float> input_data{0, 12, 24, 1, 13, 25, 2, 14, 26, 3, 15, 27, 4, 16, 28, 5, 17, 29,
6, 18, 30, 7, 19, 31, 8, 20, 32, 9, 21, 33, 10, 22, 34, 11, 23, 35};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 3, 4, 3},
reinterpret_cast<void *>(input_data.data()), 36 * sizeof(float));
input.SetFormat(mindspore::Format::NHWC);
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {5, 17, 29, 6, 18, 30, 7, 19, 31, 9, 21, 33, 10, 22, 34, 11, 23, 35};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestMinimum) {
auto op = std::make_shared<ops::Minimum>();
std::vector<float> input_data{1, 5, 3};
std::vector<float> input_data2{4, 2, 6};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {1, 2, 3};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestMul) {
auto op = std::make_shared<ops::Mul>();
std::vector<float> input_data{1, 2, 3};
std::vector<float> input_data2{4, 5, 6};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data.data()), 3 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(float));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {4, 10, 18};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestPad) {
auto op = std::make_shared<ops::Pad>();
std::vector<float> input_data{-0.1, 0.3, 3.6, 0.4, 0.5, -3.2};
std::vector<int32_t> input_data2{1, 2, 2, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 3},
reinterpret_cast<void *>(input_data.data()), 6 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {4},
reinterpret_cast<void *>(input_data2.data()), 4 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {0, 0, 0, 0, 0, 0, 0, 0, -0.1, 0.3, 3.6, 0, 0, 0, 0.4,
0.5, -3.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestPReLU) {
auto op = std::make_shared<ops::PReLU>();
std::vector<float> input_data{-6, -4, -2, -5, -3, -1, 0, 2, 4, 1, 3, 5};
std::vector<float> input_data2{0.1, 0.6, -0.3};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 1, 2, 3},
reinterpret_cast<void *>(input_data.data()), 12 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeFloat32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(float));
input.SetFormat(mindspore::Format::NHWC);
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-0.6, -2.4, 0.6, -0.5, -1.8, 0.3, 0, 2, 4, 1, 3, 5};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestReshape) {
auto op = std::make_shared<ops::Reshape>();
std::vector<float> input_data{-0.1, 0.3, 3.6, 0.4, 0.5, -3.2};
std::vector<int32_t> input_data2{3, 2};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 3},
reinterpret_cast<void *>(input_data.data()), 6 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {2},
reinterpret_cast<void *>(input_data2.data()), 2 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {-0.1, 0.3, 3.6, 0.4, 0.5, -3.2};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
std::vector<int64_t> shape{3, 2};
ASSERT_EQ(outputs[0].Shape(), shape);
}
TEST_F(KernelExecutorTest, TestSoftmax) {
auto op = std::make_shared<ops::Softmax>();
op->Init();
std::vector<float> input_data{1, 2, 3, 4, 5};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {1, 5},
reinterpret_cast<void *>(input_data.data()), 5 * sizeof(float));
inputs.emplace_back(input);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {0.0116558, 0.0316853, 0.0861187, 0.234124, 0.636416};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestStridedSlice) {
auto op = std::make_shared<ops::StridedSlice>();
std::vector<float> input_data{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
std::vector<int32_t> input_data2{1, 0, 0};
std::vector<int32_t> input_data3{2, 1, 3};
std::vector<int32_t> input_data4{1, 1, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {3, 2, 3},
reinterpret_cast<void *>(input_data.data()), 18 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(int32_t));
mindspore::MSTensor input3("input", mindspore::DataType::kNumberTypeInt32, {3},
reinterpret_cast<void *>(input_data3.data()), 3 * sizeof(int32_t));
mindspore::MSTensor input4("input", mindspore::DataType::kNumberTypeInt32, {3},
reinterpret_cast<void *>(input_data4.data()), 3 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
inputs.emplace_back(input3);
inputs.emplace_back(input4);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {3, 3, 3};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestTopK) {
auto op = std::make_shared<ops::TopK>();
op->Init(true);
std::vector<float> input_data{1, 2, 3, 4, 5};
std::vector<int32_t> input_data2{3};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {5},
reinterpret_cast<void *>(input_data.data()), 5 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {1},
reinterpret_cast<void *>(input_data2.data()), 1 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {5, 4, 3};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
TEST_F(KernelExecutorTest, TestTranspose) {
auto op = std::make_shared<ops::Transpose>();
std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
std::vector<int32_t> input_data2{0, 2, 1};
std::vector<mindspore::MSTensor> inputs;
std::vector<mindspore::MSTensor> outputs;
mindspore::MSTensor input("input", mindspore::DataType::kNumberTypeFloat32, {2, 2, 3},
reinterpret_cast<void *>(input_data.data()), 12 * sizeof(float));
mindspore::MSTensor input2("input", mindspore::DataType::kNumberTypeInt32, {3},
reinterpret_cast<void *>(input_data2.data()), 3 * sizeof(int32_t));
inputs.emplace_back(input);
inputs.emplace_back(input2);
ASSERT_EQ(kernel_executor_->Build(op, inputs, context_), mindspore::kSuccess);
ASSERT_EQ(kernel_executor_->Execute(inputs, &outputs), mindspore::kSuccess);
float correct[] = {1, 4, 2, 5, 3, 6, 7, 10, 8, 11, 9, 12};
ASSERT_EQ(0, CompareOutputData(reinterpret_cast<float *>(outputs[0].MutableData()), correct, outputs[0].ElementNum(),
0.0001));
}
} // namespace mindspore