| @@ -19,6 +19,7 @@ | |||
| #include <string> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include <map> | |||
| #include "include/api/types.h" | |||
| #include "include/api/dual_abi_helper.h" | |||
| @@ -68,6 +69,13 @@ struct MS_API ModelContext : public Context { | |||
| static inline void SetInputShape(const std::shared_ptr<Context> &context, const std::string &shape); | |||
| static inline std::string GetInputShape(const std::shared_ptr<Context> &context); | |||
| static void SetInputShapeMap(const std::shared_ptr<Context> &context, const std::map<int, std::vector<int>> &shape); | |||
| static std::map<int, std::vector<int>> GetInputShapeMap(const std::shared_ptr<Context> &context); | |||
| static void SetDynamicBatchSize(const std::shared_ptr<Context> &context, | |||
| const std::vector<size_t> &dynamic_batch_size); | |||
| static inline std::string GetDynamicBatchSize(const std::shared_ptr<Context> &context); | |||
| static void SetOutputType(const std::shared_ptr<Context> &context, enum DataType output_type); | |||
| static enum DataType GetOutputType(const std::shared_ptr<Context> &context); | |||
| @@ -107,6 +115,7 @@ struct MS_API ModelContext : public Context { | |||
| static void SetGpuTrtInferMode(const std::shared_ptr<Context> &context, const std::vector<char> &gpu_trt_infer_mode); | |||
| static std::vector<char> GetGpuTrtInferModeChar(const std::shared_ptr<Context> &context); | |||
| static std::vector<char> GetDynamicBatchSizeChar(const std::shared_ptr<Context> &context); | |||
| }; | |||
| void GlobalContext::SetGlobalDeviceTarget(const std::string &device_target) { | |||
| @@ -162,6 +171,10 @@ std::string ModelContext::GetFusionSwitchConfigPath(const std::shared_ptr<Contex | |||
| return CharToString(GetFusionSwitchConfigPathChar(context)); | |||
| } | |||
| std::string ModelContext::GetDynamicBatchSize(const std::shared_ptr<Context> &context) { | |||
| return CharToString(GetDynamicBatchSizeChar(context)); | |||
| } | |||
| void ModelContext::SetGpuTrtInferMode(const std::shared_ptr<Context> &context, const std::string &gpu_trt_infer_mode) { | |||
| SetGpuTrtInferMode(context, StringToChar(gpu_trt_infer_mode)); | |||
| } | |||
| @@ -24,6 +24,7 @@ constexpr auto kGlobalContextDeviceID = "mindspore.ascend.globalcontext.device_i | |||
| constexpr auto kGlobalContextDumpCfgPath = "mindspore.ascend.globalcontext.dump_config_file_path"; | |||
| constexpr auto kModelOptionInsertOpCfgPath = "mindspore.option.insert_op_config_file_path"; // aipp config file | |||
| constexpr auto kModelOptionInputFormat = "mindspore.option.input_format"; // nchw or nhwc | |||
| constexpr auto kModelOptionInputShapeMap = "mindspore.option.input_shape_map"; | |||
| constexpr auto kModelOptionInputShape = "mindspore.option.input_shape"; | |||
| // Mandatory while dynamic batch: e.g. "input_op_name1: n1,c2,h3,w4;input_op_name2: n4,c3,h2,w1" | |||
| constexpr auto kModelOptionOutputType = "mindspore.option.output_type"; // "FP32", "UINT8" or "FP16", default as "FP32" | |||
| @@ -33,6 +34,8 @@ constexpr auto kModelOptionOpSelectImplMode = "mindspore.option.op_select_impl_m | |||
| constexpr auto KModelOptionFusionSwitchCfgPath = "mindspore.option.fusion_switch_config_file_path"; | |||
| // "False": Inference with native backend, "True": Inference with Tensor-RT engine, default as "False" | |||
| constexpr auto kModelOptionGpuTrtInferMode = "mindspore.option.gpu_trt_infer_mode"; | |||
| constexpr auto kModelOptionDynamicBatchSize = "mindspore.option.dynamic_batch_size"; | |||
| constexpr auto kModelOptionDynamicImageSize = "mindspore.option.dynamic_image_size"; | |||
| namespace mindspore { | |||
| struct Context::Data { | |||
| @@ -159,6 +162,17 @@ std::vector<char> ModelContext::GetInputShapeChar(const std::shared_ptr<Context> | |||
| return StringToChar(ref); | |||
| } | |||
| void ModelContext::SetInputShapeMap(const std::shared_ptr<Context> &context, | |||
| const std::map<int, std::vector<int>> &shape) { | |||
| MS_EXCEPTION_IF_NULL(context); | |||
| context->data->params[kModelOptionInputShapeMap] = shape; | |||
| } | |||
| std::map<int, std::vector<int>> ModelContext::GetInputShapeMap(const std::shared_ptr<Context> &context) { | |||
| MS_EXCEPTION_IF_NULL(context); | |||
| return GetValue<std::map<int, std::vector<int>>>(context, kModelOptionInputShapeMap); | |||
| } | |||
| void ModelContext::SetOutputType(const std::shared_ptr<Context> &context, enum DataType output_type) { | |||
| MS_EXCEPTION_IF_NULL(context); | |||
| if (context->data == nullptr) { | |||
| @@ -235,4 +249,23 @@ std::vector<char> ModelContext::GetGpuTrtInferModeChar(const std::shared_ptr<Con | |||
| const std::string &ref = GetValue<std::string>(context, kModelOptionGpuTrtInferMode); | |||
| return StringToChar(ref); | |||
| } | |||
| void ModelContext::SetDynamicBatchSize(const std::shared_ptr<Context> &context, const std::vector<size_t> &batch_size) { | |||
| MS_EXCEPTION_IF_NULL(context); | |||
| if (context->data == nullptr) { | |||
| context->data = std::make_shared<Data>(); | |||
| MS_EXCEPTION_IF_NULL(context->data); | |||
| } | |||
| std::string batchs = ""; | |||
| for (auto bs : batch_size) { | |||
| batchs += std::to_string(bs) + ","; | |||
| } | |||
| context->data->params[kModelOptionDynamicBatchSize] = batchs; | |||
| } | |||
| std::vector<char> ModelContext::GetDynamicBatchSizeChar(const std::shared_ptr<Context> &context) { | |||
| MS_EXCEPTION_IF_NULL(context); | |||
| const std::string &ref = GetValue<std::string>(context, kModelOptionDynamicBatchSize); | |||
| return StringToChar(ref); | |||
| } | |||
| } // namespace mindspore | |||
| @@ -53,18 +53,15 @@ inline static void PushbackIfNotNull(U *vec, T &&item) { | |||
| } | |||
| static void ConstructTensorDesc(const std::vector<AclTensorInfo> &acl_tensor_list, std::vector<std::string> *names, | |||
| std::vector<std::vector<int64_t>> *shapes, std::vector<enum DataType> *data_types, | |||
| std::vector<size_t> *mem_sizes) { | |||
| std::vector<std::vector<int64_t>> *shapes, std::vector<enum DataType> *data_types) { | |||
| ClearIfNotNull(names); | |||
| ClearIfNotNull(shapes); | |||
| ClearIfNotNull(data_types); | |||
| ClearIfNotNull(mem_sizes); | |||
| for (size_t i = 0; i < acl_tensor_list.size(); ++i) { | |||
| const auto &info = acl_tensor_list[i]; | |||
| PushbackIfNotNull(names, info.name); | |||
| PushbackIfNotNull(shapes, info.dims); | |||
| PushbackIfNotNull(data_types, TransToApiType(info.data_type)); | |||
| PushbackIfNotNull(mem_sizes, info.buffer_size); | |||
| } | |||
| } | |||
| @@ -81,20 +78,17 @@ static std::string ShapeToString(const std::vector<int64_t> &shape) { | |||
| } | |||
| Status ModelProcess::ConstructTensors(const std::vector<AclTensorInfo> &acl_tensor_list, | |||
| std::vector<MSTensor> *tensor_list) { | |||
| std::vector<MSTensor> *tensor_list, const std::vector<size_t> &mem_sizes) { | |||
| MS_EXCEPTION_IF_NULL(tensor_list); | |||
| std::vector<std::string> names; | |||
| std::vector<std::vector<int64_t>> shapes; | |||
| std::vector<enum DataType> data_types; | |||
| std::vector<size_t> mem_sizes; | |||
| ConstructTensorDesc(acl_tensor_list, &names, &shapes, &data_types, &mem_sizes); | |||
| ConstructTensorDesc(acl_tensor_list, &names, &shapes, &data_types); | |||
| tensor_list->clear(); | |||
| if (names.size() != acl_tensor_list.size() || shapes.size() != acl_tensor_list.size() || | |||
| data_types.size() != acl_tensor_list.size() || mem_sizes.size() != acl_tensor_list.size()) { | |||
| data_types.size() != acl_tensor_list.size()) { | |||
| MS_LOG(ERROR) << "Inner error, size do not match: names size " << names.size() << " shapes size " << shapes.size() | |||
| << " data types size " << data_types.size() << " mem sizes size " << mem_sizes.size() | |||
| << " acl_tensor_list size " << acl_tensor_list.size(); | |||
| << " data types size " << data_types.size() << " acl_tensor_list size " << acl_tensor_list.size(); | |||
| return kMCFailed; | |||
| } | |||
| @@ -102,7 +96,7 @@ Status ModelProcess::ConstructTensors(const std::vector<AclTensorInfo> &acl_tens | |||
| for (size_t i = 0; i < acl_tensor_list.size(); ++i) { | |||
| tensor_list->emplace_back(names[i], data_types[i], shapes[i], nullptr, mem_sizes[i]); | |||
| auto ret = aclrtMemcpy((*tensor_list)[i].MutableData(), (*tensor_list)[i].DataSize(), | |||
| acl_tensor_list[i].device_data, acl_tensor_list[i].buffer_size, kind); | |||
| acl_tensor_list[i].device_data, mem_sizes[i], kind); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MS_LOG(ERROR) << "Memcpy input " << i << " from " << (is_run_on_device_ ? "host" : "device") | |||
| << " to host failed, memory size " << acl_tensor_list[i].buffer_size; | |||
| @@ -165,6 +159,7 @@ Status ModelProcess::InitInputsBuffer() { | |||
| } | |||
| MS_LOG(INFO) << "Name of input " << i << " is " << input_name; | |||
| input_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, data_type, shape, input_name}); | |||
| input_size_.push_back(buffer_size); | |||
| } | |||
| MS_LOG(INFO) << "Create model inputs success"; | |||
| return kSuccess; | |||
| @@ -319,38 +314,72 @@ Status ModelProcess::UnLoad() { | |||
| return kSuccess; | |||
| } | |||
| size_t ModelProcess::GetDynamicDims(const std::vector<AclTensorInfo> &inputs) { | |||
| size_t max_num = 0; | |||
| for (auto input : inputs) { | |||
| size_t cur_num = std::count(input.dims.begin(), input.dims.end(), -1); | |||
| if (cur_num > max_num) { | |||
| max_num = cur_num; | |||
| } | |||
| } | |||
| return max_num; | |||
| } | |||
| Status ModelProcess::SetBatchSize(const std::vector<MSTensor> &inputs) { | |||
| size_t index; | |||
| aclError ret; | |||
| input_size_.clear(); | |||
| for (auto input : inputs) { | |||
| input_size_.push_back(input.DataSize()); | |||
| } | |||
| auto *p = reinterpret_cast<const float *>(inputs[inputs.size() - 1].Data().get()); | |||
| MS_EXCEPTION_IF_NULL(p); | |||
| auto dynamicBatchSize = p[0]; | |||
| ret = aclmdlGetInputIndexByName(model_desc_, ACL_DYNAMIC_TENSOR_NAME, &index); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MS_LOG(ERROR) << "get index failed"; | |||
| return kMCDeviceError; | |||
| } | |||
| ret = aclmdlSetDynamicBatchSize(model_id_, inputs_, index, dynamicBatchSize); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MS_LOG(ERROR) << "dynamic batch set failed, modelId is " << model_id_; | |||
| return kMCDeviceError; | |||
| } | |||
| return kSuccess; | |||
| } | |||
| Status ModelProcess::CheckAndInitInput(const std::vector<MSTensor> &inputs) { | |||
| aclError ret; | |||
| inputs_ = aclmdlCreateDataset(); | |||
| size_t dynamic_nums = GetDynamicDims(input_infos_); | |||
| // check inputs | |||
| if (inputs.size() != input_infos_.size()) { | |||
| MS_LOG(ERROR) << "Inputs count not match, required count " << input_infos_.size() << ", given count " | |||
| << inputs.size(); | |||
| return kMCInvalidInput; | |||
| } | |||
| for (size_t i = 0; i < input_infos_.size(); ++i) { | |||
| if (inputs[i].Shape() != input_infos_[i].dims) { | |||
| MS_LOG(INFO) << "Note: input " << i << " shape not match, required " << ShapeToString(input_infos_[i].dims) | |||
| << ", given " << ShapeToString(inputs[i].Shape()); | |||
| } | |||
| if (inputs[i].DataType() != TransToApiType(input_infos_[i].data_type)) { | |||
| MS_LOG(INFO) << "Note: input " << i << " data type not match, required " | |||
| << TransToApiType(input_infos_[i].data_type) << ", given " << inputs[i].DataType(); | |||
| } | |||
| if (inputs[i].DataSize() != input_infos_[i].buffer_size) { | |||
| MS_LOG(ERROR) << "Input " << i << " data size not match, required size " << input_infos_[i].buffer_size | |||
| << ", given count " << inputs[i].DataSize(); | |||
| if (dynamic_nums == 0) { | |||
| if (inputs.size() != input_infos_.size()) { | |||
| MS_LOG(ERROR) << "Inputs count not match, required count " << input_infos_.size() << ", given count " | |||
| << inputs.size(); | |||
| return kMCInvalidInput; | |||
| } | |||
| for (size_t i = 0; i < input_infos_.size(); ++i) { | |||
| if (inputs[i].Shape() != input_infos_[i].dims) { | |||
| MS_LOG(INFO) << "Note: input " << i << " shape not match, required " << ShapeToString(input_infos_[i].dims) | |||
| << ", given " << ShapeToString(inputs[i].Shape()); | |||
| } | |||
| if (inputs[i].DataType() != TransToApiType(input_infos_[i].data_type)) { | |||
| MS_LOG(INFO) << "Note: input " << i << " data type not match, required " | |||
| << TransToApiType(input_infos_[i].data_type) << ", given " << inputs[i].DataType(); | |||
| } | |||
| if (inputs[i].DataSize() != input_infos_[i].buffer_size) { | |||
| MS_LOG(ERROR) << "Input " << i << " data size not match, required size " << input_infos_[i].buffer_size | |||
| << ", given count " << inputs[i].DataSize(); | |||
| return kMCInvalidInput; | |||
| } | |||
| } | |||
| } | |||
| // copy inputs | |||
| for (size_t i = 0; i < input_infos_.size(); ++i) { | |||
| const auto &info = input_infos_[i]; | |||
| auto input = inputs[i]; | |||
| const void *data = input.MutableData(); | |||
| void *input_buffer = nullptr; | |||
| if (!is_run_on_device_) { | |||
| ret = aclrtMemcpy(info.device_data, info.buffer_size, data, input.DataSize(), ACL_MEMCPY_HOST_TO_DEVICE); | |||
| @@ -374,6 +403,40 @@ Status ModelProcess::CheckAndInitInput(const std::vector<MSTensor> &inputs) { | |||
| return kMCDeviceError; | |||
| } | |||
| } | |||
| if (dynamic_nums == 1) { | |||
| if (SetBatchSize(inputs) == kMCDeviceError) { | |||
| MS_LOG(ERROR) << "failed to convert dynamic batch size"; | |||
| return kMCDeviceError; | |||
| } | |||
| } else if (dynamic_nums == 2) { | |||
| MS_LOG(ERROR) << "only dynamic batch size is supported"; | |||
| return kMCInvalidInput; | |||
| } | |||
| if (ResetOutputSize() == kMCDeviceError) { | |||
| MS_LOG(ERROR) << "reset output size failed"; | |||
| return kMCDeviceError; | |||
| } | |||
| return kSuccess; | |||
| } | |||
| Status ModelProcess::ResetOutputSize() { | |||
| aclDataType output_type; | |||
| aclError ret; | |||
| size_t output_size = aclmdlGetNumOutputs(model_desc_); | |||
| for (size_t index = 0; index < output_size; index++) { | |||
| size_t dims = 1; | |||
| struct aclmdlIODims output_dims; | |||
| ret = aclmdlGetCurOutputDims(model_desc_, index, &output_dims); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MS_LOG(ERROR) << "get output dim error."; | |||
| return kMCDeviceError; | |||
| } | |||
| for (size_t i = 0; i < output_dims.dimCount; i++) { | |||
| dims *= output_dims.dims[i]; | |||
| } | |||
| output_type = aclmdlGetOutputDataType(model_desc_, index); | |||
| output_size_.push_back(dims * aclDataTypeSize(output_type)); | |||
| } | |||
| return kSuccess; | |||
| } | |||
| @@ -427,7 +490,7 @@ Status ModelProcess::BuildOutputs(std::vector<MSTensor> *outputs) { | |||
| } | |||
| std::vector<MSTensor> ModelProcess::GetInputs() { | |||
| Status ret = ConstructTensors(input_infos_, &input_tensors_); | |||
| Status ret = ConstructTensors(input_infos_, &input_tensors_, input_size_); | |||
| if (ret != kSuccess) { | |||
| MS_LOG(ERROR) << "ConstructTensors failed."; | |||
| input_tensors_.clear(); | |||
| @@ -437,7 +500,7 @@ std::vector<MSTensor> ModelProcess::GetInputs() { | |||
| } | |||
| std::vector<MSTensor> ModelProcess::GetOutputs() { | |||
| Status ret = ConstructTensors(output_infos_, &output_tensors_); | |||
| Status ret = ConstructTensors(output_infos_, &output_tensors_, output_size_); | |||
| if (ret != kSuccess) { | |||
| MS_LOG(ERROR) << "ConstructTensors failed."; | |||
| output_tensors_.clear(); | |||
| @@ -61,10 +61,13 @@ class ModelProcess { | |||
| private: | |||
| Status CreateDataBuffer(void **data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset); | |||
| Status CheckAndInitInput(const std::vector<MSTensor> &inputs); | |||
| Status ConstructTensors(const std::vector<AclTensorInfo> &acl_tensor_list, std::vector<MSTensor> *tensor_list); | |||
| Status ConstructTensors(const std::vector<AclTensorInfo> &acl_tensor_list, std::vector<MSTensor> *tensor_list, | |||
| const std::vector<size_t> &mem_sizes); | |||
| Status BuildOutputs(std::vector<MSTensor> *outputs); | |||
| Status SetBatchSize(const std::vector<MSTensor> &inputs); | |||
| Status InitInputsBuffer(); | |||
| Status InitOutputsBuffer(); | |||
| Status ResetOutputSize(); | |||
| void DestroyInputsDataset(); | |||
| void DestroyInputsDataMem(); | |||
| @@ -81,6 +84,9 @@ class ModelProcess { | |||
| std::vector<AclTensorInfo> output_infos_; | |||
| std::vector<MSTensor> input_tensors_; | |||
| std::vector<MSTensor> output_tensors_; | |||
| std::vector<size_t> output_size_; | |||
| std::vector<size_t> input_size_; | |||
| size_t GetDynamicDims(const std::vector<AclTensorInfo> &); | |||
| }; | |||
| } // namespace mindspore | |||
| @@ -47,6 +47,20 @@ Status AclModel::Build() { | |||
| graph = iter->second; | |||
| } else { | |||
| auto func_graph = ModelImpl::GetFuncGraph(); | |||
| auto inputs = func_graph->parameters(); | |||
| std::vector<std::string> input_names; | |||
| for (auto node : inputs) { | |||
| auto para = node->cast<ParameterPtr>(); | |||
| MS_EXCEPTION_IF_NULL(para); | |||
| std::string name = para->name(); | |||
| for (auto pos = name.find(':'); pos != std::string::npos; pos = name.find(':')) { | |||
| name = name.substr(0, pos) + "_" + name.substr(pos + 1); | |||
| MS_LOG(INFO) << name; | |||
| } | |||
| para->set_name(name); | |||
| input_names.push_back(name); | |||
| } | |||
| options->RenameInput(input_names); | |||
| MS_EXCEPTION_IF_NULL(func_graph); | |||
| model_converter_.set_options(options.get()); | |||
| auto om_data = model_converter_.LoadMindIR(func_graph); | |||
| @@ -27,10 +27,9 @@ AclModelOptions::AclModelOptions(const std::shared_ptr<Context> &context) { | |||
| if (context == nullptr) { | |||
| return; | |||
| } | |||
| insert_op_cfg_path = ModelContext::GetInsertOpConfigPath(context); | |||
| input_format = ModelContext::GetInputFormat(context); | |||
| input_shape = ModelContext::GetInputShape(context); | |||
| insert_op_cfg_path_ = ModelContext::GetInsertOpConfigPath(context); | |||
| input_format_ = ModelContext::GetInputFormat(context); | |||
| input_shape_map_ = ModelContext::GetInputShapeMap(context); | |||
| auto out_type = ModelContext::GetOutputType(context); | |||
| auto iter = kSupportedDtypeOptionMap.find(out_type); | |||
| if (out_type == DataType::kTypeUnknown) { | |||
| @@ -38,26 +37,46 @@ AclModelOptions::AclModelOptions(const std::shared_ptr<Context> &context) { | |||
| } else if (iter == kSupportedDtypeOptionMap.end()) { | |||
| MS_LOG(WARNING) << "Unsupported output type " << out_type << ", use FP32 as default."; | |||
| } else { | |||
| output_type = iter->second; | |||
| output_type_ = iter->second; | |||
| } | |||
| dynamic_batch_size_ = ModelContext::GetDynamicBatchSize(context); | |||
| precision_mode_ = ModelContext::GetPrecisionMode(context); | |||
| op_select_impl_mode_ = ModelContext::GetOpSelectImplMode(context); | |||
| fusion_switch_cfg_path_ = ModelContext::GetFusionSwitchConfigPath(context); | |||
| } | |||
| precision_mode = ModelContext::GetPrecisionMode(context); | |||
| op_select_impl_mode = ModelContext::GetOpSelectImplMode(context); | |||
| fusion_switch_cfg_path = ModelContext::GetFusionSwitchConfigPath(context); | |||
| void AclModelOptions::RenameInput(const std::vector<std::string> &input_names) { | |||
| if (input_names.size() != input_shape_map_.size()) { | |||
| MS_LOG(INFO) << "Inputs count not match"; | |||
| return; | |||
| } | |||
| input_shape_ = ""; | |||
| for (size_t i = 0; i < input_shape_map_.size(); i++) { | |||
| std::string s; | |||
| for (size_t j = 0; j < input_shape_map_[i].size(); j++) { | |||
| s += std::to_string(input_shape_map_[i][j]) + ","; | |||
| } | |||
| input_shape_ += input_names[i] + ":" + s.substr(0, s.size() - 1) + ";"; | |||
| } | |||
| input_shape_ = input_shape_.substr(0, input_shape_.size() - 1); | |||
| MS_LOG(INFO) << "input name is " << input_shape_; | |||
| } | |||
| std::tuple<std::map<std::string, std::string>, std::map<std::string, std::string>> AclModelOptions::GenAclOptions() | |||
| const { | |||
| const std::map<std::string const *, std::string> init_options_map = { | |||
| {&op_select_impl_mode, ge::ir_option::OP_SELECT_IMPL_MODE}, | |||
| {&soc_version, ge::ir_option::SOC_VERSION}, | |||
| {&fusion_switch_cfg_path, ge::ir_option::FUSION_SWITCH_FILE}}; | |||
| {&op_select_impl_mode_, ge::ir_option::OP_SELECT_IMPL_MODE}, | |||
| {&soc_version_, ge::ir_option::SOC_VERSION}, | |||
| {&fusion_switch_cfg_path_, ge::ir_option::FUSION_SWITCH_FILE}}; | |||
| const std::map<std::string const *, std::string> build_options_map = { | |||
| {&insert_op_cfg_path, ge::ir_option::INSERT_OP_FILE}, {&input_format, ge::ir_option::INPUT_FORMAT}, | |||
| {&input_shape, ge::ir_option::INPUT_SHAPE}, {&output_type, ge::ir_option::OUTPUT_TYPE}, | |||
| {&precision_mode, ge::ir_option::PRECISION_MODE}, | |||
| }; | |||
| {&insert_op_cfg_path_, ge::ir_option::INSERT_OP_FILE}, | |||
| {&input_format_, ge::ir_option::INPUT_FORMAT}, | |||
| {&input_shape_, ge::ir_option::INPUT_SHAPE}, | |||
| {&output_type_, ge::ir_option::OUTPUT_TYPE}, | |||
| {&precision_mode_, ge::ir_option::PRECISION_MODE}, | |||
| {&dynamic_batch_size_, ge::ir_option::DYNAMIC_BATCH_SIZE}, | |||
| {&dynamic_image_size_, ge::ir_option::DYNAMIC_IMAGE_SIZE}}; | |||
| std::map<std::string, std::string> init_options; | |||
| std::map<std::string, std::string> build_options; | |||
| @@ -26,23 +26,31 @@ | |||
| #include "include/api/context.h" | |||
| namespace mindspore { | |||
| struct AclModelOptions { | |||
| // build options | |||
| std::string insert_op_cfg_path; | |||
| std::string input_format; | |||
| std::string input_shape; | |||
| std::string output_type; | |||
| std::string precision_mode; | |||
| std::string op_select_impl_mode; | |||
| std::string fusion_switch_cfg_path; | |||
| std::string soc_version = "Ascend310"; | |||
| class AclModelOptions { | |||
| public: | |||
| explicit AclModelOptions(const std::shared_ptr<Context> &context); | |||
| ~AclModelOptions() = default; | |||
| std::string GenAclOptionsKey() const; | |||
| void RenameInput(const std::vector<std::string> &); | |||
| // return tuple<init_options, build_options> | |||
| std::tuple<std::map<std::string, std::string>, std::map<std::string, std::string>> GenAclOptions() const; | |||
| std::string GenAclOptionsKey() const; | |||
| private: | |||
| std::string output_node_; // todo: at convert.cc::BuildGraph(), no atc options | |||
| // build options | |||
| std::string insert_op_cfg_path_; | |||
| std::string input_format_; | |||
| std::string input_shape_; | |||
| std::string output_type_; | |||
| std::string precision_mode_; | |||
| std::string op_select_impl_mode_; | |||
| std::string fusion_switch_cfg_path_; | |||
| std::string soc_version_ = "Ascend310"; | |||
| std::string dynamic_batch_size_; | |||
| std::string dynamic_image_size_; | |||
| std::map<int, std::vector<int>> input_shape_map_; | |||
| std::vector<std::string> dynamic_image_size_nums_; | |||
| }; | |||
| } // namespace mindspore | |||
| @@ -72,19 +72,6 @@ bool CreateSessionAndGraphRunner() { | |||
| } // namespace | |||
| transform::DfGraphPtr ModelConverter::ConvertFuncGraphToAIR(const FuncGraphPtr &anf_graph) { | |||
| for (auto &anf_node : anf_graph->parameters()) { | |||
| MS_EXCEPTION_IF_NULL(anf_node); | |||
| auto para = anf_node->cast<ParameterPtr>(); | |||
| MS_EXCEPTION_IF_NULL(para); | |||
| // normalize name | |||
| std::string name = para->name(); | |||
| for (auto pos = name.find(':'); pos != std::string::npos; pos = name.find(':')) { | |||
| name = name.substr(0, pos) + "_" + name.substr(pos + 1); | |||
| MS_LOG(INFO) << name; | |||
| } | |||
| para->set_name(name); | |||
| } | |||
| transform::DfGraphConvertor converter(anf_graph); | |||
| std::string net_id = "0"; | |||
| std::string init_graph = "init_subgraph." + net_id; | |||
| @@ -0,0 +1,99 @@ | |||
| /** | |||
| * 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 <string> | |||
| #include <vector> | |||
| #include <map> | |||
| #include "common/common_test.h" | |||
| #include "include/api/model.h" | |||
| #include "include/api/serialization.h" | |||
| #include "include/api/context.h" | |||
| using namespace mindspore; | |||
| static const char tensor_add_file[] = "/home/workspace/mindspore_dataset/mindir/add/add.mindir"; | |||
| static const float input_data_1[2][2] = {{1,2},{3,4}}; | |||
| static const float input_data_2[2][2] = {{2,3},{4,5}}; | |||
| static const float input_data_3[1] ={2}; | |||
| class TestDynamicBatchSize : public ST::Common { | |||
| public: | |||
| TestDynamicBatchSize() {} | |||
| }; | |||
| TEST_F(TestDynamicBatchSize, InferMindIR) { | |||
| mindspore::GlobalContext::SetGlobalDeviceTarget(mindspore::kDeviceTypeAscend310); | |||
| mindspore::GlobalContext::SetGlobalDeviceID(2); | |||
| std::map<int,std::vector<int>> input_shape; | |||
| input_shape.insert(std::make_pair(0,std::vector<int>{-1,2})); | |||
| input_shape.insert(std::make_pair(1,std::vector<int>{-1,2})); | |||
| auto model_context = std::make_shared<ModelContext>(); | |||
| std::vector<size_t> dynamic_batch_size ={1,2,4,8}; | |||
| ModelContext::SetDynamicBatchSize(model_context,dynamic_batch_size); | |||
| ModelContext::SetInputShapeMap(model_context,input_shape); | |||
| auto graph = Serialization::LoadModel(tensor_add_file, ModelType::kMindIR); | |||
| Model tensor_add(GraphCell(graph),model_context); | |||
| ASSERT_TRUE(tensor_add.Build() == kSuccess); | |||
| // get model inputs | |||
| std::vector<MSTensor> origin_inputs = tensor_add.GetInputs(); | |||
| ASSERT_EQ(origin_inputs.size()-1, 2); | |||
| // prepare input | |||
| std::vector<MSTensor> outputs; | |||
| std::vector<MSTensor> inputs; | |||
| size_t row = sizeof(input_data_1)/sizeof(input_data_1[0]); | |||
| size_t col = sizeof(input_data_1[0])/sizeof(input_data_1[0][0]);; | |||
| inputs.emplace_back(origin_inputs[0].Name(), origin_inputs[0].DataType(), origin_inputs[0].Shape(), | |||
| input_data_1, sizeof(float) * row*col); | |||
| inputs.emplace_back(origin_inputs[1].Name(), origin_inputs[1].DataType(), origin_inputs[1].Shape(), | |||
| input_data_2, sizeof(float) * row*col); | |||
| inputs.emplace_back(origin_inputs[2].Name(), origin_inputs[2].DataType(), origin_inputs[2].Shape(), | |||
| input_data_3, sizeof(float) * 1); | |||
| // infer | |||
| ASSERT_TRUE(tensor_add.Predict(inputs, &outputs) == kSuccess); | |||
| // assert input | |||
| inputs = tensor_add.GetInputs(); | |||
| ASSERT_EQ(inputs.size()-1, 2); | |||
| auto after_input_data_1 = inputs[0].Data(); | |||
| auto after_input_data_2 = inputs[1].Data(); | |||
| const float *p = reinterpret_cast<const float *>(after_input_data_1.get()); | |||
| float input_data1[inputs[0].DataSize() / sizeof(float)] ={0}; | |||
| float input_data2[inputs[1].DataSize() / sizeof(float)] ={0}; | |||
| size_t k=0,t=0; | |||
| for(size_t i=0;i<row;i++) | |||
| for(size_t j=0;j<col;j++){ | |||
| input_data1[k++]=input_data_1[i][j]; | |||
| input_data2[t++]=input_data_2[i][j]; | |||
| } | |||
| for (size_t i = 0; i < inputs[0].DataSize() / sizeof(float); ++i) { | |||
| ASSERT_LE(std::abs(p[i] - input_data1[i]), 1e-4); | |||
| } | |||
| p = reinterpret_cast<const float *>(after_input_data_2.get()); | |||
| for (size_t i = 0; i < inputs[1].DataSize() / sizeof(float); ++i) { | |||
| ASSERT_LE(std::abs(p[i] - input_data2[i]), 1e-4); | |||
| } | |||
| // assert output | |||
| for (auto &buffer : outputs) { | |||
| auto buffer_data = buffer.Data(); | |||
| p = reinterpret_cast<const float *>(buffer_data.get()); | |||
| for (size_t i = 0; i < buffer.DataSize() / sizeof(float); ++i) { | |||
| ASSERT_LE(std::abs(p[i] - (input_data1[i] + input_data2[i])), 1e-4); | |||
| } | |||
| } | |||
| } | |||