forked from mindspore-Ecosystem/mindspore
dynamic_batch
Signed-off-by: zhupuxu <zhupuxu@huawei.com>
This commit is contained in:
parent
68eb5125c6
commit
5ca25451ee
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue