Merge pull request !3807 from 徐永飞/mastertags/v0.7.0-beta
| @@ -15,7 +15,7 @@ include(${CMAKE_SOURCE_DIR}/cmake/external_libs/json.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/dependency_securec.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/protobuf.cmake) | |||
| if (ENABLE_DEBUGGER OR ENABLE_SERVING) | |||
| if (ENABLE_DEBUGGER OR ENABLE_SERVING OR ENABLE_TESTCASES) | |||
| # build dependencies of gRPC | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/absl.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/c-ares.cmake) | |||
| @@ -69,7 +69,6 @@ endif() | |||
| if (ENABLE_MINDDATA) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/icu4c.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/jpeg_turbo.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/libtiff.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/opencv.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/sqlite.cmake) | |||
| @@ -78,6 +77,10 @@ if (ENABLE_MINDDATA) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/sentencepiece.cmake) | |||
| endif() | |||
| if (ENABLE_MINDDATA OR ENABLE_SERVING) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/jpeg_turbo.cmake) | |||
| endif() | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/gtest.cmake) | |||
| include(${CMAKE_SOURCE_DIR}/cmake/external_libs/onnx.cmake) | |||
| set(CMAKE_CXX_FLAGS ${_ms_tmp_CMAKE_CXX_FLAGS_F}) | |||
| @@ -26,19 +26,10 @@ | |||
| #ifndef ENABLE_ACL | |||
| #include "mindspore/core/utils/log_adapter.h" | |||
| namespace mindspore::inference { | |||
| #define MSI_LOG(level) MS_LOG(level) | |||
| #define MSI_LOG_DEBUG MSI_LOG(DEBUG) | |||
| #define MSI_LOG_INFO MSI_LOG(INFO) | |||
| #define MSI_LOG_WARNING MSI_LOG(WARNING) | |||
| #define MSI_LOG_ERROR MSI_LOG(ERROR) | |||
| #define MSI_ASSERT(item) MS_ASSERT(item) | |||
| } // namespace mindspore::inference | |||
| #else // ENABLE_ACL | |||
| #include "acl/acl.h" | |||
| #endif | |||
| namespace mindspore::inference { | |||
| class LogStream { | |||
| @@ -58,15 +49,23 @@ class LogStream { | |||
| } | |||
| friend class LogWriter; | |||
| friend class Status; | |||
| private: | |||
| std::shared_ptr<std::stringstream> sstream_; | |||
| }; | |||
| template <class T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0> | |||
| constexpr std::ostream &operator<<(std::ostream &stream, const T &value) { | |||
| return stream << static_cast<typename std::underlying_type<T>::type>(value); | |||
| } | |||
| #ifndef ENABLE_ACL | |||
| #define MSI_LOG(level) MS_LOG(level) | |||
| #define MSI_LOG_DEBUG MSI_LOG(DEBUG) | |||
| #define MSI_LOG_INFO MSI_LOG(INFO) | |||
| #define MSI_LOG_WARNING MSI_LOG(WARNING) | |||
| #define MSI_LOG_ERROR MSI_LOG(ERROR) | |||
| #define MSI_ASSERT(item) MS_ASSERT(item) | |||
| #else // ENABLE_ACL | |||
| class LogWriter { | |||
| public: | |||
| @@ -100,8 +99,10 @@ class LogWriter { | |||
| #define MSI_ASSERT(item) | |||
| } // namespace mindspore::inference | |||
| #endif // ENABLE_ACL | |||
| #define INFER_STATUS(code) inference::Status(code) < inference::LogStream() | |||
| } // namespace mindspore::inference | |||
| #endif // MINDSPORE_INFERENCE_LOG_H_ | |||
| @@ -129,12 +129,25 @@ class InferTensor : public InferTensorBase { | |||
| void *mutable_data() override { return data_.data(); } | |||
| }; | |||
| class InferImagesBase { | |||
| public: | |||
| virtual size_t batch_size() const = 0; | |||
| virtual bool get(size_t index, const void *&pic_buffer, uint32_t &pic_size) const = 0; | |||
| virtual size_t input_index() const = 0; // the index of images as input in model | |||
| }; | |||
| class RequestBase { | |||
| public: | |||
| virtual size_t size() const = 0; | |||
| virtual const InferTensorBase *operator[](size_t index) const = 0; | |||
| }; | |||
| class ImagesRequestBase { | |||
| public: | |||
| virtual size_t size() const = 0; | |||
| virtual const InferImagesBase *operator[](size_t index) const = 0; | |||
| }; | |||
| class ReplyBase { | |||
| public: | |||
| virtual size_t size() const = 0; | |||
| @@ -21,10 +21,36 @@ | |||
| #include <vector> | |||
| #include <string> | |||
| #include "include/infer_tensor.h" | |||
| #include "include/infer_log.h" | |||
| namespace mindspore { | |||
| namespace inference { | |||
| enum Status { SUCCESS = 0, FAILED, INVALID_INPUTS }; | |||
| enum StatusCode { SUCCESS = 0, FAILED, INVALID_INPUTS }; | |||
| class Status { | |||
| public: | |||
| Status() : status_code_(FAILED) {} | |||
| Status(enum StatusCode status_code, const std::string &status_msg = "") | |||
| : status_code_(status_code), status_msg_(status_msg) {} | |||
| bool IsSuccess() const { return status_code_ == SUCCESS; } | |||
| enum StatusCode StatusCode() const { return status_code_; } | |||
| std::string StatusMessage() const { return status_msg_; } | |||
| bool operator==(const Status &other) const { return status_code_ == other.status_code_; } | |||
| bool operator==(enum StatusCode other_code) const { return status_code_ == other_code; } | |||
| bool operator!=(const Status &other) const { return status_code_ != other.status_code_; } | |||
| bool operator!=(enum StatusCode other_code) const { return status_code_ != other_code; } | |||
| operator bool() const = delete; | |||
| Status &operator<(const LogStream &stream) noexcept __attribute__((visibility("default"))) { | |||
| status_msg_ = stream.sstream_->str(); | |||
| return *this; | |||
| } | |||
| private: | |||
| enum StatusCode status_code_; | |||
| std::string status_msg_; | |||
| }; | |||
| class MS_API InferSession { | |||
| public: | |||
| InferSession() = default; | |||
| @@ -42,7 +68,12 @@ class MS_API InferSession { | |||
| VectorInferTensorWrapReply reply(outputs); | |||
| return ExecuteModel(model_id, request, reply); | |||
| } | |||
| // default not support input data preprocess(decode, resize, crop, crop&paste, etc.) | |||
| virtual Status ExecuteModel(uint32_t /*model_id*/, | |||
| const ImagesRequestBase & /*images_inputs*/, // images for preprocess | |||
| const RequestBase & /*request*/, ReplyBase & /*reply*/) { | |||
| return FAILED; | |||
| } | |||
| static std::shared_ptr<InferSession> CreateSession(const std::string &device, uint32_t device_id); | |||
| }; | |||
| @@ -87,7 +87,8 @@ GraphId AscendInferenceSession::CompileGraph(NotNull<FuncGraphPtr> func_graph) { | |||
| return graph_id; | |||
| } | |||
| bool AscendInferenceSession::CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const { | |||
| bool AscendInferenceSession::CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs, | |||
| std::string *error_msg) const { | |||
| MS_LOG(INFO) << "Start check client inputs, graph id : " << graph_id; | |||
| auto kernel_graph = GetGraph(graph_id); | |||
| MS_EXCEPTION_IF_NULL(kernel_graph); | |||
| @@ -113,12 +114,25 @@ bool AscendInferenceSession::CheckModelInputs(uint32_t graph_id, const std::vect | |||
| MS_LOG(ERROR) << "Input number is inconsistent. The actual input number [" << inputs.size() | |||
| << "] but the graph input number is [" << paras.size() << "]"; | |||
| MS_LOG(ERROR) << "InputsInfo --" << InputsInfo(paras, inputs); | |||
| if (error_msg != nullptr) { | |||
| std::stringstream str_stream; | |||
| str_stream << "Input number is inconsistent. The given input number [" << inputs.size() | |||
| << "] but the graph input number is [" << paras.size() << "]\n"; | |||
| str_stream << "InputsInfo --" << InputsInfo(paras, inputs); | |||
| *error_msg = str_stream.str(); | |||
| } | |||
| return false; | |||
| } | |||
| auto input = inputs[no_weight_input++]; | |||
| if (!CompareInput(input, paras[i])) { | |||
| MS_LOG(ERROR) << "Please check the input information."; | |||
| MS_LOG(ERROR) << "InputsInfo --" << InputsInfo(paras, inputs); | |||
| if (error_msg != nullptr) { | |||
| std::stringstream str_stream; | |||
| str_stream << "Please check the input information.\n"; | |||
| str_stream << "InputsInfo --" << InputsInfo(paras, inputs); | |||
| *error_msg = str_stream.str(); | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @@ -165,17 +179,35 @@ std::string AscendInferenceSession::PrintInputShape(std::vector<T> shape) const | |||
| std::string AscendInferenceSession::InputsInfo(const std::vector<ParameterPtr> ¶s, | |||
| const std::vector<tensor::TensorPtr> &inputs) const { | |||
| const std::map<TypeId, std::string> dtype_name_map{ | |||
| {TypeId::kNumberTypeBegin, "Unknown"}, {TypeId::kNumberTypeBool, "Bool"}, | |||
| {TypeId::kNumberTypeFloat64, "Float64"}, {TypeId::kNumberTypeInt8, "Int8"}, | |||
| {TypeId::kNumberTypeUInt8, "Uint8"}, {TypeId::kNumberTypeInt16, "Int16"}, | |||
| {TypeId::kNumberTypeUInt16, "Uint16"}, {TypeId::kNumberTypeInt32, "Int32"}, | |||
| {TypeId::kNumberTypeUInt32, "Uint32"}, {TypeId::kNumberTypeInt64, "Int64"}, | |||
| {TypeId::kNumberTypeUInt64, "Uint64"}, {TypeId::kNumberTypeFloat16, "Float16"}, | |||
| {TypeId::kNumberTypeFloat32, "Float32"}, | |||
| }; | |||
| auto data_type_to_string = [&dtype_name_map](TypeId type_id) { | |||
| auto it = dtype_name_map.find(type_id); | |||
| if (it == dtype_name_map.end()) { | |||
| return std::string("Unknown"); | |||
| } | |||
| return it->second; | |||
| }; | |||
| std::string graph = "graph inputs:{ "; | |||
| for (size_t i = 0; i < paras.size(); ++i) { | |||
| graph += std::to_string(i) + ": dims " + std::to_string(AnfAlgo::GetOutputDeviceShape(paras[i], 0).size()) + | |||
| ", shape " + PrintInputShape(AnfAlgo::GetOutputDeviceShape(paras[i], 0)) + ", data type " + | |||
| std::to_string(AnfAlgo::GetSelectKernelBuildInfo(paras[i])->GetOutputDeviceType(0)) + " }"; | |||
| auto ¶ = paras[i]; | |||
| graph += std::to_string(i) + ": dims " + std::to_string(AnfAlgo::GetOutputDeviceShape(para, 0).size()) + | |||
| ", shape " + PrintInputShape(AnfAlgo::GetOutputDeviceShape(para, 0)) + ", data type " + | |||
| data_type_to_string(AnfAlgo::GetSelectKernelBuildInfo(para)->GetOutputDeviceType(0)) + " }"; | |||
| } | |||
| std::string actual = "actual inputs:{ "; | |||
| std::string actual = "given inputs:{ "; | |||
| for (size_t i = 0; i < inputs.size(); ++i) { | |||
| actual += std::to_string(i) + ": dims " + std::to_string(inputs[i]->shape().size()) + ", shape " + | |||
| PrintInputShape(inputs[i]->shape()) + ", data type " + std::to_string(inputs[i]->data_type()) + " }"; | |||
| PrintInputShape(inputs[i]->shape()) + ", data type " + data_type_to_string(inputs[i]->data_type()) + " }"; | |||
| } | |||
| return graph + " " + actual; | |||
| } | |||
| @@ -39,7 +39,8 @@ class AscendInferenceSession : public AscendSession { | |||
| void LoadInputData(const std::shared_ptr<KernelGraph> &kernel_graph, | |||
| const std::vector<tensor::TensorPtr> &inputs_const) const; | |||
| GraphId CompileGraph(NotNull<FuncGraphPtr> func_graph) override; | |||
| bool CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const override; | |||
| bool CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs, | |||
| std::string *error_msg) const override; | |||
| bool CompareInput(const tensor::TensorPtr &input, const ParameterPtr ¶meter) const; | |||
| template <typename T> | |||
| std::string PrintInputShape(std::vector<T> shape) const; | |||
| @@ -116,7 +116,7 @@ Status MSInferSession::LoadModelFromFile(const std::string &file_name, uint32_t | |||
| Status MSInferSession::UnloadModel(uint32_t model_id) { return SUCCESS; } | |||
| tensor::TensorPtr ServingTensor2MSTensor(const InferTensorBase &out_tensor) { | |||
| Status ServingTensor2MSTensor(size_t index, const InferTensorBase &out_tensor, tensor::TensorPtr &ms_tensor) { | |||
| std::vector<int> shape; | |||
| for (auto dim : out_tensor.shape()) { | |||
| shape.push_back(static_cast<int>(dim)); | |||
| @@ -134,14 +134,22 @@ tensor::TensorPtr ServingTensor2MSTensor(const InferTensorBase &out_tensor) { | |||
| auto it = type2id_map.find(out_tensor.data_type()); | |||
| if (it == type2id_map.end()) { | |||
| MSI_LOG_WARNING << "undefined MSI data type " << out_tensor.data_type(); | |||
| return nullptr; | |||
| return FAILED; | |||
| } else { | |||
| data_type = it->second; | |||
| } | |||
| auto ms_tensor = std::make_shared<tensor::Tensor>(data_type, shape); | |||
| ms_tensor = std::make_shared<tensor::Tensor>(data_type, shape); | |||
| if (ms_tensor->Size() != out_tensor.data_size()) { | |||
| MSI_LOG_ERROR << "input " << std::to_string(index) | |||
| << " data size not match shape and dtype, calculated required size " << ms_tensor->Size() | |||
| << ", given " << out_tensor.data_size(); | |||
| return INFER_STATUS(INVALID_INPUTS) << "input " << std::to_string(index) | |||
| << " data size not match shape and dtype, calculated required size " | |||
| << ms_tensor->Size() << ", given " << out_tensor.data_size(); | |||
| } | |||
| memcpy_s(ms_tensor->data_c(), ms_tensor->Size(), out_tensor.data(), out_tensor.data_size()); | |||
| return ms_tensor; | |||
| return SUCCESS; | |||
| } | |||
| void MSTensor2ServingTensor(tensor::TensorPtr ms_tensor, InferTensorBase &out_tensor) { | |||
| @@ -189,16 +197,18 @@ Status MSInferSession::ExecuteModel(uint32_t model_id, const RequestBase &reques | |||
| MS_LOG(ERROR) << "Execute Model " << model_id << " Failed, input tensor is null, index " << i; | |||
| return FAILED; | |||
| } | |||
| auto input = ServingTensor2MSTensor(*request[i]); | |||
| if (input == nullptr) { | |||
| tensor::TensorPtr input = nullptr; | |||
| auto ret = ServingTensor2MSTensor(i, *request[i], input); | |||
| if (ret != SUCCESS) { | |||
| MS_LOG(ERROR) << "Tensor convert failed"; | |||
| return FAILED; | |||
| return ret; | |||
| } | |||
| inputs.push_back(input); | |||
| } | |||
| if (!CheckModelInputs(model_id, inputs)) { | |||
| auto ret = CheckModelInputs(model_id, inputs); | |||
| if (ret != SUCCESS) { | |||
| MS_LOG(ERROR) << "Check Model " << model_id << " Inputs Failed"; | |||
| return INVALID_INPUTS; | |||
| return ret; | |||
| } | |||
| vector<tensor::TensorPtr> outputs = RunGraph(model_id, inputs); | |||
| if (outputs.empty()) { | |||
| @@ -354,9 +364,13 @@ Status MSInferSession::InitEnv(const std::string &device, uint32_t device_id) { | |||
| return SUCCESS; | |||
| } | |||
| bool MSInferSession::CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const { | |||
| Status MSInferSession::CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const { | |||
| MS_ASSERT(session_impl_ != nullptr); | |||
| return session_impl_->CheckModelInputs(graph_id, inputs); | |||
| std::string error_msg; | |||
| if (!session_impl_->CheckModelInputs(graph_id, inputs, &error_msg)) { | |||
| return INFER_STATUS(INVALID_INPUTS) << error_msg; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| } // namespace mindspore::inference | |||
| @@ -58,7 +58,7 @@ class MSInferSession : public InferSession { | |||
| static void RegAllOp(); | |||
| string AjustTargetName(const std::string &device); | |||
| Status CompileGraph(std::shared_ptr<FuncGraph> funcGraphPtr, uint32_t &model_id); | |||
| bool CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const; | |||
| Status CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const; | |||
| std::vector<tensor::TensorPtr> RunGraph(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs); | |||
| }; | |||
| } // namespace inference | |||
| @@ -97,7 +97,10 @@ class SessionBasic { | |||
| virtual GraphId GetFinalRunGraph() const { return kInvalidGraphId; } | |||
| void AssignParamKey(const KernelGraphPtr &kernel_graph); | |||
| void InitPSParamAndOptim(const KernelGraphPtr &kernel_graph, const std::vector<tensor::TensorPtr> &inputs_const); | |||
| virtual bool CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs) const { return true; } | |||
| virtual bool CheckModelInputs(uint32_t graph_id, const std::vector<tensor::TensorPtr> &inputs, | |||
| std::string *error_msg) const { | |||
| return true; | |||
| } | |||
| #ifdef ENABLE_DEBUGGER | |||
| // set debugger | |||
| @@ -103,9 +103,12 @@ endif () | |||
| if (ENABLE_ACL) | |||
| add_compile_definitions(ENABLE_ACL) | |||
| add_compile_definitions(ENABLE_DVPP_INTERFACE) | |||
| set(ALC_LIB_SO ${ACL_LIB_DIR}/lib64/libruntime.so ${ACL_LIB_DIR}/lib64/libascendcl.so | |||
| ${ACL_LIB_DIR}/lib64/libacl_retr.so ${ACL_LIB_DIR}/lib64/libacl_cblas.so) | |||
| ${ACL_LIB_DIR}/lib64/libacl_retr.so ${ACL_LIB_DIR}/lib64/libacl_cblas.so | |||
| ${ACL_LIB_DIR}/lib64/libacl_dvpp.so) | |||
| target_link_libraries(ms_serving ${ALC_LIB_SO}) | |||
| target_link_libraries(ms_serving jpeg_turbo::jpeg) | |||
| else () | |||
| target_link_libraries(ms_serving inference mindspore_gvar) | |||
| endif () | |||
| @@ -16,6 +16,7 @@ | |||
| #include <memory> | |||
| #include <algorithm> | |||
| #include <fstream> | |||
| #include "serving/acl/acl_session.h" | |||
| #include "include/infer_log.h" | |||
| @@ -25,7 +26,7 @@ std::shared_ptr<InferSession> InferSession::CreateSession(const std::string &dev | |||
| try { | |||
| auto session = std::make_shared<AclSession>(); | |||
| auto ret = session->InitEnv(device, device_id); | |||
| if (!ret) { | |||
| if (ret != SUCCESS) { | |||
| return nullptr; | |||
| } | |||
| return session; | |||
| @@ -36,22 +37,123 @@ std::shared_ptr<InferSession> InferSession::CreateSession(const std::string &dev | |||
| } | |||
| Status AclSession::LoadModelFromFile(const std::string &file_name, uint32_t &model_id) { | |||
| return model_process_.LoadModelFromFile(file_name, model_id) ? SUCCESS : FAILED; | |||
| Status ret = model_process_.LoadModelFromFile(file_name, model_id); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Load model from file failed, model file " << file_name; | |||
| return FAILED; | |||
| } | |||
| std::string dvpp_config_file; | |||
| auto index = file_name.rfind("."); | |||
| if (index == std::string::npos) { | |||
| dvpp_config_file = file_name; | |||
| } else { | |||
| dvpp_config_file = file_name.substr(0, index); | |||
| } | |||
| dvpp_config_file += "_dvpp_config.json"; | |||
| std::ifstream fp(dvpp_config_file); | |||
| if (!fp.is_open()) { | |||
| MSI_LOG_INFO << "Dvpp config file not exist, model will execute with tensors as inputs, dvpp config file " | |||
| << dvpp_config_file; | |||
| return SUCCESS; | |||
| } | |||
| fp.close(); | |||
| if (dvpp_process_.InitWithJsonConfig(dvpp_config_file) != SUCCESS) { | |||
| MSI_LOG_ERROR << "Dvpp config file parse error, dvpp config file " << dvpp_config_file; | |||
| return FAILED; | |||
| } | |||
| execute_with_dvpp_ = true; | |||
| MSI_LOG_INFO << "Dvpp config success"; | |||
| return SUCCESS; | |||
| } | |||
| Status AclSession::UnloadModel(uint32_t model_id) { | |||
| Status AclSession::UnloadModel(uint32_t /*model_id*/) { | |||
| model_process_.UnLoad(); | |||
| return SUCCESS; | |||
| } | |||
| Status AclSession::ExecuteModel(uint32_t model_id, const RequestBase &request, | |||
| Status AclSession::ExecuteModel(uint32_t /*model_id*/, const RequestBase &request, | |||
| ReplyBase &reply) { // set d context | |||
| aclError rt_ret = aclrtSetCurrentContext(context_); | |||
| if (rt_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "set the ascend device context failed"; | |||
| return FAILED; | |||
| } | |||
| return model_process_.Execute(request, reply) ? SUCCESS : FAILED; | |||
| return model_process_.Execute(request, reply); | |||
| } | |||
| Status AclSession::PreProcess(uint32_t /*model_id*/, const InferImagesBase *images_input, | |||
| ImagesDvppOutput &dvpp_output) { | |||
| if (images_input == nullptr) { | |||
| MSI_LOG_ERROR << "images input is nullptr"; | |||
| return FAILED; | |||
| } | |||
| auto batch_size = images_input->batch_size(); | |||
| if (batch_size <= 0) { | |||
| MSI_LOG_ERROR << "invalid batch size " << images_input->batch_size(); | |||
| return FAILED; | |||
| } | |||
| std::vector<const void *> pic_buffer_list; | |||
| std::vector<size_t> pic_size_list; | |||
| for (size_t i = 0; i < batch_size; i++) { | |||
| const void *pic_buffer = nullptr; | |||
| uint32_t pic_size = 0; | |||
| if (!images_input->get(i, pic_buffer, pic_size) || pic_buffer == nullptr || pic_size == 0) { | |||
| MSI_LOG_ERROR << "Get request " << 0 << "th buffer failed"; | |||
| return FAILED; | |||
| } | |||
| pic_buffer_list.push_back(pic_buffer); | |||
| pic_size_list.push_back(pic_size); | |||
| } | |||
| auto ret = dvpp_process_.Process(pic_buffer_list, pic_size_list, dvpp_output.buffer_device, dvpp_output.buffer_size); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "dvpp process failed"; | |||
| return ret; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| Status AclSession::ExecuteModel(uint32_t model_id, const ImagesRequestBase &images_inputs, // images for preprocess | |||
| const RequestBase &request, ReplyBase &reply) { | |||
| if (!execute_with_dvpp_) { | |||
| MSI_LOG_ERROR << "Unexpected images as inputs, DVPP not config"; | |||
| return INFER_STATUS(INVALID_INPUTS) << "Unexpected images as inputs, DVPP not config"; | |||
| } | |||
| aclError rt_ret = aclrtSetCurrentContext(context_); | |||
| if (rt_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "set the ascend device context failed"; | |||
| return FAILED; | |||
| } | |||
| if (images_inputs.size() != 1) { | |||
| MSI_LOG_ERROR << "Only support one input to do DVPP preprocess"; | |||
| return INFER_STATUS(INVALID_INPUTS) << "Only support one input to do DVPP preprocess"; | |||
| } | |||
| if (images_inputs[0] == nullptr) { | |||
| MSI_LOG_ERROR << "Get first images input failed"; | |||
| return FAILED; | |||
| } | |||
| if (images_inputs[0]->batch_size() != model_process_.GetBatchSize()) { | |||
| MSI_LOG_ERROR << "Input batch size " << images_inputs[0]->batch_size() << " not match Model batch size " | |||
| << model_process_.GetBatchSize(); | |||
| return INFER_STATUS(INVALID_INPUTS) << "Input batch size " << images_inputs[0]->batch_size() | |||
| << " not match Model batch size " << model_process_.GetBatchSize(); | |||
| } | |||
| if (request.size() != 0) { | |||
| MSI_LOG_ERROR << "only support one input, images input size is 1, tensor inputs is not 0 " << request.size(); | |||
| return INFER_STATUS(INVALID_INPUTS) << "only support one input, images input size is 1, tensor inputs is not 0 " | |||
| << request.size(); | |||
| } | |||
| ImagesDvppOutput dvpp_output; | |||
| Status ret = PreProcess(model_id, images_inputs[0], dvpp_output); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "DVPP preprocess failed"; | |||
| return ret; | |||
| } | |||
| ret = model_process_.Execute(dvpp_output.buffer_device, dvpp_output.buffer_size, reply); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Execute model failed"; | |||
| return ret; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| Status AclSession::InitEnv(const std::string &device_type, uint32_t device_id) { | |||
| @@ -95,11 +197,16 @@ Status AclSession::InitEnv(const std::string &device_type, uint32_t device_id) { | |||
| model_process_.SetIsDevice(is_device); | |||
| MSI_LOG_INFO << "get run mode success is device input/output " << is_device; | |||
| if (dvpp_process_.InitResource(stream_) != SUCCESS) { | |||
| MSI_LOG_ERROR << "dvpp init resource failed"; | |||
| return FAILED; | |||
| } | |||
| MSI_LOG_INFO << "Init acl success, device id " << device_id_; | |||
| return SUCCESS; | |||
| } | |||
| Status AclSession::FinalizeEnv() { | |||
| dvpp_process_.Finalize(); | |||
| aclError ret; | |||
| if (stream_ != nullptr) { | |||
| ret = aclrtDestroyStream(stream_); | |||
| @@ -25,9 +25,11 @@ | |||
| #include "include/inference.h" | |||
| #include "serving/acl/model_process.h" | |||
| #include "serving/acl/dvpp_process.h" | |||
| namespace mindspore { | |||
| namespace inference { | |||
| class AclSession : public InferSession { | |||
| public: | |||
| AclSession(); | |||
| @@ -37,6 +39,8 @@ class AclSession : public InferSession { | |||
| Status LoadModelFromFile(const std::string &file_name, uint32_t &model_id) override; | |||
| Status UnloadModel(uint32_t model_id) override; | |||
| Status ExecuteModel(uint32_t model_id, const RequestBase &request, ReplyBase &reply) override; | |||
| Status ExecuteModel(uint32_t model_id, const ImagesRequestBase &images_inputs, // images for preprocess | |||
| const RequestBase &request, ReplyBase &reply) override; | |||
| private: | |||
| std::string device_type_; | |||
| @@ -44,6 +48,10 @@ class AclSession : public InferSession { | |||
| aclrtStream stream_ = nullptr; | |||
| aclrtContext context_ = nullptr; | |||
| ModelProcess model_process_; | |||
| bool execute_with_dvpp_ = false; | |||
| DvppProcess dvpp_process_; | |||
| Status PreProcess(uint32_t model_id, const InferImagesBase *images_input, ImagesDvppOutput &dvpp_output); | |||
| }; | |||
| } // namespace inference | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,159 @@ | |||
| /** | |||
| * Copyright 2020 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 INC_DVPP_PROCESS_ACL | |||
| #define INC_DVPP_PROCESS_ACL | |||
| #include <vector> | |||
| #include <string> | |||
| #include "acl/acl.h" | |||
| #include "acl/acl_mdl.h" | |||
| #include "acl/acl_rt.h" | |||
| #include "acl/ops/acl_dvpp.h" | |||
| #include "include/inference.h" | |||
| namespace mindspore::inference { | |||
| struct DvppDecodePara { | |||
| acldvppPixelFormat pixel_format = PIXEL_FORMAT_YUV_SEMIPLANAR_420; | |||
| }; | |||
| struct DvppResizePara { | |||
| uint32_t output_width = 0; | |||
| uint32_t output_height = 0; | |||
| }; | |||
| enum DvppCropType { | |||
| // crop left,top,right,bottom is given in config | |||
| kDvppCropTypeOffset = 0, | |||
| // crop left,top,right,bottom is calculated by image width/height and output crop width/height | |||
| kDvppCropTypeCentre = 1, | |||
| }; | |||
| struct DvppRoiArea { | |||
| uint32_t left = 0; | |||
| uint32_t top = 0; | |||
| uint32_t right = 0; | |||
| uint32_t bottom = 0; | |||
| }; | |||
| struct DvppCropInfo { | |||
| DvppCropType crop_type = kDvppCropTypeOffset; | |||
| DvppRoiArea crop_area; // when kDvppCropTypeOffset | |||
| uint32_t crop_width = 0; // when kDvppCropTypeCentre | |||
| uint32_t crop_height = 0; // when kDvppCropTypeCentre | |||
| }; | |||
| struct DvppCropPara { | |||
| DvppCropInfo crop_info; | |||
| uint32_t output_width = 0; | |||
| uint32_t output_height = 0; | |||
| }; | |||
| struct DvppCropAndPastePara { | |||
| DvppCropInfo crop_info; | |||
| DvppRoiArea paste_area; | |||
| uint32_t output_width = 0; | |||
| uint32_t output_height = 0; | |||
| }; | |||
| class DvppProcess { | |||
| public: | |||
| DvppProcess(); | |||
| ~DvppProcess(); | |||
| Status InitResource(aclrtStream stream); | |||
| void Finalize(); | |||
| Status InitJpegDecodePara(const DvppDecodePara &decode_para); // jpeg decode + (resize | crop) | |||
| Status InitResizePara(const DvppResizePara &resize_para); // jpeg decode + resize | |||
| Status InitCropPara(const DvppCropPara &crop_para); // jpeg decode + crop | |||
| Status InitCropAndPastePara(const DvppCropAndPastePara &crop_and_paste_para); // jpeg decode + crop&paste | |||
| Status InitWithJsonConfig(const std::string &json_config); | |||
| // output device buffer will be destroy by DvppProcess itself. | |||
| Status Process(const void *pic_buffer, size_t pic_buffer_size, void *&output_device_buffer, size_t &output_size); | |||
| Status Process(const std::vector<const void *> &pic_buffer_list, const std::vector<size_t> &pic_buffer_size_list, | |||
| void *&output_device_buffer, size_t &output_size); | |||
| private: | |||
| uint32_t pic_width_ = 0; | |||
| uint32_t pic_height_ = 0; | |||
| DvppDecodePara decode_para_; | |||
| DvppResizePara resize_para_; | |||
| DvppCropPara crop_para_; | |||
| DvppCropAndPastePara crop_and_paste_para_; | |||
| // only one of the resize or crop flag can be true | |||
| bool to_resize_flag_ = false; | |||
| bool to_crop_flag_ = false; | |||
| bool to_crop_and_paste_flag_ = false; | |||
| void *input_pic_dev_buffer_ = nullptr; | |||
| uint32_t input_pic_buffer_size_ = 0; | |||
| uint32_t decode_output_buffer_size_ = 0; | |||
| void *decode_output_buffer_dev_ = nullptr; | |||
| acldvppPicDesc *decode_output_desc_ = nullptr; | |||
| acldvppResizeConfig *resize_config_ = nullptr; | |||
| acldvppRoiConfig *crop_area_ = nullptr; | |||
| acldvppRoiConfig *paste_area_ = nullptr; | |||
| acldvppPicDesc *vpc_output_desc_ = nullptr; | |||
| void *vpc_output_buffer_dev_ = nullptr; // vpc_output_buffer_size_ length | |||
| uint32_t vpc_output_buffer_size_ = 0; | |||
| void *batch_vpc_output_buffer_dev_ = nullptr; // batch_size_ * vpc_output_buffer_size_ length | |||
| uint32_t batch_size_ = 0; | |||
| aclrtStream stream_ = nullptr; | |||
| acldvppChannelDesc *dvpp_channel_desc_ = nullptr; | |||
| uint32_t AlignmentHelper(uint32_t org_size, uint32_t alignment) const; | |||
| uint32_t GetImageBufferSize(uint32_t stride_width, uint32_t stride_height, acldvppPixelFormat pixel_format) const; | |||
| Status GetPicDescStride(uint32_t width, uint32_t height, uint32_t &stride_width, uint32_t &stride_height); | |||
| Status GetPicDescStrideDecode(uint32_t width, uint32_t height, uint32_t &stride_width, uint32_t &stride_height); | |||
| Status InputInputBuffer(const void *pic_buffer, size_t pic_buffer_size); | |||
| Status InitDecodeOutputDesc(uint32_t image_width, | |||
| uint32_t image_height); // decode_output_desc_, decode_output_buffer_dev_ | |||
| Status CheckRoiAreaWidthHeight(uint32_t width, uint32_t height); | |||
| Status CheckAndAdjustRoiArea(DvppRoiArea &area); | |||
| Status UpdateCropArea(uint32_t image_width, uint32_t image_height); | |||
| Status CheckResizeImageInfo(uint32_t image_width, uint32_t image_height) const; | |||
| void DestroyDecodeDesc(); | |||
| Status InitVpcOutputDesc(uint32_t output_width, uint32_t output_height, | |||
| acldvppPixelFormat pixel_format); // vpc_output_desc_, vpc_output_buffer_dev_batch_ | |||
| Status InitRoiAreaConfig(acldvppRoiConfig *&roi_area, const DvppRoiArea &init_para); | |||
| Status InitCommonCropPara(DvppCropInfo &crop_info, uint32_t out_width, uint32_t out_height); | |||
| Status InitResizeOutputDesc(); // vpc_output_desc_, vpc_output_buffer_dev_, resize_config | |||
| Status InitCropOutputDesc(); // vpc_output_desc_, vpc_output_buffer_dev_, crop_area_ | |||
| Status InitCropAndPasteOutputDesc(); // vpc_output_desc_, vpc_output_buffer_dev_, crop_area_, paste_area_ | |||
| void DestroyVpcOutputDesc(); | |||
| Status ProcessDecode(); | |||
| Status ProcessResize(); | |||
| Status ProcessCrop(); | |||
| Status ProcessCropAndPaste(); | |||
| void DestroyResource(); | |||
| Status GetJpegWidthHeight(const void *pic_buffer, size_t pic_buffer_size, uint32_t &image_width, | |||
| uint32_t &image_height); | |||
| }; | |||
| } // namespace mindspore::inference | |||
| #endif // INC_DVPP_PROCESS_ACL | |||
| @@ -0,0 +1,68 @@ | |||
| { | |||
| "preprocess": [ | |||
| { | |||
| "input": { | |||
| "index": 0 | |||
| }, | |||
| "decode_para": { | |||
| "out_pixel_format": "YUV420SP" | |||
| }, | |||
| "dvpp_process": { | |||
| "op_name": "resize", | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| }, | |||
| "sample of dvpp_process content": [ | |||
| { | |||
| "op_name": "resize", | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| }, | |||
| { | |||
| "op_name": "crop", | |||
| "crop_type": "offset", | |||
| "crop_left": 10, | |||
| "crop_top": 10, | |||
| "crop_right": 100, | |||
| "crop_bottom": 200, | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| }, | |||
| { | |||
| "op_name": "crop", | |||
| "crop_type": "centre", | |||
| "crop_width": 100, | |||
| "crop_height": 100, | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| }, | |||
| { | |||
| "op_name": "crop_and_paste", | |||
| "crop_type": "offset", | |||
| "crop_left": 10, | |||
| "crop_top": 10, | |||
| "crop_right": 100, | |||
| "crop_bottom": 200, | |||
| "paste_left": 10, | |||
| "paste_top": 10, | |||
| "paste_right": 100, | |||
| "paste_bottom": 200, | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| }, | |||
| { | |||
| "op_name": "crop_and_paste", | |||
| "crop_type": "centre", | |||
| "crop_width": 100, | |||
| "crop_height": 100, | |||
| "paste_left": 10, | |||
| "paste_top": 10, | |||
| "paste_right": 100, | |||
| "paste_bottom": 200, | |||
| "out_width": 224, | |||
| "out_height": 224 | |||
| } | |||
| ] | |||
| } | |||
| ] | |||
| } | |||
| @@ -23,41 +23,44 @@ | |||
| namespace mindspore { | |||
| namespace inference { | |||
| bool ModelProcess::LoadModelFromFile(const std::string &file_name, uint32_t &model_id) { | |||
| aclError acl_ret = aclmdlLoadFromFile(file_name.c_str(), &model_id); | |||
| if (acl_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Read model file failed, file name is " << file_name; | |||
| return false; | |||
| } | |||
| MSI_LOG_INFO << "Load model success " << file_name; | |||
| Status ModelProcess::PreInitModelResource() { | |||
| model_desc_ = aclmdlCreateDesc(); | |||
| acl_ret = aclmdlGetDesc(model_desc_, model_id); | |||
| aclError acl_ret = aclmdlGetDesc(model_desc_, model_id_); | |||
| if (acl_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Read model desc failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| bool ret = InitInputsBuffer(); | |||
| if (!ret) { | |||
| Status ret = InitInputsBuffer(); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Create input buffer failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| ret = InitOutputsBuffer(); | |||
| if (!ret) { | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Create output buffer failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| Status ModelProcess::LoadModelFromFile(const std::string &file_name, uint32_t &model_id) { | |||
| aclError acl_ret = aclmdlLoadFromFile(file_name.c_str(), &model_id); | |||
| if (acl_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Read model file failed, file name is " << file_name; | |||
| return FAILED; | |||
| } | |||
| MSI_LOG_INFO << "Load model success " << file_name; | |||
| model_id_ = model_id; | |||
| return true; | |||
| if (PreInitModelResource() != SUCCESS) { | |||
| aclmdlUnload(model_id_); | |||
| MSI_LOG_ERROR << "Pre init model resource failed, file name is " << file_name; | |||
| return FAILED; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| bool ModelProcess::InitInputsBuffer() { | |||
| Status ModelProcess::InitInputsBuffer() { | |||
| aclError ret; | |||
| inputs_ = aclmdlCreateDataset(); | |||
| if (inputs_ == nullptr) { | |||
| MSI_LOG_ERROR << "Create input dataset failed"; | |||
| return false; | |||
| } | |||
| size_t input_size = aclmdlGetNumInputs(model_desc_); | |||
| for (size_t i = 0; i < input_size; ++i) { | |||
| @@ -67,7 +70,7 @@ bool ModelProcess::InitInputsBuffer() { | |||
| ret = aclrtMalloc(&data_mem_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Malloc device input buffer faild , input size " << buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } | |||
| @@ -75,17 +78,20 @@ bool ModelProcess::InitInputsBuffer() { | |||
| ret = aclmdlGetInputDims(model_desc_, i, &dims); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Get input shape failed"; | |||
| return false; | |||
| if (!is_run_on_device_) { | |||
| aclrtFree(data_mem_buffer); | |||
| } | |||
| return FAILED; | |||
| } | |||
| aclDataType dataType = aclmdlGetInputDataType(model_desc_, i); | |||
| aclDataType data_type = aclmdlGetInputDataType(model_desc_, i); | |||
| std::vector<int64_t> shape(dims.dims, dims.dims + dims.dimCount); | |||
| input_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, dataType, shape}); | |||
| input_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, data_type, shape}); | |||
| } | |||
| MSI_LOG_INFO << "Create model inputs success"; | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| bool ModelProcess::CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset) { | |||
| Status ModelProcess::CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset) { | |||
| aclError ret; | |||
| auto free_data_buffer = [this](void *dataMemBuffer) { | |||
| if (!is_run_on_device_) { | |||
| @@ -98,13 +104,13 @@ bool ModelProcess::CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, | |||
| ret = aclrtMalloc(&data_mem_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Malloc device buffer faild , buffer size " << buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } else { | |||
| ret = aclrtMallocHost(&data_mem_buffer, buffer_size); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Malloc device buffer faild , buffer size " << buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } | |||
| @@ -112,46 +118,51 @@ bool ModelProcess::CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, | |||
| if (data_buffer == nullptr) { | |||
| MSI_LOG_ERROR << "Create Data Buffer failed"; | |||
| free_data_buffer(data_mem_buffer); | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| ret = aclmdlAddDatasetBuffer(dataset, data_buffer); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "add data buffer failed"; | |||
| free_data_buffer(data_mem_buffer); | |||
| aclDestroyDataBuffer(data_buffer); | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| bool ModelProcess::InitOutputsBuffer() { | |||
| Status ModelProcess::InitOutputsBuffer() { | |||
| aclError ret; | |||
| outputs_ = aclmdlCreateDataset(); | |||
| if (outputs_ == nullptr) { | |||
| MSI_LOG_ERROR << "Create input dataset failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| size_t output_size = aclmdlGetNumOutputs(model_desc_); | |||
| for (size_t i = 0; i < output_size; ++i) { | |||
| auto buffer_size = aclmdlGetOutputSizeByIndex(model_desc_, i); | |||
| void *data_mem_buffer = nullptr; | |||
| if (CreateDataBuffer(data_mem_buffer, buffer_size, outputs_) != true) { | |||
| if (CreateDataBuffer(data_mem_buffer, buffer_size, outputs_) != SUCCESS) { | |||
| MSI_LOG_ERROR << "add output data buffer failed, buffer size " << buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| aclmdlIODims dims; | |||
| ret = aclmdlGetOutputDims(model_desc_, i, &dims); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Get input shape failed"; | |||
| return false; | |||
| if (!is_run_on_device_) { | |||
| aclrtFree(data_mem_buffer); | |||
| } else { | |||
| aclrtFreeHost(data_mem_buffer); | |||
| } | |||
| return FAILED; | |||
| } | |||
| aclDataType dataType = aclmdlGetOutputDataType(model_desc_, i); | |||
| aclDataType data_type = aclmdlGetOutputDataType(model_desc_, i); | |||
| std::vector<int64_t> shape(dims.dims, dims.dims + dims.dimCount); | |||
| output_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, dataType, shape}); | |||
| output_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, data_type, shape}); | |||
| } | |||
| MSI_LOG_INFO << "Create model output success"; | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| void ModelProcess::DestroyInputsDataset() { | |||
| @@ -176,27 +187,29 @@ void ModelProcess::DestroyInputsDataMem() { | |||
| } | |||
| void ModelProcess::DestroyInputsBuffer() { | |||
| DestroyInputsDataset(); | |||
| DestroyInputsDataMem(); | |||
| DestroyInputsDataset(); | |||
| } | |||
| void ModelProcess::DestroyOutputsBuffer() { | |||
| for (const auto &item : output_infos_) { | |||
| if (!is_run_on_device_) { | |||
| aclrtFree(item.device_data); | |||
| } else { | |||
| aclrtFreeHost(item.device_data); | |||
| } | |||
| } | |||
| output_infos_.clear(); | |||
| if (outputs_ == nullptr) { | |||
| return; | |||
| } | |||
| for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(outputs_); i++) { | |||
| auto dataBuffer = aclmdlGetDatasetBuffer(outputs_, i); | |||
| auto data = aclGetDataBufferAddr(dataBuffer); | |||
| if (!is_run_on_device_) { | |||
| aclrtFree(data); | |||
| } else { | |||
| aclrtFreeHost(data); | |||
| } | |||
| aclDestroyDataBuffer(dataBuffer); | |||
| } | |||
| aclmdlDestroyDataset(outputs_); | |||
| outputs_ = nullptr; | |||
| output_infos_.clear(); | |||
| } | |||
| void ModelProcess::UnLoad() { | |||
| @@ -213,24 +226,26 @@ void ModelProcess::UnLoad() { | |||
| MSI_LOG_INFO << "End unload model " << model_id_; | |||
| } | |||
| bool ModelProcess::CheckAndInitInput(const RequestBase &request) { | |||
| Status ModelProcess::CheckAndInitInput(const RequestBase &request) { | |||
| aclError ret; | |||
| inputs_ = aclmdlCreateDataset(); | |||
| // check inputs | |||
| if (request.size() != input_infos_.size()) { | |||
| MSI_LOG_ERROR << "inputs count not match, required count " << input_infos_.size() << ", given count " | |||
| << request.size(); | |||
| return false; | |||
| return INFER_STATUS(INVALID_INPUTS) << "inputs count not match, required count " << input_infos_.size() | |||
| << ", given count " << request.size(); | |||
| } | |||
| for (size_t i = 0; i < input_infos_.size(); i++) { | |||
| if (request[i] == nullptr) { | |||
| MSI_LOG_ERROR << "input " << i << " cannot be null"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| if (request[i]->data_size() != input_infos_[i].buffer_size) { | |||
| MSI_LOG_ERROR << "input " << i << " data size not match, required size " << input_infos_[i].buffer_size | |||
| << ", given count " << request[i]->data_size(); | |||
| return false; | |||
| return INFER_STATUS(INVALID_INPUTS) << "input " << i << " data size not match, required size " | |||
| << input_infos_[i].buffer_size << ", given count " << request[i]->data_size(); | |||
| } | |||
| } | |||
| // copy inputs | |||
| @@ -242,7 +257,7 @@ bool ModelProcess::CheckAndInitInput(const RequestBase &request) { | |||
| ret = aclrtMemcpy(info.device_data, info.buffer_size, data, request[i]->data_size(), ACL_MEMCPY_HOST_TO_DEVICE); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "memcpy input " << i << " data to device failed, buffer size " << request[i]->data_size(); | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| input_buffer = info.device_data; | |||
| } else { | |||
| @@ -251,32 +266,70 @@ bool ModelProcess::CheckAndInitInput(const RequestBase &request) { | |||
| auto data_buffer = aclCreateDataBuffer(input_buffer, info.buffer_size); | |||
| if (data_buffer == nullptr) { | |||
| MSI_LOG_ERROR << "Create Data Buffer failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| ret = aclmdlAddDatasetBuffer(inputs_, data_buffer); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "add data buffer failed"; | |||
| aclDestroyDataBuffer(data_buffer); | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| Status ModelProcess::CheckAndInitDvppInput(const void *dvpp_outputs_buffer_dev, size_t dvpp_outputs_buffer_size, | |||
| size_t input_index) { | |||
| aclError ret; | |||
| inputs_ = aclmdlCreateDataset(); | |||
| // check inputs | |||
| if (input_index >= input_infos_.size()) { | |||
| MSI_LOG_ERROR << "inputs count not match, required count " << input_infos_.size() << ", given index " | |||
| << input_index; | |||
| return INFER_STATUS(INVALID_INPUTS) << "inputs count not match, required count " << input_infos_.size() | |||
| << ", given index " << input_index; | |||
| } | |||
| if (dvpp_outputs_buffer_dev == nullptr) { | |||
| MSI_LOG_ERROR << "input " << 0 << " cannot be null"; | |||
| return FAILED; | |||
| } | |||
| if (dvpp_outputs_buffer_size != input_infos_[input_index].buffer_size) { | |||
| MSI_LOG_ERROR << "input " << 0 << " data size not match, required size " << input_infos_[input_index].buffer_size | |||
| << ", given count " << dvpp_outputs_buffer_size; | |||
| return INFER_STATUS(INVALID_INPUTS) << "input " << 0 << " data size not match, required size " | |||
| << input_infos_[input_index].buffer_size << ", given count " | |||
| << dvpp_outputs_buffer_size; | |||
| } | |||
| // copy inputs | |||
| auto &info = input_infos_[input_index]; | |||
| auto data_buffer = aclCreateDataBuffer(const_cast<void *>(dvpp_outputs_buffer_dev), info.buffer_size); | |||
| if (data_buffer == nullptr) { | |||
| MSI_LOG_ERROR << "Create Data Buffer failed"; | |||
| return FAILED; | |||
| } | |||
| ret = aclmdlAddDatasetBuffer(inputs_, data_buffer); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "add data buffer failed"; | |||
| aclDestroyDataBuffer(data_buffer); | |||
| return FAILED; | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| bool ModelProcess::BuildOutputs(ReplyBase &reply) { | |||
| Status ModelProcess::BuildOutputs(ReplyBase &reply) { | |||
| aclError ret; | |||
| // copy outputs | |||
| reply.clear(); | |||
| std::unordered_map<aclDataType, inference::DataType> dataTypeMap = { | |||
| std::unordered_map<aclDataType, inference::DataType> data_type_map = { | |||
| {ACL_FLOAT16, inference::kMSI_Float16}, {ACL_FLOAT, inference::kMSI_Float32}, {ACL_DOUBLE, inference::kMSI_Float64}, | |||
| {ACL_INT8, inference::kMSI_Int8}, {ACL_INT16, inference::kMSI_Int16}, {ACL_INT32, inference::kMSI_Int32}, | |||
| {ACL_INT64, inference::kMSI_Int64}, {ACL_UINT8, inference::kMSI_Uint8}, {ACL_UINT16, inference::kMSI_Uint16}, | |||
| {ACL_UINT32, inference::kMSI_Uint32}, {ACL_UINT64, inference::kMSI_Uint64}, {ACL_BOOL, inference::kMSI_Bool}, | |||
| }; | |||
| auto trans_to_serving_type = [&dataTypeMap](aclDataType data_type) { | |||
| auto it = dataTypeMap.find(data_type); | |||
| if (it == dataTypeMap.end()) { | |||
| auto trans_to_serving_type = [&data_type_map](aclDataType data_type) { | |||
| auto it = data_type_map.find(data_type); | |||
| if (it == data_type_map.end()) { | |||
| return inference::kMSI_Unknown; | |||
| } else { | |||
| return it->second; | |||
| @@ -287,53 +340,93 @@ bool ModelProcess::BuildOutputs(ReplyBase &reply) { | |||
| auto output = reply.add(); | |||
| if (output == nullptr) { | |||
| MSI_LOG_ERROR << "add new output failed"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| output->set_data_type(trans_to_serving_type(info.data_type)); | |||
| output->set_shape(info.dims); | |||
| if (!output->resize_data(info.buffer_size)) { | |||
| MSI_LOG_ERROR << "new output data buffer failed, data size " << info.buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| if (!is_run_on_device_) { | |||
| ret = aclrtMemcpy(output->mutable_data(), output->data_size(), info.device_data, info.buffer_size, | |||
| ACL_MEMCPY_DEVICE_TO_HOST); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Memcpy output " << i << " to host failed, memory size " << info.buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } else { | |||
| ret = aclrtMemcpy(output->mutable_data(), output->data_size(), info.device_data, info.buffer_size, | |||
| ACL_MEMCPY_HOST_TO_HOST); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Memcpy output " << i << " to host failed, memory size " << info.buffer_size; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| Status ModelProcess::Execute(const RequestBase &request, ReplyBase &reply) { | |||
| aclError acl_ret; | |||
| Status ret = CheckAndInitInput(request); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "check or init input failed"; | |||
| DestroyInputsDataset(); | |||
| return ret; // forward status error | |||
| } | |||
| acl_ret = aclmdlExecute(model_id_, inputs_, outputs_); | |||
| DestroyInputsDataset(); | |||
| if (acl_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Execute Model Failed"; | |||
| return FAILED; | |||
| } | |||
| ret = BuildOutputs(reply); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Build outputs faield"; | |||
| return FAILED; | |||
| } | |||
| MSI_LOG_INFO << "excute model success"; | |||
| return SUCCESS; | |||
| } | |||
| bool ModelProcess::Execute(const RequestBase &request, ReplyBase &reply) { | |||
| Status ModelProcess::Execute(const void *dvpp_outputs_buffer_dev, size_t dvpp_outputs_buffer_size, ReplyBase &reply) { | |||
| aclError acl_ret; | |||
| if (CheckAndInitInput(request) != true) { | |||
| if (input_infos_.size() != 1) { | |||
| MSI_LOG_ERROR << "can only support input size 1, now model inputs size is " << input_infos_.size(); | |||
| return INFER_STATUS(INVALID_INPUTS) << "can only support input size 1, now model inputs size is " | |||
| << input_infos_.size(); | |||
| } | |||
| Status ret = CheckAndInitDvppInput(dvpp_outputs_buffer_dev, dvpp_outputs_buffer_size, 0); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "check or init input failed"; | |||
| DestroyInputsDataset(); | |||
| return false; | |||
| return ret; // forward status msg | |||
| } | |||
| acl_ret = aclmdlExecute(model_id_, inputs_, outputs_); | |||
| DestroyInputsDataset(); | |||
| if (acl_ret != ACL_ERROR_NONE) { | |||
| MSI_LOG_ERROR << "Execute Model Failed"; | |||
| return false; | |||
| return INFER_STATUS(FAILED) << "Execute Model Failed"; | |||
| } | |||
| bool ret = BuildOutputs(reply); | |||
| if (!ret) { | |||
| ret = BuildOutputs(reply); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG_ERROR << "Build outputs faield"; | |||
| return false; | |||
| return FAILED; | |||
| } | |||
| MSI_LOG_INFO << "excute model success"; | |||
| return true; | |||
| return SUCCESS; | |||
| } | |||
| size_t ModelProcess::GetBatchSize() const { | |||
| if (input_infos_.empty()) { | |||
| MSI_LOG_ERROR << "Model is not loaded"; | |||
| return 0; | |||
| } | |||
| if (input_infos_[0].dims.empty()) { | |||
| return 1; | |||
| } | |||
| return static_cast<size_t>(input_infos_[0].dims[0]); | |||
| } | |||
| } // namespace inference | |||
| @@ -21,7 +21,6 @@ | |||
| #include "acl/acl.h" | |||
| #include "acl/acl_mdl.h" | |||
| #include "acl/acl_rt.h" | |||
| #include "serving/core/util/status.h" | |||
| #include "include/inference.h" | |||
| namespace mindspore { | |||
| @@ -34,21 +33,30 @@ struct AclTensorInfo { | |||
| std::vector<int64_t> dims; | |||
| }; | |||
| struct ImagesDvppOutput { | |||
| void *buffer_device = nullptr; | |||
| size_t buffer_size = 0; | |||
| size_t input_index = 0; | |||
| }; | |||
| class ModelProcess { | |||
| public: | |||
| ModelProcess() {} | |||
| ~ModelProcess() {} | |||
| bool LoadModelFromFile(const std::string &file_name, uint32_t &model_id); | |||
| Status LoadModelFromFile(const std::string &file_name, uint32_t &model_id); | |||
| void UnLoad(); | |||
| // override this method to avoid request/reply data copy | |||
| bool Execute(const RequestBase &request, ReplyBase &reply); | |||
| Status Execute(const RequestBase &request, ReplyBase &reply); | |||
| Status Execute(const void *dvpp_outputs_buffer_dev, size_t dvpp_outputs_buffer_size, ReplyBase &reply); | |||
| void SetIsDevice(bool is_device) { is_run_on_device_ = is_device; } | |||
| size_t GetBatchSize() const; | |||
| private: | |||
| uint32_t model_id_ = 0xffffffff; | |||
| // if run one device(AICPU), there is no need to alloc device memory and copy inputs to(/outputs from) device | |||
| bool is_run_on_device_ = false; | |||
| aclmdlDesc *model_desc_ = nullptr; | |||
| aclmdlDataset *inputs_ = nullptr; | |||
| @@ -56,12 +64,15 @@ class ModelProcess { | |||
| std::vector<AclTensorInfo> input_infos_; | |||
| std::vector<AclTensorInfo> output_infos_; | |||
| bool CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset); | |||
| bool CheckAndInitInput(const RequestBase &request); | |||
| bool BuildOutputs(ReplyBase &reply); | |||
| Status PreInitModelResource(); | |||
| Status CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset); | |||
| Status CheckAndInitInput(const RequestBase &request); | |||
| Status CheckAndInitDvppInput(const void *dvpp_outputs_buffer_dev, size_t dvpp_outputs_buffer_size, | |||
| size_t input_index); | |||
| Status BuildOutputs(ReplyBase &reply); | |||
| bool InitInputsBuffer(); | |||
| bool InitOutputsBuffer(); | |||
| Status InitInputsBuffer(); | |||
| Status InitOutputsBuffer(); | |||
| void DestroyInputsDataset(); | |||
| void DestroyInputsDataMem(); | |||
| void DestroyInputsBuffer(); | |||
| @@ -31,7 +31,6 @@ | |||
| #include "core/version_control/version_controller.h" | |||
| #include "core/util/file_system_operation.h" | |||
| #include "core/serving_tensor.h" | |||
| #include "util/status.h" | |||
| using ms_serving::MSService; | |||
| using ms_serving::PredictReply; | |||
| @@ -45,7 +44,7 @@ namespace serving { | |||
| { \ | |||
| auto time_end_##name = std::chrono::steady_clock::now(); \ | |||
| auto time_cost = std::chrono::duration<double, std::milli>(time_end_##name - time_start_##name).count(); \ | |||
| MSI_LOG_INFO << #name " Time Cost " << time_cost << "ms ---------------------"; \ | |||
| MSI_LOG_INFO << #name " Time Cost # " << time_cost << " ms ---------------------"; \ | |||
| } | |||
| Status Session::CreatDeviceSession(const std::string &device, uint32_t device_id) { | |||
| @@ -75,15 +74,26 @@ Status Session::Predict(const PredictRequest &request, PredictReply &reply) { | |||
| std::lock_guard<std::mutex> lock(mutex_); | |||
| MSI_LOG(INFO) << "run Predict"; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| if (request.images_size() > 0) { | |||
| ServingImagesRequest serving_images(request); | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| Status ret = session_->ExecuteModel(graph_id_, serving_images, serving_request, serving_reply); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG(ERROR) << "execute model with images return failed"; | |||
| return ret; | |||
| } | |||
| } else if (request.data_size() > 0) { | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| Status ret = session_->ExecuteModel(graph_id_, serving_request, serving_reply); | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG(ERROR) << "execute model with datas return failed"; | |||
| return ret; | |||
| } | |||
| } | |||
| auto ret = session_->ExecuteModel(graph_id_, serving_request, serving_reply); | |||
| MSI_LOG(INFO) << "run Predict finished"; | |||
| if (Status(ret) != SUCCESS) { | |||
| MSI_LOG(ERROR) << "execute model return failed"; | |||
| return Status(ret); | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| @@ -98,9 +108,9 @@ Status Session::Warmup(const MindSporeModelPtr model) { | |||
| MSI_TIME_STAMP_START(LoadModelFromFile) | |||
| auto ret = session_->LoadModelFromFile(file_name, graph_id_); | |||
| MSI_TIME_STAMP_END(LoadModelFromFile) | |||
| if (Status(ret) != SUCCESS) { | |||
| if (ret != SUCCESS) { | |||
| MSI_LOG(ERROR) << "Load graph model failed, file name is " << file_name.c_str(); | |||
| return Status(ret); | |||
| return ret; | |||
| } | |||
| model_loaded_ = true; | |||
| MSI_LOG(INFO) << "Session Warmup finished"; | |||
| @@ -123,14 +133,19 @@ std::promise<void> exit_requested; | |||
| void ClearEnv() { Session::Instance().Clear(); } | |||
| void HandleSignal(int sig) { exit_requested.set_value(); } | |||
| grpc::Status CreatGRPCStatus(Status status) { | |||
| switch (status) { | |||
| grpc::Status CreatGRPCStatus(const Status &status) { | |||
| switch (status.StatusCode()) { | |||
| case SUCCESS: | |||
| return grpc::Status::OK; | |||
| case FAILED: | |||
| return grpc::Status::CANCELLED; | |||
| case INVALID_INPUTS: | |||
| return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "The Predict Inputs do not match the Model Request!"); | |||
| case INVALID_INPUTS: { | |||
| auto status_msg = status.StatusMessage(); | |||
| if (status_msg.empty()) { | |||
| status_msg = "The Predict Inputs do not match the Model Request!"; | |||
| } | |||
| return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, status_msg); | |||
| } | |||
| default: | |||
| return grpc::Status::CANCELLED; | |||
| } | |||
| @@ -31,6 +31,10 @@ namespace serving { | |||
| using ms_serving::PredictReply; | |||
| using ms_serving::PredictRequest; | |||
| using inference::Status; | |||
| using inference::SUCCESS; | |||
| using inference::FAILED; | |||
| using inference::INVALID_INPUTS; | |||
| class Session { | |||
| public: | |||
| @@ -120,7 +120,7 @@ ServingRequest::ServingRequest(const ms_serving::PredictRequest &request) : requ | |||
| [](const ms_serving::Tensor &item) { return ServingTensor(const_cast<ms_serving::Tensor &>(item)); }); | |||
| } | |||
| size_t ServingRequest::size() const { return request_.data_size(); } | |||
| size_t ServingRequest::size() const { return cache_.size(); } | |||
| const InferTensorBase *ServingRequest::operator[](size_t index) const { | |||
| if (index >= cache_.size()) { | |||
| @@ -130,6 +130,22 @@ const InferTensorBase *ServingRequest::operator[](size_t index) const { | |||
| return &(cache_[index]); | |||
| } | |||
| ServingImages::ServingImages(const ms_serving::Images &images) : images_(images) {} | |||
| size_t ServingImages::batch_size() const { return images_.images_size(); } | |||
| bool ServingImages::get(size_t index, const void *&pic_buffer, uint32_t &pic_size) const { | |||
| if (index >= static_cast<size_t>(images_.images_size())) { | |||
| MSI_LOG_ERROR << "visit invalid index " << index << " total size " << images_.images_size(); | |||
| return false; | |||
| } | |||
| pic_buffer = images_.images(index).data(); | |||
| pic_size = images_.images(index).size(); | |||
| return true; | |||
| } | |||
| size_t ServingImages::input_index() const { return static_cast<size_t>(images_.input_index()); } | |||
| size_t ServingReply::size() const { return cache_.size(); } | |||
| InferTensorBase *ServingReply::operator[](size_t index) { | |||
| @@ -160,5 +176,21 @@ InferTensorBase *ServingReply::add() { | |||
| void ServingReply::clear() { reply_.mutable_result()->Clear(); } | |||
| ServingImagesRequest::ServingImagesRequest(const ms_serving::PredictRequest &request) : request_(request) { | |||
| auto &images_inputs = request_.images(); | |||
| std::transform(images_inputs.begin(), images_inputs.end(), std::back_inserter(cache_), | |||
| [](const ms_serving::Images &item) { return ServingImages(const_cast<ms_serving::Images &>(item)); }); | |||
| } | |||
| size_t ServingImagesRequest::size() const { return cache_.size(); } | |||
| const inference::InferImagesBase *ServingImagesRequest::operator[](size_t index) const { | |||
| if (index >= cache_.size()) { | |||
| MSI_LOG_ERROR << "visit invalid index " << index << " total size " << cache_.size(); | |||
| return nullptr; | |||
| } | |||
| return &(cache_[index]); | |||
| } | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -47,6 +47,18 @@ class MS_API ServingTensor : public inference::InferTensorBase { | |||
| ms_serving::Tensor &tensor_; | |||
| }; | |||
| class ServingImages : public inference::InferImagesBase { | |||
| public: | |||
| explicit ServingImages(const ms_serving::Images &images); | |||
| size_t batch_size() const override; | |||
| bool get(size_t index, const void *&pic_buffer, uint32_t &pic_size) const override; | |||
| size_t input_index() const override; | |||
| private: | |||
| const ms_serving::Images &images_; | |||
| }; | |||
| class ServingRequest : public inference::RequestBase { | |||
| public: | |||
| explicit ServingRequest(const ms_serving::PredictRequest &request); | |||
| @@ -74,6 +86,18 @@ class ServingReply : public inference::ReplyBase { | |||
| std::vector<ServingTensor> cache_; | |||
| }; | |||
| class ServingImagesRequest : public inference::ImagesRequestBase { | |||
| public: | |||
| explicit ServingImagesRequest(const ms_serving::PredictRequest &request); | |||
| size_t size() const override; | |||
| const inference::InferImagesBase *operator[](size_t index) const override; | |||
| private: | |||
| const ms_serving::PredictRequest &request_; | |||
| std::vector<ServingImages> cache_; | |||
| }; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_SERVING_TENSOR_H_ | |||
| @@ -15,10 +15,14 @@ | |||
| */ | |||
| #ifndef MINDSPORE_STATUS_H | |||
| #define MINDSPORE_STATUS_H | |||
| #include "include/inference.h" | |||
| namespace mindspore { | |||
| namespace serving { | |||
| using Status = uint32_t; | |||
| enum ServingStatus { SUCCESS = 0, FAILED, INVALID_INPUTS }; | |||
| using inference::Status; | |||
| using inference::SUCCESS; | |||
| using inference::FAILED; | |||
| using inference::INVALID_INPUTS; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -20,17 +20,19 @@ syntax = "proto3"; | |||
| package ms_serving; | |||
| service MSService { | |||
| rpc Predict(PredictRequest) returns (PredictReply) {} | |||
| rpc Test(PredictRequest) returns (PredictReply) {} | |||
| rpc Predict(PredictRequest) returns (PredictReply) {} | |||
| rpc Test(PredictRequest) returns (PredictReply) {} | |||
| } | |||
| message PredictRequest { | |||
| repeated Tensor data = 1; | |||
| repeated Tensor data = 1; | |||
| repeated Images images = 2; | |||
| } | |||
| message PredictReply { | |||
| repeated Tensor result = 1; | |||
| repeated Tensor result = 1; | |||
| } | |||
| enum DataType { | |||
| MS_UNKNOWN = 0; | |||
| MS_BOOL = 1; | |||
| @@ -62,3 +64,7 @@ message Tensor { | |||
| bytes data = 3; | |||
| } | |||
| message Images{ | |||
| repeated bytes images = 1; | |||
| uint32 input_index = 2; | |||
| } | |||
| @@ -51,6 +51,10 @@ else() | |||
| endif() | |||
| endforeach () | |||
| endif() | |||
| # removing serving ut | |||
| file(GLOB_RECURSE SERVING_ACL_UT_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} serving/*.cc) | |||
| list(REMOVE_ITEM UT_SRCS ${SERVING_ACL_UT_SRCS}) | |||
| add_subdirectory(serving) | |||
| file(GLOB_RECURSE MINDSPORE_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "../../../mindspore/core/base/*.cc" | |||
| @@ -163,7 +167,7 @@ file(GLOB_RECURSE UT_SUTB_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "stub/ge/*.cc" | |||
| ) | |||
| add_executable(ut_tests ${UT_SRCS} ${MINDSPORE_SRC_LIST} ${UT_SUTB_SRC_LIST}) | |||
| add_executable(ut_tests ${UT_SRCS} ${MINDSPORE_SRC_LIST} ${UT_SUTB_SRC_LIST} $<TARGET_OBJECTS:ut_serving_obj>) | |||
| if (ENABLE_GE) | |||
| if(ENABLE_TRAIN) | |||
| @@ -188,3 +192,14 @@ if (USE_GLOG) | |||
| endif() | |||
| target_link_libraries(ut_tests PRIVATE securec graph) | |||
| # link grpc | |||
| if (EXISTS ${grpc_ROOT}/lib64) | |||
| set(gRPC_DIR "${grpc_ROOT}/lib64/cmake/grpc") | |||
| else () | |||
| set(gRPC_DIR "${grpc_ROOT}/lib/cmake/grpc") | |||
| endif () | |||
| find_package(gRPC CONFIG REQUIRED) | |||
| target_link_libraries(ut_tests PRIVATE gRPC::grpc++) | |||
| target_link_libraries(ut_tests PRIVATE gRPC::grpc++_reflection) | |||
| target_link_libraries(ut_tests PRIVATE protobuf::libprotobuf) | |||
| @@ -0,0 +1,90 @@ | |||
| find_package(Threads REQUIRED) | |||
| # This branch assumes that gRPC and all its dependencies are already installed | |||
| # on this system, so they can be located by find_package(). | |||
| # Find Protobuf installation | |||
| # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. | |||
| #set(protobuf_MODULE_COMPATIBLE TRUE) | |||
| #find_package(Protobuf CONFIG REQUIRED) | |||
| #message(STATUS "Using protobuf ${protobuf_VERSION}") | |||
| add_library(protobuf::libprotobuf ALIAS protobuf::protobuf) | |||
| add_executable(protobuf::libprotoc ALIAS protobuf::protoc) | |||
| set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_PROTOBUF_PROTOC protoc) | |||
| else () | |||
| set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>) | |||
| endif () | |||
| # Find gRPC installation | |||
| # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. | |||
| if (EXISTS ${grpc_ROOT}/lib64) | |||
| set(gRPC_DIR "${grpc_ROOT}/lib64/cmake/grpc") | |||
| else () | |||
| set(gRPC_DIR "${grpc_ROOT}/lib/cmake/grpc") | |||
| endif () | |||
| message("serving ut using grpc_DIR : " ${gPRC_DIR}) | |||
| find_package(gRPC CONFIG REQUIRED) | |||
| message(STATUS "Using gRPC ${gRPC_VERSION}") | |||
| set(_GRPC_GRPCPP gRPC::grpc++) | |||
| set(_REFLECTION gRPC::grpc++_reflection) | |||
| if (CMAKE_CROSSCOMPILING) | |||
| find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) | |||
| find_program(_GRPC_PYTHON_PLUGIN_EXECUTABLE grpc_python_plugin) | |||
| else () | |||
| set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>) | |||
| set(_GRPC_PYTHON_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_python_plugin>) | |||
| endif () | |||
| # Proto file | |||
| get_filename_component(hw_proto "ms_service.proto" ABSOLUTE) | |||
| get_filename_component(hw_proto_path ${hw_proto} PATH) | |||
| # Generated sources | |||
| set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/ms_service.pb.cc") | |||
| set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ms_service.pb.h") | |||
| set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/ms_service.grpc.pb.cc") | |||
| set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ms_service.grpc.pb.h") | |||
| set(hw_py_pb2 "${CMAKE_CURRENT_BINARY_DIR}/ms_service_pb2.py") | |||
| set(hw_py_pb2_grpc "${CMAKE_CURRENT_BINARY_DIR}/ms_service_pb2_grpc.py") | |||
| add_custom_command( | |||
| OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" "${hw_py_pb2}" "${hw_py_pb2_grpc}" | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${hw_proto_path}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" | |||
| "${hw_proto}" | |||
| COMMAND ${_PROTOBUF_PROTOC} | |||
| ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| --python_out "${CMAKE_CURRENT_BINARY_DIR}" | |||
| -I "${hw_proto_path}" | |||
| --plugin=protoc-gen-grpc="${_GRPC_PYTHON_PLUGIN_EXECUTABLE}" | |||
| "${hw_proto}" | |||
| DEPENDS "${hw_proto}") | |||
| list(APPEND SERVING_SRC_TEST ${hw_proto_srcs} ${hw_grpc_srcs}) | |||
| file(GLOB_RECURSE ACL_SESSION_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} | |||
| "../../../../serving/acl/*.cc" | |||
| "../../../../serving/core/*.cc") | |||
| list(APPEND SERVING_SRC_TEST ${ACL_SESSION_SRC_LIST}) | |||
| # utest files | |||
| file(GLOB_RECURSE ACL_UTEST_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc") | |||
| list(APPEND SERVING_SRC_TEST ${ACL_UTEST_SRC_LIST}) | |||
| include_directories(${CMAKE_SOURCE_DIR}/serving/core) | |||
| include_directories(${CMAKE_SOURCE_DIR}/serving/acl) | |||
| include_directories(${CMAKE_SOURCE_DIR}/serving) | |||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}) | |||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | |||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}/../) | |||
| add_library(ut_serving_obj OBJECT ${SERVING_SRC_TEST}) | |||
| @@ -0,0 +1,26 @@ | |||
| /** | |||
| * Copyright 2020 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 ACL_STUB_INC_ACL_H | |||
| #define ACL_STUB_INC_ACL_H | |||
| #include "acl_base.h" | |||
| #include "acl_mdl.h" | |||
| #include "acl_rt.h" | |||
| aclError aclInit(const char *configPath); | |||
| aclError aclFinalize(); | |||
| #endif // ACL_STUB_INC_ACL_H | |||
| @@ -0,0 +1,85 @@ | |||
| /** | |||
| * Copyright 2020 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 ACL_STUB_INC_ACL_BASE | |||
| #define ACL_STUB_INC_ACL_BASE | |||
| #include <stdint.h> | |||
| #include <stddef.h> | |||
| typedef void *aclrtStream; | |||
| typedef void *aclrtEvent; | |||
| typedef void *aclrtContext; | |||
| typedef int aclError; | |||
| typedef uint16_t aclFloat16; | |||
| typedef struct aclDataBuffer aclDataBuffer; | |||
| typedef struct aclTensorDesc aclTensorDesc; | |||
| const int ACL_ERROR_NONE = 0; | |||
| typedef enum { | |||
| ACL_DT_UNDEFINED = -1, | |||
| ACL_FLOAT = 0, | |||
| ACL_FLOAT16 = 1, | |||
| ACL_INT8 = 2, | |||
| ACL_INT32 = 3, | |||
| ACL_UINT8 = 4, | |||
| ACL_INT16 = 6, | |||
| ACL_UINT16 = 7, | |||
| ACL_UINT32 = 8, | |||
| ACL_INT64 = 9, | |||
| ACL_UINT64 = 10, | |||
| ACL_DOUBLE = 11, | |||
| ACL_BOOL = 12, | |||
| } aclDataType; | |||
| typedef enum { | |||
| ACL_FORMAT_UNDEFINED = -1, | |||
| ACL_FORMAT_NCHW = 0, | |||
| ACL_FORMAT_NHWC = 1, | |||
| ACL_FORMAT_ND = 2, | |||
| ACL_FORMAT_NC1HWC0 = 3, | |||
| ACL_FORMAT_FRACTAL_Z = 4, | |||
| ACL_FORMAT_FRACTAL_NZ = 29, | |||
| } aclFormat; | |||
| typedef enum { | |||
| ACL_DEBUG, | |||
| ACL_INFO, | |||
| ACL_WARNING, | |||
| ACL_ERROR, | |||
| } aclLogLevel; | |||
| aclDataBuffer *aclCreateDataBuffer(void *data, size_t size); | |||
| aclError aclDestroyDataBuffer(const aclDataBuffer *dataBuffer); | |||
| void *aclGetDataBufferAddr(const aclDataBuffer *dataBuffer); | |||
| uint32_t aclGetDataBufferSize(const aclDataBuffer *dataBuffer); | |||
| size_t aclDataTypeSize(aclDataType dataType); | |||
| aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format); | |||
| void aclDestroyTensorDesc(const aclTensorDesc *desc); | |||
| aclDataType aclGetTensorDescType(const aclTensorDesc *desc); | |||
| aclFormat aclGetTensorDescFormat(const aclTensorDesc *desc); | |||
| size_t aclGetTensorDescSize(const aclTensorDesc *desc); | |||
| size_t aclGetTensorDescElementCount(const aclTensorDesc *desc); | |||
| size_t aclGetTensorDescNumDims(const aclTensorDesc *desc); | |||
| int64_t aclGetTensorDescDim(const aclTensorDesc *desc, size_t index); | |||
| void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, const char *fmt, ...); | |||
| #define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) | |||
| #endif | |||
| @@ -0,0 +1,75 @@ | |||
| /** | |||
| * Copyright 2020 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 ACL_STUB_INC_ACL_MDL | |||
| #define ACL_STUB_INC_ACL_MDL | |||
| #include "acl_base.h" | |||
| #define ACL_MAX_DIM_CNT 128 | |||
| #define ACL_MAX_TENSOR_NAME_LEN 128 | |||
| #define ACL_MAX_BATCH_NUM 128 | |||
| #define ACL_MAX_HW_NUM 128 | |||
| #define ACL_MAX_SHAPE_COUNT 128 | |||
| typedef struct aclmdlDataset aclmdlDataset; | |||
| typedef struct aclmdlDesc aclmdlDesc; | |||
| typedef struct aclmdlIODims { | |||
| char name[ACL_MAX_TENSOR_NAME_LEN]; | |||
| size_t dimCount; | |||
| int64_t dims[ACL_MAX_DIM_CNT]; | |||
| } aclmdlIODims; | |||
| aclmdlDesc *aclmdlCreateDesc(); | |||
| aclError aclmdlDestroyDesc(aclmdlDesc *modelDesc); | |||
| aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId); | |||
| size_t aclmdlGetNumInputs(aclmdlDesc *modelDesc); | |||
| size_t aclmdlGetNumOutputs(aclmdlDesc *modelDesc); | |||
| size_t aclmdlGetInputSizeByIndex(aclmdlDesc *modelDesc, size_t index); | |||
| size_t aclmdlGetOutputSizeByIndex(aclmdlDesc *modelDesc, size_t index); | |||
| aclmdlDataset *aclmdlCreateDataset(); | |||
| aclError aclmdlDestroyDataset(const aclmdlDataset *dataSet); | |||
| aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataSet, aclDataBuffer *dataBuffer); | |||
| size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *dataSet); | |||
| aclDataBuffer *aclmdlGetDatasetBuffer(const aclmdlDataset *dataSet, size_t index); | |||
| aclError aclmdlLoadFromFile(const char *modelPath, uint32_t *modelId); | |||
| aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); | |||
| aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, size_t workSize, | |||
| void *weightPtr, size_t weightSize); | |||
| aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, void *workPtr, | |||
| size_t workSize, void *weightPtr, size_t weightSize); | |||
| aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output); | |||
| aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, aclrtStream stream); | |||
| aclError aclmdlUnload(uint32_t modelId); | |||
| aclError aclmdlQuerySize(const char *fileName, size_t *workSize, size_t *weightSize); | |||
| aclError aclmdlQuerySizeFromMem(const void *model, size_t modelSize, size_t *workSize, size_t *weightSize); | |||
| aclError aclmdlGetInputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); | |||
| aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); | |||
| aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); | |||
| aclFormat aclmdlGetInputFormat(const aclmdlDesc *modelDesc, size_t index); | |||
| aclFormat aclmdlGetOutputFormat(const aclmdlDesc *modelDesc, size_t index); | |||
| aclDataType aclmdlGetInputDataType(const aclmdlDesc *modelDesc, size_t index); | |||
| aclDataType aclmdlGetOutputDataType(const aclmdlDesc *modelDesc, size_t index); | |||
| #endif | |||
| @@ -0,0 +1,89 @@ | |||
| /** | |||
| * Copyright 2020 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 ACL_STUB_INC_ACL_RT_H | |||
| #define ACL_STUB_INC_ACL_RT_H | |||
| #include "acl_base.h" | |||
| typedef enum aclrtRunMode { | |||
| ACL_DEVICE, | |||
| ACL_HOST, | |||
| } aclrtRunMode; | |||
| typedef enum aclrtTsId { | |||
| ACL_TS_ID_AICORE, | |||
| ACL_TS_ID_AIVECTOR, | |||
| ACL_TS_ID_RESERVED, | |||
| } aclrtTsId; | |||
| typedef enum aclrtEventStatus { | |||
| ACL_EVENT_STATUS_COMPLETE, | |||
| ACL_EVENT_STATUS_NOT_READY, | |||
| ACL_EVENT_STATUS_RESERVED, | |||
| } aclrtEventStatus; | |||
| typedef enum aclrtCallbackBlockType { | |||
| ACL_CALLBACK_NO_BLOCK, | |||
| ACL_CALLBACK_BLOCK, | |||
| } aclrtCallbackBlockType; | |||
| typedef enum aclrtMemcpyKind { | |||
| ACL_MEMCPY_HOST_TO_HOST, | |||
| ACL_MEMCPY_HOST_TO_DEVICE, | |||
| ACL_MEMCPY_DEVICE_TO_HOST, | |||
| ACL_MEMCPY_DEVICE_TO_DEVICE, | |||
| } aclrtMemcpyKind; | |||
| typedef enum aclrtMemMallocPolicy { | |||
| ACL_MEM_MALLOC_HUGE_FIRST, | |||
| ACL_MEM_MALLOC_HUGE_ONLY, | |||
| ACL_MEM_MALLOC_NORMAL_ONLY, | |||
| } aclrtMemMallocPolicy; | |||
| typedef struct rtExceptionInfo aclrtExceptionInfo; | |||
| typedef void (*aclrtCallback)(void *userData); | |||
| typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo *exceptionInfo); | |||
| aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId); | |||
| aclError aclrtDestroyContext(aclrtContext context); | |||
| aclError aclrtSetCurrentContext(aclrtContext context); | |||
| aclError aclrtGetCurrentContext(aclrtContext *context); | |||
| aclError aclrtSetDevice(int32_t deviceId); | |||
| aclError aclrtResetDevice(int32_t deviceId); | |||
| aclError aclrtGetDevice(int32_t *deviceId); | |||
| aclError aclrtGetRunMode(aclrtRunMode *runMode); | |||
| aclError aclrtSynchronizeDevice(void); | |||
| aclError aclrtSetTsDevice(aclrtTsId tsId); | |||
| aclError aclrtGetDeviceCount(uint32_t *count); | |||
| aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); | |||
| aclError aclrtFree(void *devPtr); | |||
| aclError aclrtMallocHost(void **hostPtr, size_t size); | |||
| aclError aclrtFreeHost(void *hostPtr); | |||
| aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind); | |||
| aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count); | |||
| aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind, | |||
| aclrtStream stream); | |||
| aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, aclrtStream stream); | |||
| aclError aclrtCreateStream(aclrtStream *stream); | |||
| aclError aclrtDestroyStream(aclrtStream stream); | |||
| aclError aclrtSynchronizeStream(aclrtStream stream); | |||
| aclError aclrtStreamWaitEvent(aclrtStream stream, aclrtEvent event); | |||
| #endif | |||
| @@ -0,0 +1,112 @@ | |||
| /** | |||
| * Copyright 2020 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 ACL_STUB_INC_ACL_DVPP_H | |||
| #define ACL_STUB_INC_ACL_DVPP_H | |||
| #include <stddef.h> | |||
| #include "acl/acl.h" | |||
| #include "acl/acl_base.h" | |||
| typedef struct acldvppPicDesc acldvppPicDesc; | |||
| typedef struct acldvppRoiConfig acldvppRoiConfig; | |||
| typedef struct acldvppResizeConfig acldvppResizeConfig; | |||
| typedef struct acldvppChannelDesc acldvppChannelDesc; | |||
| typedef struct acldvppStreamDesc acldvppStreamDesc; | |||
| typedef struct acldvppBatchPicDesc acldvppBatchPicDesc; | |||
| enum acldvppPixelFormat { | |||
| PIXEL_FORMAT_YUV_400 = 0, | |||
| PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // YUV | |||
| PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // YVU | |||
| PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // YUV | |||
| PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // YVU | |||
| PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // YUV | |||
| PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // YVU | |||
| }; | |||
| enum acldvppStreamFormat { | |||
| H265_MAIN_LEVEL = 0, | |||
| H254_BASELINE_LEVEL = 1, | |||
| H254_MAIN_LEVEL, | |||
| H254_HIGH_LEVEL, | |||
| }; | |||
| enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; | |||
| aclError acldvppMalloc(void **devPtr, size_t size); | |||
| aclError acldvppFree(void *devPtr); | |||
| acldvppChannelDesc *acldvppCreateChannelDesc(); | |||
| aclError acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc); | |||
| acldvppPicDesc *acldvppCreatePicDesc(); | |||
| aclError acldvppDestroyPicDesc(acldvppPicDesc *picDesc); | |||
| aclError acldvppSetPicDescSize(acldvppPicDesc *picDesc, uint32_t size); | |||
| aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format); | |||
| aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width); | |||
| aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height); | |||
| aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev); | |||
| aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride); | |||
| aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride); | |||
| aclError acldvppSetPicDescRetCode(acldvppPicDesc *picDesc, uint32_t retCode); | |||
| uint32_t acldvppGetPicDescSize(acldvppPicDesc *picDesc); | |||
| acldvppPixelFormat acldvppGetPicDescFormat(acldvppPicDesc *picDesc); | |||
| uint32_t acldvppGetPicDescWidth(acldvppPicDesc *picDesc); | |||
| uint32_t acldvppGetPicDescHeight(acldvppPicDesc *picDesc); | |||
| void *acldvppGetPicDescData(acldvppPicDesc *picDesc); | |||
| uint32_t acldvppGetPicDescWidthStride(acldvppPicDesc *picDesc); | |||
| uint32_t acldvppGetPicDescHeightStride(acldvppPicDesc *picDesc); | |||
| uint32_t acldvppGetPicDescRetCode(acldvppPicDesc *picDesc); | |||
| acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); | |||
| aclError acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig); | |||
| aclError acldvppSetRoiConfigLeft(acldvppRoiConfig *roiConfig, uint32_t left); | |||
| aclError acldvppSetRoiConfigRight(acldvppRoiConfig *roiConfig, uint32_t right); | |||
| aclError acldvppSetRoiConfigTop(acldvppRoiConfig *roiConfig, uint32_t top); | |||
| aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *roiConfig, uint32_t bottom); | |||
| aclError acldvppSetRoiConfig(acldvppRoiConfig *roiConfig, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); | |||
| acldvppResizeConfig *acldvppCreateResizeConfig(); | |||
| aclError acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig); | |||
| aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, acldvppPixelFormat ouputPixelFormat, | |||
| uint32_t *decSize); | |||
| aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc); | |||
| aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc); | |||
| aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, | |||
| acldvppResizeConfig *resizeConfig, aclrtStream stream); | |||
| aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, | |||
| acldvppRoiConfig *cropArea, aclrtStream stream); | |||
| aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, | |||
| acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, | |||
| acldvppRoiConfig *pasteArea, aclrtStream stream); | |||
| aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchDesc, uint32_t *roiNums, | |||
| uint32_t size, acldvppBatchPicDesc *dstBatchDesc, acldvppRoiConfig *cropAreas[], | |||
| aclrtStream stream); | |||
| aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, | |||
| acldvppPicDesc *outputDesc, aclrtStream stream); | |||
| acldvppBatchPicDesc *acldvppCreateBatchPicDesc(uint32_t batchSize); | |||
| acldvppPicDesc *acldvppGetPicDesc(acldvppBatchPicDesc *batchPicDesc, uint32_t index); | |||
| aclError acldvppDestroyBatchPicDesc(acldvppBatchPicDesc *batchPicDesc); | |||
| #endif // ACL_STUB_INC_ACL_DVPP_H | |||
| @@ -0,0 +1,163 @@ | |||
| /** | |||
| * Copyright 2020 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 "acl_session_test_common.h" | |||
| using namespace std; | |||
| namespace mindspore { | |||
| namespace serving { | |||
| class AclSessionAddTest : public AclSessionTest { | |||
| public: | |||
| AclSessionAddTest() = default; | |||
| void SetUp() override { | |||
| AclSessionTest::SetUp(); | |||
| aclmdlDesc model_desc; | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| mock_model_desc_ = MockModelDesc(model_desc); | |||
| g_acl_model_desc = &mock_model_desc_; | |||
| g_acl_model = &add_mock_model_; | |||
| } | |||
| void CreateDefaultRequest(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input1 = request.add_data(); | |||
| CreateTensor(*input1, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input0_data = reinterpret_cast<float *>(input0->mutable_data()->data()); | |||
| auto input1_data = reinterpret_cast<float *>(input1->mutable_data()->data()); | |||
| for (int i = 0; i < 2 * 24 * 24 * 3; i++) { | |||
| input0_data[i] = i % 1024; | |||
| input1_data[i] = i % 1024 + 1; | |||
| } | |||
| } | |||
| void CheckDefaultReply(const PredictReply &reply) { | |||
| EXPECT_TRUE(reply.result().size() == 1); | |||
| if (reply.result().size() == 1) { | |||
| CheckTensorItem(reply.result(0), {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto &output = reply.result(0).data(); | |||
| EXPECT_EQ(output.size(), 2 * 24 * 24 * 3 * sizeof(float)); | |||
| if (output.size() == 2 * 24 * 24 * 3 * sizeof(float)) { | |||
| auto output_data = reinterpret_cast<const float *>(output.data()); | |||
| for (int i = 0; i < 2 * 24 * 24 * 3; i++) { | |||
| EXPECT_EQ(output_data[i], (i % 1024) + (i % 1024 + 1)); | |||
| if (output_data[i] != (i % 1024) + (i % 1024 + 1)) { | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| MockModelDesc mock_model_desc_; | |||
| AddMockAclModel add_mock_model_; | |||
| }; | |||
| TEST_F(AclSessionAddTest, TestAclSession_OneTime_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionAddTest, TestAclSession_MutilTimes_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionAddTest, TestAclSession_DeviceRunMode_OneTime_Success) { | |||
| SetDeviceRunMode(); | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionAddTest, TestAclSession_DeviceRunMode_MutilTimes_Success) { | |||
| SetDeviceRunMode(); | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,191 @@ | |||
| /** | |||
| * Copyright 2020 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_ACL_SESSION_TEST_COMMON_H | |||
| #define MINDSPORE_ACL_SESSION_TEST_COMMON_H | |||
| #include "common/common_test.h" | |||
| #include "serving/core/server.h" | |||
| #include "include/inference.h" | |||
| #include "include/infer_tensor.h" | |||
| #include "serving/core/serving_tensor.h" | |||
| #include "serving/acl/acl_session.h" | |||
| #include "serving/acl/model_process.h" | |||
| #include "serving/acl/dvpp_process.h" | |||
| #include "acl_stub.h" | |||
| class MockDeviceRunMode : public AclRunMode { | |||
| public: | |||
| aclError aclrtGetRunMode(aclrtRunMode *runMode) override { | |||
| *runMode = aclrtRunMode::ACL_DEVICE; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| }; | |||
| class AclSessionTest : public testing::Test { | |||
| public: | |||
| AclSessionTest() = default; | |||
| void SetUp() override { | |||
| g_acl_data_buffer = &g_acl_data_buffer_default; | |||
| g_acl_env = &g_acl_env_default; | |||
| g_acl_dataset = &g_acl_dataset_default; | |||
| g_acl_model = &g_acl_model_default; | |||
| g_acl_model_desc = &g_acl_model_desc_default; | |||
| g_acl_device_context_stream = &g_acl_device_context_stream_default; | |||
| g_acl_memory = &g_acl_memory_default; | |||
| g_acl_dvpp_pic_desc = &g_acl_dvpp_pic_desc_default; | |||
| g_acl_dvpp_roi_config = &g_acl_dvpp_roi_config_default; | |||
| g_acl_dvpp_resize_config = &g_acl_dvpp_resize_config_default; | |||
| g_acl_dvpp_channel_desc = &g_acl_dvpp_channel_desc_default; | |||
| g_acl_dvpp_process = &g_acl_dvpp_process_default; | |||
| g_acl_run_mode = &acl_run_mode_default; | |||
| g_acl_jpeg_lib = &acl_jpeg_lib_default; | |||
| } | |||
| void TearDown() override { | |||
| EXPECT_TRUE(g_acl_data_buffer->Check()); | |||
| EXPECT_TRUE(g_acl_env->Check()); | |||
| EXPECT_TRUE(g_acl_dataset->Check()); | |||
| EXPECT_TRUE(g_acl_model->Check()); | |||
| EXPECT_TRUE(g_acl_model_desc->Check()); | |||
| EXPECT_TRUE(g_acl_device_context_stream->Check()); | |||
| EXPECT_TRUE(g_acl_memory->Check()); | |||
| EXPECT_TRUE(g_acl_dvpp_pic_desc->Check()); | |||
| EXPECT_TRUE(g_acl_dvpp_roi_config->Check()); | |||
| EXPECT_TRUE(g_acl_dvpp_resize_config->Check()); | |||
| EXPECT_TRUE(g_acl_dvpp_channel_desc->Check()); | |||
| EXPECT_TRUE(g_acl_dvpp_process->Check()); | |||
| EXPECT_TRUE(g_acl_jpeg_lib->Check()); | |||
| } | |||
| AclDataBuffer g_acl_data_buffer_default; | |||
| AclEnv g_acl_env_default; | |||
| AclDataSet g_acl_dataset_default; | |||
| AclModel g_acl_model_default; | |||
| AclModelDesc g_acl_model_desc_default; | |||
| AclDeviceContextStream g_acl_device_context_stream_default; | |||
| AclMemory g_acl_memory_default; | |||
| AclDvppPicDesc g_acl_dvpp_pic_desc_default; | |||
| AclDvppRoiConfig g_acl_dvpp_roi_config_default; | |||
| AclDvppResizeConfig g_acl_dvpp_resize_config_default; | |||
| AclDvppChannelDesc g_acl_dvpp_channel_desc_default; | |||
| AclDvppProcess g_acl_dvpp_process_default; | |||
| AclRunMode acl_run_mode_default; | |||
| MockDeviceRunMode acl_device_run_mode; | |||
| AclJpegLib acl_jpeg_lib_default = AclJpegLib(0, 0); | |||
| void SetDeviceRunMode() { g_acl_run_mode = &acl_device_run_mode; } | |||
| void CreateTensor(ms_serving::Tensor &tensor, const std::vector<int64_t> &shape, ms_serving::DataType data_type, | |||
| std::size_t data_size = INT64_MAX) { | |||
| if (data_size == INT64_MAX) { | |||
| data_size = GetDataTypeSize(data_type); | |||
| for (auto item : shape) { | |||
| data_size *= item; | |||
| } | |||
| } | |||
| tensor.set_data(std::string(data_size, 0)); | |||
| tensor.set_tensor_type(data_type); | |||
| auto tensor_shape = tensor.mutable_tensor_shape(); | |||
| for (auto item : shape) { | |||
| tensor_shape->add_dims(item); | |||
| } | |||
| } | |||
| size_t GetDataTypeSize(ms_serving::DataType data_type) { | |||
| const std::map<ms_serving::DataType, size_t> type_size_map{ | |||
| {ms_serving::DataType::MS_BOOL, sizeof(bool)}, {ms_serving::DataType::MS_INT8, sizeof(int8_t)}, | |||
| {ms_serving::DataType::MS_UINT8, sizeof(uint8_t)}, {ms_serving::DataType::MS_INT16, sizeof(int16_t)}, | |||
| {ms_serving::DataType::MS_UINT16, sizeof(uint16_t)}, {ms_serving::DataType::MS_INT32, sizeof(int32_t)}, | |||
| {ms_serving::DataType::MS_UINT32, sizeof(uint32_t)}, {ms_serving::DataType::MS_INT64, sizeof(int64_t)}, | |||
| {ms_serving::DataType::MS_UINT64, sizeof(uint64_t)}, {ms_serving::DataType::MS_FLOAT16, 2}, | |||
| {ms_serving::DataType::MS_FLOAT32, sizeof(float)}, {ms_serving::DataType::MS_FLOAT64, sizeof(double)}, | |||
| }; | |||
| auto it = type_size_map.find(data_type); | |||
| if (it == type_size_map.end()) { | |||
| EXPECT_TRUE(false); | |||
| return 0; | |||
| } | |||
| return it->second; | |||
| } | |||
| void CheckTensorItem(const ms_serving::Tensor &tensor, const std::vector<int64_t> &expect_shape, | |||
| ms_serving::DataType expect_data_type) { | |||
| std::vector<int64_t> tensor_shape; | |||
| for (auto item : tensor.tensor_shape().dims()) { | |||
| tensor_shape.push_back(item); | |||
| } | |||
| EXPECT_EQ(expect_shape, tensor_shape); | |||
| EXPECT_EQ(expect_data_type, tensor.tensor_type()); | |||
| int64_t elem_cnt = 1; | |||
| for (auto item : expect_shape) { | |||
| elem_cnt *= item; | |||
| } | |||
| auto data_size = GetDataTypeSize(expect_data_type); | |||
| EXPECT_EQ(data_size * elem_cnt, tensor.data().size()); | |||
| } | |||
| }; | |||
| class MockModelDesc : public AclModelDesc { | |||
| public: | |||
| MockModelDesc() {} | |||
| MockModelDesc(const aclmdlDesc &mock_model_desc) : mock_model_desc_(mock_model_desc) {} | |||
| aclmdlDesc *aclmdlCreateDesc() override { | |||
| aclmdlDesc *model_desc = AclModelDesc::aclmdlCreateDesc(); | |||
| *model_desc = mock_model_desc_; | |||
| return model_desc; | |||
| } | |||
| aclmdlDesc mock_model_desc_; | |||
| }; | |||
| class AddMockAclModel : public AclModel { | |||
| public: | |||
| aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output) override { | |||
| if (AclModel::aclmdlExecute(modelId, input, output) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (input->data_buffers.size() != 2) { | |||
| return 1; | |||
| } | |||
| auto &input0 = input->data_buffers[0]; | |||
| auto &input1 = input->data_buffers[1]; | |||
| std::size_t expect_count = input0->size / sizeof(float); | |||
| if (input0->size != expect_count * sizeof(float) || input1->size != expect_count * sizeof(float)) { | |||
| return 1; | |||
| } | |||
| if (output->data_buffers.size() != 1) { | |||
| return 1; | |||
| } | |||
| auto &output0 = output->data_buffers[0]; | |||
| if (output0->size != expect_count * sizeof(float)) { | |||
| return 1; | |||
| } | |||
| auto input0_data = reinterpret_cast<const float *>(input0->data); | |||
| auto input1_data = reinterpret_cast<const float *>(input1->data); | |||
| auto output0_data = reinterpret_cast<float *>(output0->data); | |||
| for (size_t i = 0; i < expect_count; i++) { | |||
| output0_data[i] = input0_data[i] + input1_data[i]; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, | |||
| aclrtStream stream) override { | |||
| return aclmdlExecute(modelId, input, output); | |||
| } | |||
| }; | |||
| #endif // MINDSPORE_ACL_SESSION_TEST_COMMON_H | |||
| @@ -0,0 +1,342 @@ | |||
| /** | |||
| * Copyright 2020 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 "acl_session_test_common.h" | |||
| using namespace std; | |||
| namespace mindspore { | |||
| namespace serving { | |||
| class MockFailAclDeviceContextStream : public AclDeviceContextStream { | |||
| public: | |||
| aclError aclrtSetDevice(int32_t deviceId) override { | |||
| if (set_device_fail_list_.empty()) { | |||
| return AclDeviceContextStream::aclrtSetDevice(deviceId); | |||
| } | |||
| auto val = set_device_fail_list_.front(); | |||
| set_device_fail_list_.erase(set_device_fail_list_.begin()); | |||
| if (val) { | |||
| return AclDeviceContextStream::aclrtSetDevice(deviceId); | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtResetDevice(int32_t deviceId) override { | |||
| auto ret = AclDeviceContextStream::aclrtResetDevice(deviceId); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| return ret; | |||
| } | |||
| if (reset_device_fail_list_.empty()) { | |||
| return ret; | |||
| } | |||
| auto val = reset_device_fail_list_.front(); | |||
| reset_device_fail_list_.erase(reset_device_fail_list_.begin()); | |||
| return val ? ACL_ERROR_NONE : 1; | |||
| } | |||
| aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId) override { | |||
| if (create_context_fail_list_.empty()) { | |||
| return AclDeviceContextStream::aclrtCreateContext(context, deviceId); | |||
| } | |||
| auto val = create_context_fail_list_.front(); | |||
| create_context_fail_list_.erase(create_context_fail_list_.begin()); | |||
| if (val) { | |||
| return AclDeviceContextStream::aclrtCreateContext(context, deviceId); | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtDestroyContext(aclrtContext context) override { | |||
| auto ret = AclDeviceContextStream::aclrtDestroyContext(context); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| return ret; | |||
| } | |||
| if (destroy_context_fail_list_.empty()) { | |||
| return ret; | |||
| } | |||
| auto val = destroy_context_fail_list_.front(); | |||
| destroy_context_fail_list_.erase(destroy_context_fail_list_.begin()); | |||
| return val ? ACL_ERROR_NONE : 1; | |||
| } | |||
| aclError aclrtCreateStream(aclrtStream *stream) override { | |||
| if (create_stream_fail_list_.empty()) { | |||
| return AclDeviceContextStream::aclrtCreateStream(stream); | |||
| } | |||
| auto val = create_stream_fail_list_.front(); | |||
| create_stream_fail_list_.erase(create_stream_fail_list_.begin()); | |||
| if (val) { | |||
| return AclDeviceContextStream::aclrtCreateStream(stream); | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtDestroyStream(aclrtStream stream) override { | |||
| auto ret = AclDeviceContextStream::aclrtDestroyStream(stream); | |||
| if (ret != ACL_ERROR_NONE) { | |||
| return ret; | |||
| } | |||
| if (destroy_stream_fail_list_.empty()) { | |||
| return ret; | |||
| } | |||
| auto val = destroy_stream_fail_list_.front(); | |||
| destroy_stream_fail_list_.erase(destroy_stream_fail_list_.begin()); | |||
| return val ? ACL_ERROR_NONE : 1; | |||
| } | |||
| std::vector<bool> set_device_fail_list_; | |||
| std::vector<bool> reset_device_fail_list_; | |||
| std::vector<bool> create_context_fail_list_; | |||
| std::vector<bool> destroy_context_fail_list_; | |||
| std::vector<bool> create_stream_fail_list_; | |||
| std::vector<bool> destroy_stream_fail_list_; | |||
| }; | |||
| class MockFailAclMemory : public AclMemory { | |||
| public: | |||
| aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy) override { | |||
| if (device_mem_fail_list_.empty()) { | |||
| return AclMemory::aclrtMalloc(devPtr, size, policy); | |||
| } | |||
| auto val = device_mem_fail_list_.front(); | |||
| device_mem_fail_list_.erase(device_mem_fail_list_.begin()); | |||
| if (val) { | |||
| return AclMemory::aclrtMalloc(devPtr, size, policy); | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtMallocHost(void **hostPtr, size_t size) override { | |||
| if (host_mem_fail_list_.empty()) { | |||
| return AclMemory::aclrtMallocHost(hostPtr, size); | |||
| } | |||
| auto val = host_mem_fail_list_.front(); | |||
| host_mem_fail_list_.erase(host_mem_fail_list_.begin()); | |||
| if (val) { | |||
| return AclMemory::aclrtMallocHost(hostPtr, size); | |||
| } | |||
| return 1; | |||
| } | |||
| aclError acldvppMalloc(void **devPtr, size_t size) override { | |||
| if (dvpp_mem_fail_list_.empty()) { | |||
| return AclMemory::acldvppMalloc(devPtr, size); | |||
| } | |||
| auto val = dvpp_mem_fail_list_.front(); | |||
| dvpp_mem_fail_list_.erase(dvpp_mem_fail_list_.begin()); | |||
| if (val) { | |||
| return AclMemory::acldvppMalloc(devPtr, size); | |||
| } | |||
| return 1; | |||
| } | |||
| std::vector<bool> device_mem_fail_list_; | |||
| std::vector<bool> host_mem_fail_list_; | |||
| std::vector<bool> dvpp_mem_fail_list_; | |||
| }; | |||
| class AclSessionModelLoadTest : public AclSessionTest { | |||
| public: | |||
| AclSessionModelLoadTest() = default; | |||
| void SetUp() override { | |||
| AclSessionTest::SetUp(); | |||
| aclmdlDesc model_desc; | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| mock_model_desc_ = MockModelDesc(model_desc); | |||
| g_acl_model_desc = &mock_model_desc_; | |||
| g_acl_device_context_stream = &fail_acl_device_context_stream_; | |||
| g_acl_memory = &fail_acl_memory_; | |||
| } | |||
| void CreateDefaultRequest(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input1 = request.add_data(); | |||
| CreateTensor(*input1, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| void CheckDefaultReply(const PredictReply &reply) { | |||
| EXPECT_TRUE(reply.result().size() == 2); | |||
| if (reply.result().size() == 2) { | |||
| CheckTensorItem(reply.result(0), {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| CheckTensorItem(reply.result(1), {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| } | |||
| MockModelDesc mock_model_desc_; | |||
| /* Test Resource will be release on something wrong happens*/ | |||
| MockFailAclDeviceContextStream fail_acl_device_context_stream_; | |||
| MockFailAclMemory fail_acl_memory_; | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_OneTime_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_SetDeviceFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.set_device_fail_list_.push_back(false); | |||
| EXPECT_FALSE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_CreateContextFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.create_context_fail_list_.push_back(false); | |||
| EXPECT_FALSE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_CreateStreamFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.create_stream_fail_list_.push_back(false); | |||
| EXPECT_FALSE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_ResetDeviceFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.reset_device_fail_list_.push_back(false); | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| acl_session.FinalizeEnv(); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_DestroyContextFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.destroy_context_fail_list_.push_back(false); | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| acl_session.FinalizeEnv(); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_DestroyStreamFail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| fail_acl_device_context_stream_.destroy_stream_fail_list_.push_back(false); | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| acl_session.FinalizeEnv(); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_MallocFail0_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(false); // input0 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_MallocFail1_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // input0 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(false); // input1 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_MallocFail2_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // input0 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // input1 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(false); // output0 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_MallocFail3_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // input0 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // input1 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(true); // output0 buffer | |||
| fail_acl_memory_.device_mem_fail_list_.push_back(false); // output1 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_RunOnDevice_MallocFail0_Success) { | |||
| SetDeviceRunMode(); | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.host_mem_fail_list_.push_back(false); // output0 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionModelLoadTest, TestAclSession_RunOnDevice_MallocFail1_Success) { | |||
| SetDeviceRunMode(); | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| fail_acl_memory_.host_mem_fail_list_.push_back(true); // output0 buffer | |||
| fail_acl_memory_.host_mem_fail_list_.push_back(false); // output1 buffer | |||
| EXPECT_FALSE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,138 @@ | |||
| /** | |||
| * Copyright 2020 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 "acl_session_test_common.h" | |||
| using namespace std; | |||
| namespace mindspore { | |||
| namespace serving { | |||
| class AclSessionOneInputOneOutputTest : public AclSessionTest { | |||
| public: | |||
| AclSessionOneInputOneOutputTest() = default; | |||
| void SetUp() override { | |||
| AclSessionTest::SetUp(); | |||
| aclmdlDesc model_desc; | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 8, 8, 3}, .data_type = ACL_FLOAT, .size = 2 * 8 * 8 * 3 * sizeof(float)}); | |||
| mock_model_desc_ = MockModelDesc(model_desc); | |||
| g_acl_model_desc = &mock_model_desc_; | |||
| } | |||
| void CreateDefaultRequest(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| void CreateInvalidDataSizeRequest(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| // data size invalid, not match model input required | |||
| CreateTensor(*input0, {2, 24, 24, 2}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| void CheckDefaultReply(const PredictReply &reply) { | |||
| EXPECT_TRUE(reply.result().size() == 1); | |||
| if (reply.result().size() == 1) { | |||
| CheckTensorItem(reply.result(0), {2, 8, 8, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| } | |||
| MockModelDesc mock_model_desc_; | |||
| }; | |||
| TEST_F(AclSessionOneInputOneOutputTest, TestAclSession_OneTime_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionOneInputOneOutputTest, TestAclSession_MutilTimes_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionOneInputOneOutputTest, TestAclSession_InvalidDataSize_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionOneInputOneOutputTest, TestAclSession_InvalidDataSize_MultiTimes_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,226 @@ | |||
| /** | |||
| * Copyright 2020 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 "acl_session_test_common.h" | |||
| using namespace std; | |||
| namespace mindspore { | |||
| namespace serving { | |||
| class AclSessionTwoInputTwoOutputTest : public AclSessionTest { | |||
| public: | |||
| AclSessionTwoInputTwoOutputTest() = default; | |||
| void SetUp() override { | |||
| AclSessionTest::SetUp(); | |||
| aclmdlDesc model_desc; | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 24, 24, 3}, .data_type = ACL_FLOAT, .size = 2 * 24 * 24 * 3 * sizeof(float)}); | |||
| model_desc.inputs.push_back( | |||
| AclTensorDesc{.dims = {2, 32}, .data_type = ACL_INT32, .size = 2 * 32 * sizeof(int32_t)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 8, 8, 3}, .data_type = ACL_FLOAT, .size = 2 * 8 * 8 * 3 * sizeof(float)}); | |||
| model_desc.outputs.push_back( | |||
| AclTensorDesc{.dims = {2, 1024}, .data_type = ACL_BOOL, .size = 2 * 1024 * sizeof(bool)}); | |||
| mock_model_desc_ = MockModelDesc(model_desc); | |||
| g_acl_model_desc = &mock_model_desc_; | |||
| } | |||
| void CreateDefaultRequest(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input1 = request.add_data(); | |||
| CreateTensor(*input1, {2, 32}, ::ms_serving::DataType::MS_INT32); | |||
| } | |||
| void CreateInvalidDataSizeRequest0(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| // data size invalid, not match model input required | |||
| CreateTensor(*input0, {2, 24, 24, 2}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input1 = request.add_data(); | |||
| CreateTensor(*input1, {2, 32}, ::ms_serving::DataType::MS_INT32); | |||
| } | |||
| void CreateInvalidDataSizeRequest1(PredictRequest &request) { | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| auto input1 = request.add_data(); | |||
| // data size invalid, not match model input required | |||
| CreateTensor(*input1, {2, 16}, ::ms_serving::DataType::MS_INT32); | |||
| } | |||
| void CreateInvalidDataSizeRequestOneInput0(PredictRequest &request) { | |||
| // only has one input for input0 | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 24, 24, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| } | |||
| void CreateInvalidDataSizeRequestOneInput1(PredictRequest &request) { | |||
| // only has one input for input1 | |||
| auto input0 = request.add_data(); | |||
| CreateTensor(*input0, {2, 32}, ::ms_serving::DataType::MS_INT32); | |||
| } | |||
| void CheckDefaultReply(const PredictReply &reply) { | |||
| EXPECT_TRUE(reply.result().size() == 2); | |||
| if (reply.result().size() == 2) { | |||
| CheckTensorItem(reply.result(0), {2, 8, 8, 3}, ::ms_serving::DataType::MS_FLOAT32); | |||
| CheckTensorItem(reply.result(1), {2, 1024}, ::ms_serving::DataType::MS_BOOL); | |||
| } | |||
| } | |||
| MockModelDesc mock_model_desc_; | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_OneTime_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_MutilTimes_Success) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateDefaultRequest(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_TRUE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| CheckDefaultReply(reply); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_Input0_InvalidDataSize_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequest0(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_Input1_InvalidDataSize_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequest1(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_OnlyInput0_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequestOneInput0(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_OnlyInput1_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequestOneInput1(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| TEST_F(AclSessionTwoInputTwoOutputTest, TestAclSession_InvalidDataSize_MultiTimes_Fail) { | |||
| inference::AclSession acl_session; | |||
| uint32_t device_id = 1; | |||
| EXPECT_TRUE(acl_session.InitEnv("Ascend", device_id) == SUCCESS); | |||
| uint32_t model_id = 0; | |||
| EXPECT_TRUE(acl_session.LoadModelFromFile("fake_model_path", model_id) == SUCCESS); | |||
| for (int i = 0; i < 10; i++) { | |||
| // create inputs | |||
| PredictRequest request; | |||
| CreateInvalidDataSizeRequest0(request); | |||
| PredictReply reply; | |||
| ServingRequest serving_request(request); | |||
| ServingReply serving_reply(reply); | |||
| EXPECT_FALSE(acl_session.ExecuteModel(model_id, serving_request, serving_reply) == SUCCESS); | |||
| } | |||
| EXPECT_TRUE(acl_session.UnloadModel(model_id) == SUCCESS); | |||
| EXPECT_TRUE(acl_session.FinalizeEnv() == SUCCESS); | |||
| }; | |||
| } // namespace serving | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,323 @@ | |||
| /** | |||
| * Copyright 2020 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 "acl_stub.h" | |||
| #include <iostream> | |||
| AclDataBuffer *g_acl_data_buffer = nullptr; | |||
| AclEnv *g_acl_env = nullptr; | |||
| AclDataSet *g_acl_dataset = nullptr; | |||
| AclModel *g_acl_model = nullptr; | |||
| AclModelDesc *g_acl_model_desc = nullptr; | |||
| AclDeviceContextStream *g_acl_device_context_stream = nullptr; | |||
| AclMemory *g_acl_memory = nullptr; | |||
| AclDvppPicDesc *g_acl_dvpp_pic_desc = nullptr; | |||
| AclDvppRoiConfig *g_acl_dvpp_roi_config = nullptr; | |||
| AclDvppResizeConfig *g_acl_dvpp_resize_config = nullptr; | |||
| AclDvppChannelDesc *g_acl_dvpp_channel_desc = nullptr; | |||
| AclDvppProcess *g_acl_dvpp_process = nullptr; | |||
| AclRunMode *g_acl_run_mode = nullptr; | |||
| AclJpegLib *g_acl_jpeg_lib = nullptr; | |||
| aclDataBuffer *aclCreateDataBuffer(void *data, size_t size) { | |||
| return g_acl_data_buffer->aclCreateDataBuffer(data, size); | |||
| } | |||
| aclError aclDestroyDataBuffer(const aclDataBuffer *dataBuffer) { | |||
| return g_acl_data_buffer->aclDestroyDataBuffer(dataBuffer); | |||
| } | |||
| void *aclGetDataBufferAddr(const aclDataBuffer *dataBuffer) { | |||
| return g_acl_data_buffer->aclGetDataBufferAddr(dataBuffer); | |||
| } | |||
| uint32_t aclGetDataBufferSize(const aclDataBuffer *dataBuffer) { | |||
| return g_acl_data_buffer->aclGetDataBufferSize(dataBuffer); | |||
| } | |||
| size_t aclDataTypeSize(aclDataType dataType) { | |||
| std::unordered_map<aclDataType, size_t> dataTypeMap = { | |||
| {ACL_FLOAT16, 2}, {ACL_FLOAT, 4}, {ACL_DOUBLE, 8}, {ACL_INT8, 1}, {ACL_INT16, 2}, {ACL_INT32, 4}, | |||
| {ACL_INT64, 8}, {ACL_UINT8, 1}, {ACL_UINT16, 2}, {ACL_UINT32, 4}, {ACL_UINT64, 8}, {ACL_BOOL, 1}, | |||
| }; | |||
| auto it = dataTypeMap.find(dataType); | |||
| if (it == dataTypeMap.end()) { | |||
| return 0; | |||
| } else { | |||
| return it->second; | |||
| } | |||
| } | |||
| void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, const char *fmt, ...) { | |||
| if (logLevel == ACL_ERROR) { | |||
| // std::cout << file << ":" << line << "," << func << ": " << fmt << std::endl; | |||
| } | |||
| } | |||
| aclError aclInit(const char *configPath) { return g_acl_env->aclInit(configPath); } | |||
| aclError aclFinalize() { return g_acl_env->aclFinalize(); } | |||
| // dataset | |||
| aclmdlDataset *aclmdlCreateDataset() { return g_acl_dataset->aclmdlCreateDataset(); } | |||
| aclError aclmdlDestroyDataset(const aclmdlDataset *dataSet) { return g_acl_dataset->aclmdlDestroyDataset(dataSet); } | |||
| aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataSet, aclDataBuffer *dataBuffer) { | |||
| return g_acl_dataset->aclmdlAddDatasetBuffer(dataSet, dataBuffer); | |||
| } | |||
| size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *dataSet) { | |||
| return g_acl_dataset->aclmdlGetDatasetNumBuffers(dataSet); | |||
| } | |||
| aclDataBuffer *aclmdlGetDatasetBuffer(const aclmdlDataset *dataSet, size_t index) { | |||
| return g_acl_dataset->aclmdlGetDatasetBuffer(dataSet, index); | |||
| } | |||
| // model | |||
| aclError aclmdlLoadFromFile(const char *modelPath, uint32_t *modelId) { | |||
| return g_acl_model->aclmdlLoadFromFile(modelPath, modelId); | |||
| } | |||
| aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId) { | |||
| return g_acl_model->aclmdlLoadFromMem(model, modelSize, modelId); | |||
| } | |||
| aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, size_t workSize, | |||
| void *weightPtr, size_t weightSize) { | |||
| return g_acl_model->aclmdlLoadFromFileWithMem(modelPath, modelId, workPtr, workSize, weightPtr, weightSize); | |||
| } | |||
| aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, void *workPtr, | |||
| size_t workSize, void *weightPtr, size_t weightSize) { | |||
| return g_acl_model->aclmdlLoadFromMemWithMem(model, modelSize, modelId, workPtr, workSize, weightPtr, weightSize); | |||
| } | |||
| aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output) { | |||
| return g_acl_model->aclmdlExecute(modelId, input, output); | |||
| } | |||
| aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, aclrtStream stream) { | |||
| return g_acl_model->aclmdlExecuteAsync(modelId, input, output, stream); | |||
| } | |||
| aclError aclmdlUnload(uint32_t modelId) { return g_acl_model->aclmdlUnload(modelId); } | |||
| // model desc | |||
| aclmdlDesc *aclmdlCreateDesc() { return g_acl_model_desc->aclmdlCreateDesc(); } | |||
| aclError aclmdlDestroyDesc(aclmdlDesc *modelDesc) { return g_acl_model_desc->aclmdlDestroyDesc(modelDesc); } | |||
| aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId) { | |||
| return g_acl_model_desc->aclmdlGetDesc(modelDesc, modelId); | |||
| } | |||
| size_t aclmdlGetNumInputs(aclmdlDesc *modelDesc) { return g_acl_model_desc->aclmdlGetNumInputs(modelDesc); } | |||
| size_t aclmdlGetNumOutputs(aclmdlDesc *modelDesc) { return g_acl_model_desc->aclmdlGetNumOutputs(modelDesc); } | |||
| size_t aclmdlGetInputSizeByIndex(aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetInputSizeByIndex(modelDesc, index); | |||
| } | |||
| size_t aclmdlGetOutputSizeByIndex(aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetOutputSizeByIndex(modelDesc, index); | |||
| } | |||
| aclError aclmdlGetInputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| return g_acl_model_desc->aclmdlGetInputDims(modelDesc, index, dims); | |||
| } | |||
| aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| return g_acl_model_desc->aclmdlGetOutputDims(modelDesc, index, dims); | |||
| } | |||
| aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| return g_acl_model_desc->aclmdlGetCurOutputDims(modelDesc, index, dims); | |||
| } | |||
| aclFormat aclmdlGetInputFormat(const aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetInputFormat(modelDesc, index); | |||
| } | |||
| aclFormat aclmdlGetOutputFormat(const aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetOutputFormat(modelDesc, index); | |||
| } | |||
| aclDataType aclmdlGetInputDataType(const aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetInputDataType(modelDesc, index); | |||
| } | |||
| aclDataType aclmdlGetOutputDataType(const aclmdlDesc *modelDesc, size_t index) { | |||
| return g_acl_model_desc->aclmdlGetOutputDataType(modelDesc, index); | |||
| } | |||
| // device, context, stream | |||
| aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId) { | |||
| return g_acl_device_context_stream->aclrtCreateContext(context, deviceId); | |||
| } | |||
| aclError aclrtDestroyContext(aclrtContext context) { return g_acl_device_context_stream->aclrtDestroyContext(context); } | |||
| aclError aclrtSetCurrentContext(aclrtContext context) { | |||
| return g_acl_device_context_stream->aclrtSetCurrentContext(context); | |||
| } | |||
| aclError aclrtSetDevice(int32_t deviceId) { return g_acl_device_context_stream->aclrtSetDevice(deviceId); } | |||
| aclError aclrtResetDevice(int32_t deviceId) { return g_acl_device_context_stream->aclrtResetDevice(deviceId); } | |||
| aclError aclrtGetRunMode(aclrtRunMode *runMode) { return g_acl_run_mode->aclrtGetRunMode(runMode); } | |||
| aclError aclrtCreateStream(aclrtStream *stream) { return g_acl_device_context_stream->aclrtCreateStream(stream); } | |||
| aclError aclrtDestroyStream(aclrtStream stream) { return g_acl_device_context_stream->aclrtDestroyStream(stream); } | |||
| aclError aclrtSynchronizeStream(aclrtStream stream) { | |||
| return g_acl_device_context_stream->aclrtSynchronizeStream(stream); | |||
| } | |||
| // memory | |||
| aclError acldvppMalloc(void **devPtr, size_t size) { return g_acl_memory->acldvppMalloc(devPtr, size); } | |||
| aclError acldvppFree(void *devPtr) { return g_acl_memory->acldvppFree(devPtr); } | |||
| aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy) { | |||
| return g_acl_memory->aclrtMalloc(devPtr, size, policy); | |||
| } | |||
| aclError aclrtFree(void *devPtr) { return g_acl_memory->aclrtFree(devPtr); } | |||
| aclError aclrtMallocHost(void **hostPtr, size_t size) { return g_acl_memory->aclrtMallocHost(hostPtr, size); } | |||
| aclError aclrtFreeHost(void *hostPtr) { return g_acl_memory->aclrtFreeHost(hostPtr); } | |||
| aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind) { | |||
| return g_acl_memory->aclrtMemcpy(dst, destMax, src, count, kind); | |||
| } | |||
| acldvppPicDesc *acldvppCreatePicDesc() { return g_acl_dvpp_pic_desc->acldvppCreatePicDesc(); } | |||
| aclError acldvppDestroyPicDesc(acldvppPicDesc *picDesc) { return g_acl_dvpp_pic_desc->acldvppDestroyPicDesc(picDesc); } | |||
| aclError acldvppSetPicDescSize(acldvppPicDesc *picDesc, uint32_t size) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescSize(picDesc, size); | |||
| } | |||
| aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescFormat(picDesc, format); | |||
| } | |||
| aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescWidth(picDesc, width); | |||
| } | |||
| aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescHeight(picDesc, height); | |||
| } | |||
| aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescData(picDesc, dataDev); | |||
| } | |||
| aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescWidthStride(picDesc, widthStride); | |||
| } | |||
| aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride) { | |||
| return g_acl_dvpp_pic_desc->acldvppSetPicDescHeightStride(picDesc, heightStride); | |||
| } | |||
| acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) { | |||
| return g_acl_dvpp_roi_config->acldvppCreateRoiConfig(left, right, top, bottom); | |||
| } | |||
| aclError acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig) { | |||
| return g_acl_dvpp_roi_config->acldvppDestroyRoiConfig(roiConfig); | |||
| } | |||
| aclError acldvppSetRoiConfig(acldvppRoiConfig *roiConfig, uint32_t left, uint32_t right, uint32_t top, | |||
| uint32_t bottom) { | |||
| return g_acl_dvpp_roi_config->acldvppSetRoiConfig(roiConfig, left, right, top, bottom); | |||
| } | |||
| acldvppResizeConfig *acldvppCreateResizeConfig() { return g_acl_dvpp_resize_config->acldvppCreateResizeConfig(); } | |||
| aclError acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig) { | |||
| return g_acl_dvpp_resize_config->acldvppDestroyResizeConfig(resizeConfig); | |||
| } | |||
| aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc) { | |||
| return g_acl_dvpp_channel_desc->acldvppCreateChannel(channelDesc); | |||
| } | |||
| aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc) { | |||
| return g_acl_dvpp_channel_desc->acldvppDestroyChannel(channelDesc); | |||
| } | |||
| acldvppChannelDesc *acldvppCreateChannelDesc() { return g_acl_dvpp_channel_desc->acldvppCreateChannelDesc(); } | |||
| aclError acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc) { | |||
| return g_acl_dvpp_channel_desc->acldvppDestroyChannelDesc(channelDesc); | |||
| } | |||
| aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, | |||
| acldvppResizeConfig *resizeConfig, aclrtStream stream) { | |||
| return g_acl_dvpp_process->acldvppVpcResizeAsync(channelDesc, inputDesc, outputDesc, resizeConfig, stream); | |||
| } | |||
| aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, | |||
| acldvppRoiConfig *cropArea, aclrtStream stream) { | |||
| return g_acl_dvpp_process->acldvppVpcCropAsync(channelDesc, inputDesc, outputDesc, cropArea, stream); | |||
| } | |||
| aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, | |||
| acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, | |||
| acldvppRoiConfig *pasteArea, aclrtStream stream) { | |||
| return g_acl_dvpp_process->acldvppVpcCropAndPasteAsync(channelDesc, inputDesc, outputDesc, cropArea, pasteArea, | |||
| stream); | |||
| } | |||
| aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchDesc, uint32_t *roiNums, | |||
| uint32_t size, acldvppBatchPicDesc *dstBatchDesc, acldvppRoiConfig *cropAreas[], | |||
| aclrtStream stream) { | |||
| return g_acl_dvpp_process->acldvppVpcBatchCropAsync(channelDesc, srcBatchDesc, roiNums, size, dstBatchDesc, cropAreas, | |||
| stream); | |||
| } | |||
| aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, | |||
| acldvppPicDesc *outputDesc, aclrtStream stream) { | |||
| return g_acl_dvpp_process->acldvppJpegDecodeAsync(channelDesc, data, size, outputDesc, stream); | |||
| } | |||
| // jpeg lib | |||
| void jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize) { | |||
| g_acl_jpeg_lib->jpeg_CreateDecompress(cinfo, version, structsize); | |||
| } | |||
| void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, unsigned long insize) { | |||
| g_acl_jpeg_lib->jpeg_mem_src(cinfo, inbuffer, insize); | |||
| } | |||
| int jpeg_read_header(j_decompress_ptr cinfo, boolean require_image) { | |||
| return g_acl_jpeg_lib->jpeg_read_header(cinfo, require_image); | |||
| } | |||
| void jpeg_destroy_decompress(j_decompress_ptr cinfo) { g_acl_jpeg_lib->jpeg_destroy_decompress(cinfo); } | |||
| struct jpeg_error_mgr *jpeg_std_error(struct jpeg_error_mgr *err) { | |||
| return err; | |||
| } | |||
| @@ -0,0 +1,857 @@ | |||
| /** | |||
| * Copyright 2020 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_ACL_STUB_H | |||
| #define MINDSPORE_ACL_STUB_H | |||
| #include "acl/acl_base.h" | |||
| #include "acl/acl.h" | |||
| #include "acl/acl_mdl.h" | |||
| #include "acl/acl_rt.h" | |||
| #include "acl/ops/acl_dvpp.h" | |||
| #include <algorithm> | |||
| #include <vector> | |||
| #include <string> | |||
| #include <unordered_map> | |||
| #include <map> | |||
| #include <functional> | |||
| #include <cstring> | |||
| #include "jpeglib.h" | |||
| struct aclDataBuffer { | |||
| void *data = nullptr; | |||
| size_t size = 0; | |||
| }; | |||
| struct aclmdlDataset { | |||
| std::vector<aclDataBuffer *> data_buffers; | |||
| }; | |||
| struct aclTensorDesc {}; | |||
| struct AclTensorDesc { | |||
| std::vector<int64_t> dims; | |||
| aclDataType data_type = ACL_DT_UNDEFINED; | |||
| size_t size = 0; | |||
| }; | |||
| struct aclmdlDesc { | |||
| std::vector<AclTensorDesc> inputs; | |||
| std::vector<AclTensorDesc> outputs; | |||
| }; | |||
| struct acldvppPicDesc { | |||
| uint32_t size = 0; | |||
| acldvppPixelFormat format = PIXEL_FORMAT_YUV_400; | |||
| uint32_t width = 0; | |||
| uint32_t height = 0; | |||
| void *dataDev = nullptr; | |||
| uint32_t widthStride = 0; | |||
| uint32_t heightStride = 0; | |||
| }; | |||
| struct acldvppRoiConfig { | |||
| uint32_t left = 0; | |||
| uint32_t right = 0; | |||
| uint32_t top = 0; | |||
| uint32_t bottom = 0; | |||
| }; | |||
| struct acldvppResizeConfig { | |||
| uint32_t id; | |||
| }; | |||
| struct acldvppChannelDesc { | |||
| bool channel_valid_flag = false; | |||
| }; | |||
| class AclModel; | |||
| extern AclModel *g_acl_model; | |||
| template <class Type> | |||
| aclError AclItemOnDestroy( | |||
| std::vector<Type> &live, std::vector<Type> &destroy, const Type *destroy_item, | |||
| std::function<void(Type &list_item)> func_release = [](Type &list_item) {}) { | |||
| for (auto it = live.begin(); it != live.end(); it++) { | |||
| if (&(*it) == destroy_item) { | |||
| func_release(*it); | |||
| destroy.push_back(*it); | |||
| live.erase(it); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| } | |||
| return 1; | |||
| } | |||
| template <class PtType, typename std::enable_if<std::is_pointer<PtType>::value, int>::type = 0> | |||
| class ResourceBase { | |||
| public: | |||
| using Type = typename std::remove_pointer<PtType>::type; | |||
| ResourceBase() = default; | |||
| virtual ~ResourceBase() { Clear(); } | |||
| void Clear() { | |||
| for (auto item : resource_live_) { | |||
| delete item; | |||
| } | |||
| resource_live_.clear(); | |||
| resource_destroy_.clear(); | |||
| } | |||
| template <class... Args> | |||
| Type *OnCreate(Args &&... args) { | |||
| auto item = new Type(std::forward<Args>(args)...); | |||
| resource_live_.push_back(item); | |||
| return item; | |||
| } | |||
| aclError OnDestroy( | |||
| const Type *item, std::function<void(Type &list_item)> func_release = [](Type &list_item) {}) { | |||
| auto it = std::find(resource_live_.begin(), resource_live_.end(), item); | |||
| if (it == resource_live_.end()) { | |||
| return 1; | |||
| } | |||
| func_release(**it); // Type& | |||
| resource_destroy_.push_back(*it); // Type* | |||
| resource_live_.erase(it); | |||
| delete item; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| size_t LiveSize() const { return resource_live_.size(); } | |||
| bool Check() const { return resource_live_.empty(); } | |||
| std::vector<Type *> resource_live_; | |||
| std::vector<Type *> resource_destroy_; | |||
| }; | |||
| class AclDataBuffer { | |||
| public: | |||
| AclDataBuffer() {} | |||
| virtual ~AclDataBuffer() { Clear(); } | |||
| virtual void Clear() { data_buffer_.Clear(); } | |||
| bool Check() { return data_buffer_.Check(); } | |||
| virtual aclDataBuffer *aclCreateDataBuffer(void *data, size_t size) { | |||
| aclDataBuffer data_buffer; | |||
| data_buffer.data = data; | |||
| data_buffer.size = size; | |||
| return data_buffer_.OnCreate(data_buffer); | |||
| } | |||
| virtual aclError aclDestroyDataBuffer(const aclDataBuffer *dataBuffer) { return data_buffer_.OnDestroy(dataBuffer); } | |||
| virtual void *aclGetDataBufferAddr(const aclDataBuffer *dataBuffer) { | |||
| if (dataBuffer == nullptr) { | |||
| return nullptr; | |||
| } | |||
| return dataBuffer->data; | |||
| } | |||
| virtual uint32_t aclGetDataBufferSize(const aclDataBuffer *dataBuffer) { | |||
| if (dataBuffer == nullptr) { | |||
| return 0; | |||
| } | |||
| return dataBuffer->size; | |||
| } | |||
| ResourceBase<aclDataBuffer *> data_buffer_; | |||
| }; | |||
| class AclDataSet { | |||
| public: | |||
| AclDataSet() {} | |||
| virtual ~AclDataSet() { Clear(); } | |||
| virtual void Clear() { dataset_.Clear(); } | |||
| bool Check() { return dataset_.Check(); } | |||
| public: | |||
| virtual aclmdlDataset *aclmdlCreateDataset() { return dataset_.OnCreate(); } | |||
| virtual aclError aclmdlDestroyDataset(const aclmdlDataset *dataSet) { return dataset_.OnDestroy(dataSet); } | |||
| virtual aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataSet, aclDataBuffer *dataBuffer) { | |||
| if (dataSet == nullptr) { | |||
| return 1; | |||
| } | |||
| dataSet->data_buffers.push_back(dataBuffer); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *dataSet) { | |||
| if (dataSet == nullptr) { | |||
| return 0; | |||
| } | |||
| return dataSet->data_buffers.size(); | |||
| } | |||
| virtual aclDataBuffer *aclmdlGetDatasetBuffer(const aclmdlDataset *dataSet, size_t index) { | |||
| if (dataSet == nullptr || index >= dataSet->data_buffers.size()) { | |||
| return nullptr; | |||
| } | |||
| return dataSet->data_buffers[index]; | |||
| } | |||
| ResourceBase<aclmdlDataset *> dataset_; | |||
| }; | |||
| class AclEnv { | |||
| public: | |||
| virtual aclError aclInit(const char *configPath) { | |||
| is_init = true; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclFinalize() { | |||
| is_init = false; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| bool Check() { return is_init == false; } | |||
| bool is_init = false; | |||
| }; | |||
| class AclModel { | |||
| public: | |||
| bool Check() { return model_live_.empty(); } | |||
| virtual aclError aclmdlLoadFromFile(const char *modelPath, uint32_t *modelId) { | |||
| model_live_.push_back(cur_max_model_id_); | |||
| *modelId = cur_max_model_id_; | |||
| cur_max_model_id_++; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId) { | |||
| return aclmdlLoadFromFile("fake_path", modelId); | |||
| } | |||
| virtual aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, size_t workSize, | |||
| void *weightPtr, size_t weightSize) { | |||
| return aclmdlLoadFromFile(modelPath, modelId); | |||
| } | |||
| virtual aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, void *workPtr, | |||
| size_t workSize, void *weightPtr, size_t weightSize) { | |||
| return aclmdlLoadFromMem(model, modelSize, modelId); | |||
| } | |||
| virtual aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output) { | |||
| if (std::find(model_live_.begin(), model_live_.end(), modelId) == model_live_.end()) { | |||
| return 1; | |||
| } | |||
| if (input == nullptr || output == nullptr) { | |||
| return false; | |||
| } | |||
| // auto& model_desc = model_live_[modelId]; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, | |||
| aclrtStream stream) { | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclmdlUnload(uint32_t modelId) { | |||
| auto it = std::find(model_live_.begin(), model_live_.end(), modelId); | |||
| if (it == model_live_.end()) { | |||
| return 1; | |||
| } | |||
| model_live_.erase(it); | |||
| model_destroy_.push_back(modelId); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| uint32_t cur_max_model_id_ = 0; | |||
| std::vector<uint32_t> model_live_; | |||
| std::vector<uint32_t> model_destroy_; | |||
| }; | |||
| class AclModelDesc { | |||
| public: | |||
| AclModelDesc() {} | |||
| virtual ~AclModelDesc() { Clear(); } | |||
| virtual void Clear() { model_desc_.Clear(); } | |||
| bool Check() { return model_desc_.Check(); } | |||
| public: | |||
| virtual aclmdlDesc *aclmdlCreateDesc() { return model_desc_.OnCreate(); } | |||
| aclError aclmdlDestroyDesc(aclmdlDesc *modelDesc) { return model_desc_.OnDestroy(modelDesc); } | |||
| aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId) { | |||
| auto &model_live = g_acl_model->model_live_; | |||
| auto it = std::find(model_live.begin(), model_live.end(), modelId); | |||
| if (it == model_live.end()) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| size_t aclmdlGetNumInputs(aclmdlDesc *modelDesc) { return modelDesc->inputs.size(); } | |||
| size_t aclmdlGetNumOutputs(aclmdlDesc *modelDesc) { return modelDesc->outputs.size(); } | |||
| size_t aclmdlGetInputSizeByIndex(aclmdlDesc *modelDesc, size_t index) { return modelDesc->inputs[index].size; } | |||
| size_t aclmdlGetOutputSizeByIndex(aclmdlDesc *modelDesc, size_t index) { return modelDesc->outputs[index].size; } | |||
| aclError aclmdlGetInputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| auto &input = modelDesc->inputs[index]; | |||
| dims->dimCount = input.dims.size(); | |||
| for (size_t i = 0; i < dims->dimCount; i++) { | |||
| dims->dims[i] = input.dims[i]; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| auto &input = modelDesc->outputs[index]; | |||
| dims->dimCount = input.dims.size(); | |||
| for (size_t i = 0; i < dims->dimCount; i++) { | |||
| dims->dims[i] = input.dims[i]; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims) { | |||
| return aclmdlGetOutputDims(modelDesc, index, dims); | |||
| } | |||
| aclFormat aclmdlGetInputFormat(const aclmdlDesc *modelDesc, size_t index) { return ACL_FORMAT_NCHW; } | |||
| aclFormat aclmdlGetOutputFormat(const aclmdlDesc *modelDesc, size_t index) { return ACL_FORMAT_NCHW; } | |||
| aclDataType aclmdlGetInputDataType(const aclmdlDesc *modelDesc, size_t index) { | |||
| return modelDesc->inputs[index].data_type; | |||
| } | |||
| aclDataType aclmdlGetOutputDataType(const aclmdlDesc *modelDesc, size_t index) { | |||
| return modelDesc->outputs[index].data_type; | |||
| } | |||
| ResourceBase<aclmdlDesc *> model_desc_; | |||
| }; | |||
| class AclRunMode { | |||
| public: | |||
| virtual aclError aclrtGetRunMode(aclrtRunMode *runMode) { | |||
| *runMode = aclrtRunMode::ACL_HOST; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| }; | |||
| class AclDeviceContextStream { | |||
| public: | |||
| AclDeviceContextStream() {} | |||
| ~AclDeviceContextStream() { Clear(); } | |||
| virtual void Clear() { | |||
| for (auto context : context_live_) { | |||
| delete (int *)context; | |||
| } | |||
| context_live_.clear(); | |||
| context_destroy_.clear(); | |||
| device_id_live_.clear(); | |||
| device_id_destroy_.clear(); | |||
| for (auto item : stream_live_) { | |||
| delete (int *)item; | |||
| } | |||
| stream_live_.clear(); | |||
| stream_destroy_.clear(); | |||
| } | |||
| bool Check() { return context_live_.empty() && device_id_live_.empty() && stream_live_.empty(); } | |||
| virtual aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId) { | |||
| context_live_.push_back(new int()); | |||
| *context = context_live_.back(); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclrtDestroyContext(aclrtContext context) { | |||
| for (auto it = context_live_.begin(); it != context_live_.end(); ++it) { | |||
| if (*it == context) { | |||
| context_live_.erase(it); | |||
| context_destroy_.push_back(context); | |||
| delete (int *)context; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtSetCurrentContext(aclrtContext context) { return ACL_ERROR_NONE; } | |||
| aclError aclrtGetCurrentContext(aclrtContext *context) { return ACL_ERROR_NONE; } | |||
| virtual aclError aclrtSetDevice(int32_t deviceId) { | |||
| device_id_live_.push_back(deviceId); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclrtResetDevice(int32_t deviceId) { | |||
| for (auto it = device_id_live_.begin(); it != device_id_live_.end(); ++it) { | |||
| if (*it == deviceId) { | |||
| device_id_live_.erase(it); | |||
| device_id_destroy_.push_back(deviceId); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtGetDevice(int32_t *deviceId) { | |||
| *deviceId = 0; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclrtSynchronizeDevice(void) { return ACL_ERROR_NONE; } | |||
| aclError aclrtSetTsDevice(aclrtTsId tsId) { return ACL_ERROR_NONE; } | |||
| aclError aclrtGetDeviceCount(uint32_t *count) { | |||
| *count = 1; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclrtCreateStream(aclrtStream *stream) { | |||
| stream_live_.push_back(new int()); | |||
| *stream = stream_live_.back(); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError aclrtDestroyStream(aclrtStream stream) { | |||
| for (auto it = stream_live_.begin(); it != context_live_.end(); ++it) { | |||
| if (*it == stream) { | |||
| stream_live_.erase(it); | |||
| stream_destroy_.push_back(stream); | |||
| delete (int *)stream; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtSynchronizeStream(aclrtStream stream) { | |||
| for (auto it = stream_live_.begin(); it != context_live_.end(); ++it) { | |||
| if (*it == stream) { | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| } | |||
| return 1; | |||
| } | |||
| std::vector<int32_t> device_id_live_; | |||
| std::vector<int32_t> device_id_destroy_; | |||
| std::vector<aclrtContext> context_live_; | |||
| std::vector<aclrtContext> context_destroy_; | |||
| std::vector<aclrtStream> stream_live_; | |||
| std::vector<aclrtStream> stream_destroy_; | |||
| }; | |||
| class AclMemory { | |||
| public: | |||
| AclMemory() {} | |||
| ~AclMemory() { Clear(); } | |||
| void Clear() { | |||
| for (auto item : device_buffer_live_) { | |||
| delete[] item; | |||
| } | |||
| for (auto item : host_buffer_live_) { | |||
| delete[] item; | |||
| } | |||
| for (auto item : dvpp_buffer_live_) { | |||
| delete[] item; | |||
| } | |||
| device_buffer_live_.clear(); | |||
| device_buffer_destroy_.clear(); | |||
| host_buffer_live_.clear(); | |||
| host_buffer_destroy_.clear(); | |||
| dvpp_buffer_live_.clear(); | |||
| dvpp_buffer_destroy_.clear(); | |||
| } | |||
| bool Check() { return device_buffer_live_.empty() && host_buffer_live_.empty() && dvpp_buffer_live_.empty(); } | |||
| virtual aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy) { | |||
| auto buffer = new uint8_t[size]; | |||
| *devPtr = buffer; | |||
| device_buffer_live_.push_back(buffer); | |||
| memory_len_[buffer] = size; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclrtFree(void *devPtr) { | |||
| auto it = std::find(device_buffer_live_.begin(), device_buffer_live_.end(), devPtr); | |||
| if (it != device_buffer_live_.end()) { | |||
| delete[](*it); | |||
| device_buffer_live_.erase(it); | |||
| device_buffer_destroy_.push_back(*it); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| return 1; | |||
| } | |||
| virtual aclError aclrtMallocHost(void **hostPtr, size_t size) { | |||
| auto buffer = new uint8_t[size]; | |||
| *hostPtr = buffer; | |||
| host_buffer_live_.push_back(buffer); | |||
| memory_len_[buffer] = size; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError aclrtFreeHost(void *hostPtr) { | |||
| auto it = std::find(host_buffer_live_.begin(), host_buffer_live_.end(), hostPtr); | |||
| if (it != host_buffer_live_.end()) { | |||
| delete[](*it); | |||
| host_buffer_live_.erase(it); | |||
| host_buffer_destroy_.push_back(*it); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| return 1; | |||
| } | |||
| aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind) { | |||
| auto is_device_memory = [this](const void *memory, uint32_t use_size) { | |||
| for (auto it = device_buffer_live_.begin(); it != device_buffer_live_.end(); it++) { | |||
| auto size = memory_len_[*it]; | |||
| if (memory >= *it && static_cast<const uint8_t *>(memory) + use_size <= (*it) + size) { | |||
| return true; | |||
| } | |||
| } | |||
| for (auto it = dvpp_buffer_live_.begin(); it != dvpp_buffer_live_.end(); it++) { | |||
| auto size = memory_len_[*it]; | |||
| if (memory >= *it && static_cast<const uint8_t *>(memory) + use_size <= (*it) + size) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| }; | |||
| if (kind == ACL_MEMCPY_HOST_TO_HOST) { | |||
| if (is_device_memory(dst, destMax) || is_device_memory(src, count)) { | |||
| return 1; | |||
| } | |||
| } else if (kind == ACL_MEMCPY_HOST_TO_DEVICE) { | |||
| if (!is_device_memory(dst, destMax) || is_device_memory(src, count)) { | |||
| return 1; | |||
| } | |||
| } else if (kind == ACL_MEMCPY_DEVICE_TO_HOST) { | |||
| if (is_device_memory(dst, destMax) || !is_device_memory(src, count)) { | |||
| return 1; | |||
| } | |||
| } else if (kind == ACL_MEMCPY_DEVICE_TO_DEVICE) { | |||
| if (!is_device_memory(dst, destMax) || !is_device_memory(src, count)) { | |||
| return 1; | |||
| } | |||
| } else { | |||
| return 1; | |||
| } | |||
| memcpy(dst, src, count); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError acldvppMalloc(void **devPtr, size_t size) { | |||
| auto buffer = new uint8_t[size]; | |||
| *devPtr = buffer; | |||
| dvpp_buffer_live_.push_back(buffer); | |||
| memory_len_[buffer] = size; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppFree(void *devPtr) { | |||
| auto it = std::find(dvpp_buffer_live_.begin(), dvpp_buffer_live_.end(), devPtr); | |||
| if (it != dvpp_buffer_live_.end()) { | |||
| delete[](*it); | |||
| dvpp_buffer_live_.erase(it); | |||
| dvpp_buffer_destroy_.push_back(*it); | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| return 1; | |||
| } | |||
| std::vector<uint8_t *> device_buffer_live_; | |||
| std::vector<uint8_t *> device_buffer_destroy_; | |||
| std::vector<uint8_t *> host_buffer_live_; | |||
| std::vector<uint8_t *> host_buffer_destroy_; | |||
| std::vector<uint8_t *> dvpp_buffer_live_; | |||
| std::vector<uint8_t *> dvpp_buffer_destroy_; | |||
| std::map<uint8_t *, uint32_t> memory_len_; | |||
| }; | |||
| class AclDvppPicDesc { | |||
| public: | |||
| bool Check() { return pic_desc_.Check(); } | |||
| acldvppPicDesc *acldvppCreatePicDesc() { return pic_desc_.OnCreate(); } | |||
| aclError acldvppDestroyPicDesc(acldvppPicDesc *picDesc) { return pic_desc_.OnDestroy(picDesc); } | |||
| aclError acldvppSetPicDescSize(acldvppPicDesc *picDesc, uint32_t size) { | |||
| picDesc->size = size; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format) { | |||
| picDesc->format = format; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width) { | |||
| picDesc->width = width; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height) { | |||
| picDesc->height = height; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev) { | |||
| picDesc->dataDev = dataDev; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride) { | |||
| picDesc->widthStride = widthStride; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride) { | |||
| picDesc->heightStride = heightStride; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| ResourceBase<acldvppPicDesc *> pic_desc_; | |||
| }; | |||
| class AclDvppRoiConfig { | |||
| public: | |||
| bool Check() { return roi_config_.Check(); } | |||
| acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom) { | |||
| return roi_config_.OnCreate(acldvppRoiConfig{.left = left, .right = right, .top = top, .bottom = bottom}); | |||
| } | |||
| aclError acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig) { return roi_config_.OnDestroy(roiConfig); } | |||
| aclError acldvppSetRoiConfig(acldvppRoiConfig *roiConfig, uint32_t left, uint32_t right, uint32_t top, | |||
| uint32_t bottom) { | |||
| roiConfig->left = left; | |||
| roiConfig->right = right; | |||
| roiConfig->top = top; | |||
| roiConfig->bottom = bottom; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| ResourceBase<acldvppRoiConfig *> roi_config_; | |||
| }; | |||
| class AclDvppResizeConfig { | |||
| public: | |||
| bool Check() { return resize_config_.Check(); } | |||
| acldvppResizeConfig *acldvppCreateResizeConfig() { return resize_config_.OnCreate(acldvppResizeConfig{}); } | |||
| aclError acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig) { | |||
| return resize_config_.OnDestroy(resizeConfig); | |||
| } | |||
| ResourceBase<acldvppResizeConfig *> resize_config_; | |||
| }; | |||
| class AclDvppChannelDesc { | |||
| public: | |||
| bool Check() { return channel_desc_.Check(); } | |||
| aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc) { | |||
| channelDesc->channel_valid_flag = true; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc) { | |||
| channelDesc->channel_valid_flag = false; | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| acldvppChannelDesc *acldvppCreateChannelDesc() { return channel_desc_.OnCreate(); } | |||
| aclError acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc) { | |||
| if (channelDesc->channel_valid_flag) { | |||
| return 1; | |||
| } | |||
| return channel_desc_.OnDestroy(channelDesc); | |||
| } | |||
| ResourceBase<acldvppChannelDesc *> channel_desc_; | |||
| }; | |||
| class AclDvppProcess { | |||
| public: | |||
| bool Check() { return true; } | |||
| virtual aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, | |||
| acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, | |||
| aclrtStream stream) { | |||
| resize_call_times_++; | |||
| if (channelDesc == nullptr || inputDesc == nullptr || outputDesc == nullptr || resizeConfig == nullptr || | |||
| stream == nullptr) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(inputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(outputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, | |||
| acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, aclrtStream stream) { | |||
| crop_call_times_++; | |||
| if (channelDesc == nullptr || inputDesc == nullptr || outputDesc == nullptr || cropArea == nullptr || | |||
| stream == nullptr) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(inputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(outputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckCropArea(cropArea) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, | |||
| acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, | |||
| acldvppRoiConfig *pasteArea, aclrtStream stream) { | |||
| crop_paste_call_times_++; | |||
| if (channelDesc == nullptr || inputDesc == nullptr || outputDesc == nullptr || cropArea == nullptr || | |||
| pasteArea == nullptr || stream == nullptr) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(inputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(outputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckCropArea(cropArea) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| if (CheckCropArea(pasteArea) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchDesc, | |||
| uint32_t *roiNums, uint32_t size, acldvppBatchPicDesc *dstBatchDesc, | |||
| acldvppRoiConfig *cropAreas[], aclrtStream stream) { | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| virtual aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, | |||
| acldvppPicDesc *outputDesc, aclrtStream stream) { | |||
| decode_call_times_++; | |||
| if (channelDesc == nullptr || data == nullptr || size == 0 || outputDesc == nullptr || stream == nullptr) { | |||
| return 1; | |||
| } | |||
| if (outputDesc->widthStride % 128 != 0) { | |||
| return 1; | |||
| } | |||
| if (outputDesc->heightStride % 16 != 0) { | |||
| return 1; | |||
| } | |||
| if (outputDesc->widthStride < 32 || outputDesc->widthStride > 8192) { | |||
| return 1; | |||
| } | |||
| if (outputDesc->heightStride < 32 || outputDesc->heightStride > 8192) { | |||
| return 1; | |||
| } | |||
| if (CheckPicDesc(outputDesc) != ACL_ERROR_NONE) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError CheckCropArea(acldvppRoiConfig *crop_area) { | |||
| if (crop_area->left % 2 != 0 || crop_area->top % 2 != 0) { | |||
| return 1; | |||
| } | |||
| if (crop_area->right % 2 != 1 || crop_area->bottom % 2 != 1) { | |||
| return 1; | |||
| } | |||
| auto crop_width = crop_area->right - crop_area->left + 1; | |||
| if (crop_width < 10 || crop_width > 4096) { | |||
| return 1; | |||
| } | |||
| auto crop_heigth = crop_area->bottom - crop_area->top + 1; | |||
| if (crop_heigth < 6 || crop_heigth > 4096) { | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| aclError CheckPicDesc(acldvppPicDesc *pic_desc) { | |||
| if (pic_desc->width == 0 || pic_desc->height == 0) { | |||
| return 1; | |||
| } | |||
| if (pic_desc->widthStride % 16 != 0 || pic_desc->widthStride < pic_desc->width) { | |||
| return 1; | |||
| } | |||
| if (pic_desc->heightStride % 2 != 0 || pic_desc->heightStride < pic_desc->height) { | |||
| return 1; | |||
| } | |||
| if (pic_desc->widthStride < 32 || pic_desc->widthStride > 4096) { | |||
| return 1; | |||
| } | |||
| if (pic_desc->heightStride < 6 || pic_desc->heightStride > 4096) { | |||
| return 1; | |||
| } | |||
| if (pic_desc->dataDev == nullptr) { | |||
| return 1; | |||
| } | |||
| auto size = pic_desc->size; | |||
| auto ele_cnt = pic_desc->widthStride * pic_desc->heightStride; | |||
| switch (pic_desc->format) { | |||
| case PIXEL_FORMAT_YUV_SEMIPLANAR_420: | |||
| case PIXEL_FORMAT_YVU_SEMIPLANAR_420: | |||
| if (ele_cnt * 3 / 2 != size) { | |||
| return 1; | |||
| } | |||
| break; | |||
| case PIXEL_FORMAT_YUV_SEMIPLANAR_422: | |||
| case PIXEL_FORMAT_YVU_SEMIPLANAR_422: | |||
| if (ele_cnt * 2 != size) { | |||
| return 1; | |||
| } | |||
| break; | |||
| case PIXEL_FORMAT_YUV_SEMIPLANAR_444: | |||
| case PIXEL_FORMAT_YVU_SEMIPLANAR_444: | |||
| if (ele_cnt * 3 != size) { | |||
| return 1; | |||
| } | |||
| break; | |||
| default: | |||
| return 1; | |||
| } | |||
| return ACL_ERROR_NONE; | |||
| } | |||
| uint32_t decode_call_times_ = 0; | |||
| uint32_t resize_call_times_ = 0; | |||
| uint32_t crop_call_times_ = 0; | |||
| uint32_t crop_paste_call_times_ = 0; | |||
| }; | |||
| class AclJpegLib { | |||
| public: | |||
| bool Check() { return jpeg_live_.empty(); } | |||
| AclJpegLib(uint32_t width, uint32_t height) : image_width_(width), image_height_(height) {} | |||
| void jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize) { jpeg_live_.push_back(cinfo); } | |||
| void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer, unsigned long insize) {} | |||
| int jpeg_read_header(j_decompress_ptr cinfo, boolean require_image) { | |||
| static JHUFF_TBL tal; | |||
| cinfo->image_width = image_width_; | |||
| cinfo->image_height = image_height_; | |||
| cinfo->jpeg_color_space = color_space_; | |||
| for (int i = 0; i < NUM_HUFF_TBLS; i++) { | |||
| cinfo->ac_huff_tbl_ptrs[i] = &tal; | |||
| cinfo->dc_huff_tbl_ptrs[i] = &tal; | |||
| } | |||
| return 0; | |||
| } | |||
| void jpeg_destroy_decompress(j_decompress_ptr cinfo) { | |||
| auto it = std::find(jpeg_live_.begin(), jpeg_live_.end(), cinfo); | |||
| if (it != jpeg_live_.end()) { | |||
| jpeg_live_.erase(it); | |||
| } | |||
| } | |||
| uint32_t image_width_; | |||
| uint32_t image_height_; | |||
| J_COLOR_SPACE color_space_ = JCS_YCbCr; | |||
| std::vector<j_decompress_ptr> jpeg_live_; | |||
| }; | |||
| extern AclDataBuffer *g_acl_data_buffer; | |||
| extern AclEnv *g_acl_env; | |||
| extern AclDataSet *g_acl_dataset; | |||
| extern AclModelDesc *g_acl_model_desc; | |||
| extern AclDeviceContextStream *g_acl_device_context_stream; | |||
| extern AclMemory *g_acl_memory; | |||
| extern AclDvppPicDesc *g_acl_dvpp_pic_desc; | |||
| extern AclDvppRoiConfig *g_acl_dvpp_roi_config; | |||
| extern AclDvppResizeConfig *g_acl_dvpp_resize_config; | |||
| extern AclDvppChannelDesc *g_acl_dvpp_channel_desc; | |||
| extern AclDvppProcess *g_acl_dvpp_process; | |||
| extern AclRunMode *g_acl_run_mode; | |||
| extern AclJpegLib *g_acl_jpeg_lib; | |||
| #endif // MINDSPORE_ACL_STUB_H | |||
| @@ -0,0 +1 @@ | |||
| ../../../../serving/ms_service.proto | |||