diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/BackendFactory.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/BackendFactory.cpp new file mode 100644 index 0000000..e184187 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/BackendFactory.cpp @@ -0,0 +1,61 @@ +/** + * 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 "BackendFactory.h" + +BackendFactory *BackendFactory::Instance() { + static BackendFactory instance; + return &instance; +} + +int BackendFactory::Init() { + if (!is_init_) { + std::string skt_bin = "libaclbackend.so"; + //handle_ = dlopen(skt_bin.c_str(), RTLD_NOW | RTLD_GLOBAL); + //if (handle_ == nullptr) { + // GELOGE(FAILED, "SKT: open skt lib failed, please check LD_LIBRARY_PATH."); + //} + } + is_init_ = true; + + return 0; +} + + +std::shared_ptr BackendFactory::CreateBaseBackend(const FrameworkType type) { + std::map::iterator iter = creator_map_.find(type); + if (iter != creator_map_.end()) { + return iter->second(); + } + + return nullptr; +} + +void BackendFactory::RegisterCreator(const FrameworkType type, BASE_BACKEND_CREATOR_FUN fun) { + std::map::iterator iter = creator_map_.find(type); + if (iter != creator_map_.end()) { + return; + } + + creator_map_[type] = fun; +} + +BackendFactory::~BackendFactory() { + creator_map_.clear(); +} + + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/BaseBackend.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/BaseBackend.cpp new file mode 100644 index 0000000..ad5d9b2 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/BaseBackend.cpp @@ -0,0 +1,49 @@ +/** + * 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 "BaseBackend.h" + + + +int BaseBackend::param() +{ + return 0; +} + +int BaseBackend::runner() +{ + return 0; +} + +int BaseBackend::runnerthread() +{ + return 0; +} + +int BaseBackend::statistic() +{ + return 0; +} + + + + + + + + + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.cpp new file mode 100644 index 0000000..0d00fb4 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.cpp @@ -0,0 +1,46 @@ +#include "aclbackend.h" + + +CREATE_BACKEND_INIT(AclBackend,model,data) +{ + Result ret = processSample.InitResource(model); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + return SUCCESS; +} + +CREATE_BACKEND_LOAD(AclBackend,model,data) +{ + INFO_LOG("AclBackend LOAD model success"); + return SUCCESS; +} + +CREATE_BACKEND_PREDICT(AclBackend,model,data,len,output,npuTime) +{ + Result ret = processSample.Process(data,len,output,npuTime); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + INFO_LOG("execute sample success"); + return SUCCESS; +} + +CREATE_BACKEND_UNLOAD(AclBackend,model,data) +{ + Result ret = processSample.Unload(); + if (ret != SUCCESS) { + ERROR_LOG("sample unload failed"); + return FAILED; + } + INFO_LOG("AclBackend UNLOAD model success"); + return SUCCESS; +} + + + +REGISTER_BASE_BACKEND_CREATOR(ACL, AclBackend) + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.h b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.h new file mode 100644 index 0000000..51945c1 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/aclbackend.h @@ -0,0 +1,8 @@ +#include "BackendFactory.h" +#include "sample_process.h" +#include +using namespace std; + +CREATE_BACKEND(AclBackend) + +SampleProcess processSample; diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/model_process.h b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/model_process.h new file mode 100644 index 0000000..0b57135 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/model_process.h @@ -0,0 +1,113 @@ +/** +* @file model_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include +#include "utils.h" +#include "acl/acl.h" +#include +using namespace std; + +/** +* ModelProcess +*/ +class ModelProcess { +public: + /** + * @brief Constructor + */ + ModelProcess(); + + /** + * @brief Destructor + */ + ~ModelProcess(); + + /** + * @brief load model from file with mem + * @param [in] modelPath: model path + * @return result + */ + Result LoadModelFromFileWithMem(const char *modelPath); + + /** + * @brief unload model + */ + void Unload(); + + /** + * @brief create model desc + * @return result + */ + Result CreateDesc(); + + /** + * @brief destroy desc + */ + void DestroyDesc(); + + aclmdlDesc *GetDesc(){return modelDesc_;}; + + /** + * @brief create model input + * @param [in] inputDataBuffer: input buffer + * @param [in] bufferSize: input buffer size + * @return result + */ + Result CreateInput(void *inputDataBuffer, size_t bufferSize); + + /** + * @brief destroy input resource + */ + void DestroyInput(); + + /** + * @brief create output buffer + * @return result + */ + Result CreateOutput(); + + /** + * @brief destroy output resource + */ + void DestroyOutput(); + + //void * GetOutput(){return outputdata;}; + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief dump model output result to file + */ + void DumpModelOutputResult(); + + /** + * @brief get model output result + */ + void OutputModelResult(); + + void OutputModelResult(vector &output); + +public: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; + vector outputdata; +}; + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/sample_process.h b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/sample_process.h new file mode 100644 index 0000000..1933120 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/sample_process.h @@ -0,0 +1,62 @@ +/** +* @file sample_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include "utils.h" +#include "acl/acl.h" +#include "model_process.h" +#include +using namespace std; + +/** +* SampleProcess +*/ +class SampleProcess { +public: + /** + * @brief Constructor + */ + SampleProcess(); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(char* omModelPath); + + /** + * @brief sample process + * @return result + */ + //Result Process(char* binfile); + + Result Process(void* binfile,int len); + + Result Process(void* binfile,int len, vector &output, long &npuTime); + + + Result Unload(); + + //ModelProcess GetModelProcess(); + ModelProcess GetModelProcess(){return processModel;}; + +public: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; + ModelProcess processModel; +}; + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/utils.h b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/utils.h new file mode 100644 index 0000000..23e7734 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/inc/utils.h @@ -0,0 +1,69 @@ +/** +* @file utils.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include +#include "common.h" +#include +#include "acl/acl_base.h" +//#include "Config.h" +/** +* Utils +*/ + +struct aclmdlTensorDesc { + aclmdlTensorDesc() : name(""), size(0), format(ACL_FORMAT_UNDEFINED), dataType(ACL_DT_UNDEFINED) {} + std::string name; + size_t size; + aclFormat format; + aclDataType dataType; + std::vector dims; +}; + +struct aclmdlDesc { + void Clear() + { + inputDesc.clear(); + outputDesc.clear(); + dynamicBatch.clear(); + dynamicHW.clear(); + } + std::vector inputDesc; + std::vector outputDesc; + std::vector dynamicBatch; + std::vector> dynamicHW; +}; + + + +class Utils { +public: + /** + * @brief create device buffer of file + * @param [in] fileName: file name + * @param [out] fileSize: size of file + * @return device buffer of file + */ + static void *GetDeviceBufferOfFile(std::string fileName, uint32_t &fileSize); + + /** + * @brief create buffer of file + * @param [in] fileName: file name + * @param [out] fileSize: size of file + * @return buffer of pic + */ + static void* ReadBinFile(std::string fileName, uint32_t& fileSize); + + static void* GetDeviceBufferOfptr(void* fileName, uint32_t fileSize); + + static long getCurrentTime(); + +}; + +#pragma once diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/model_process.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/model_process.cpp new file mode 100644 index 0000000..17970f9 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/model_process.cpp @@ -0,0 +1,444 @@ +/** +* @file model_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "model_process.h" +#include +#include +#include +#include +#include "utils.h" +using namespace std; +extern bool g_isDevice; +//extern Config configSettings; +extern std::map ACLdt; +extern std::map ACLdt_size; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) +{ +} + +ModelProcess::~ModelProcess() +{ +} + + + +Result ModelProcess::LoadModelFromFileWithMem(const char *modelPath) +{ + if (loadFlag_) { + ERROR_LOG("has already loaded a model"); + return FAILED; + } + + aclError ret = aclmdlQuerySize(modelPath, &modelMemSize_, &modelWeightSize_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("query model failed, model file is %s", modelPath); + return FAILED; + } + //int mem_malloc_type=configSettings.Read("aclrtMemMallocPolicy", 0); + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for weight failed, require size is %zu", modelWeightSize_); + return FAILED; + } + + ret = aclmdlLoadFromFileWithMem(modelPath, &modelId_, modelMemPtr_, + modelMemSize_, modelWeightPtr_, modelWeightSize_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("load model from file failed, model file is %s", modelPath); + return FAILED; + } + + loadFlag_ = true; + INFO_LOG("load model %s success", modelPath); + return SUCCESS; +} + +Result ModelProcess::CreateDesc() +{ + modelDesc_ = aclmdlCreateDesc(); + if (modelDesc_ == nullptr) { + ERROR_LOG("create model description failed"); + return FAILED; + } + + aclError ret = aclmdlGetDesc(modelDesc_, modelId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("get model description failed"); + return FAILED; + } + + INFO_LOG("create model description success"); + + return SUCCESS; +} + +void ModelProcess::DestroyDesc() +{ + if (modelDesc_ != nullptr) { + (void)aclmdlDestroyDesc(modelDesc_); + modelDesc_ = nullptr; + } +} + + +Result ModelProcess::CreateInput(void *inputDataBuffer, size_t bufferSize) +{ + input_ = aclmdlCreateDataset(); + if (input_ == nullptr) { + ERROR_LOG("can't create dataset, create input failed"); + return FAILED; + } + //INFO_LOG("start CreateInput::aclCreateDataBuffer is %d", Utils::getCurrentTime()); + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize); + //INFO_LOG("end CreateInput::aclCreateDataBuffer is %d", Utils::getCurrentTime()); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + //INFO_LOG("start CreateInput::aclmdlAddDatasetBuffer is %d", Utils::getCurrentTime()); + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + //INFO_LOG("end CreateInput::aclmdlAddDatasetBuffer is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("add input dataset buffer failed"); + aclDestroyDataBuffer(inputData); + inputData = nullptr; + return FAILED; + } + + return SUCCESS; +} + +void ModelProcess::DestroyInput() +{ + if (input_ == nullptr) { + return; + } + + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(input_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(input_, i); + aclDestroyDataBuffer(dataBuffer); + } + aclmdlDestroyDataset(input_); + input_ = nullptr; +} + +Result ModelProcess::CreateOutput() +{ + if (modelDesc_ == nullptr) { + ERROR_LOG("no model description, create ouput failed"); + return FAILED; + } + + output_ = aclmdlCreateDataset(); + if (output_ == nullptr) { + ERROR_LOG("can't create dataset, create output failed"); + return FAILED; + } + + size_t outputSize = aclmdlGetNumOutputs(modelDesc_); + for (size_t i = 0; i < outputSize; ++i) { + size_t buffer_size = aclmdlGetOutputSizeByIndex(modelDesc_, i); + + void *outputBuffer = nullptr; + aclError ret = aclrtMalloc(&outputBuffer, buffer_size, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't malloc buffer, size is %zu, create output failed", buffer_size); + return FAILED; + } + + aclDataBuffer* outputData = aclCreateDataBuffer(outputBuffer, buffer_size); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't create data buffer, create output failed"); + aclrtFree(outputBuffer); + return FAILED; + } + + ret = aclmdlAddDatasetBuffer(output_, outputData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("can't add data buffer, create output failed"); + aclrtFree(outputBuffer); + aclDestroyDataBuffer(outputData); + return FAILED; + } + } + + INFO_LOG("create model output success"); + return SUCCESS; +} + +void ModelProcess::DumpModelOutputResult() +{ + stringstream ss; + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + static int executeNum = 0; + for (size_t i = 0; i < outputNum; ++i) { + ss << "output" << ++executeNum << "_" << i << ".bin"; + string outputFileName = ss.str(); + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSize(dataBuffer); + + void* outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&outHostData, len); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret); + return; + } + + ret = aclrtMemcpy(outHostData, len, data, len, ACL_MEMCPY_DEVICE_TO_HOST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret); + (void)aclrtFreeHost(outHostData); + return; + } + + fwrite(outHostData, len, sizeof(char), outputFile); + + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } else { + fwrite(data, len, sizeof(char), outputFile); + } + fclose(outputFile); + outputFile = nullptr; + } else { + ERROR_LOG("create output file [%s] failed", outputFileName.c_str()); + return; + } + } + + INFO_LOG("dump data success"); + return; +} + +void ModelProcess::OutputModelResult() +{ + + aclError ret = ACL_ERROR_NONE; + + if(outputdata.size()!=0) + { + for(auto it=outputdata.begin();it!=outputdata.end();++it){ + ret = aclrtFreeHost(*it); + } + outputdata.clear(); + } + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSize(dataBuffer); + //INFO_LOG("OutputModelResult::len %d", len); + //void *outHostData = NULL; + outputdata.push_back(NULL); + ret = ACL_ERROR_NONE; + float *outData = NULL; + if (!g_isDevice) { + //INFO_LOG("start OutputModelResult::aclrtMallocHost is %d", Utils::getCurrentTime()); + aclError ret = aclrtMallocHost(&outputdata[i], len); + //INFO_LOG("end OutputModelResult::aclrtMallocHost is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMallocHost failed, ret[%d]", ret); + return; + } + //INFO_LOG("start OutputModelResult::aclrtMemcpy is %d", Utils::getCurrentTime()); + ret = aclrtMemcpy(outputdata[i], len, data, len, ACL_MEMCPY_DEVICE_TO_HOST); + //INFO_LOG("end OutputModelResult::aclrtMemcpy is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtMemcpy failed, ret[%d]", ret); + return; + } + + outData = reinterpret_cast(outputdata[i]); + //outputdata.push_back(outHostData); + } else { + outData = reinterpret_cast(data); + outputdata.push_back(data); + } + map > resultMap; + for (unsigned int j = 0; j < len / sizeof(float); ++j) { + resultMap[*outData] = j; + outData++; + } + + int cnt = 0; + for (auto it = resultMap.begin(); it != resultMap.end(); ++it) { + // print top 5 + if (++cnt > 5) { + break; + } + + //INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first); + } + } + + INFO_LOG("1.output data success"); + return; +} + +void ModelProcess::OutputModelResult(vector &output) +{ + + OutputModelResult(); + + size_t outputSize = aclmdlGetNumOutputs(modelDesc_); + + + for (size_t i = 0; i < outputSize; ++i) { + Output_buf tmp_output; + //ptr + tmp_output.ptr = outputdata[i]; + //size + tmp_output.size = aclmdlGetOutputSizeByIndex(modelDesc_, i); + //ndim & shape + aclmdlIODims d={{'a'},0,{1,2,3}}; + aclmdlIODims *dims=&d; + aclError ret = aclmdlGetOutputDims((const aclmdlDesc *)modelDesc_, i, dims); + tmp_output.ndim = (*dims).dimCount; + for(int j=0;j<(*dims).dimCount;j++) + tmp_output.shape.push_back((*dims).dims[j]); + + //itemsize & format + aclDataType dt = aclmdlGetOutputDataType(modelDesc_, i); + tmp_output.itemsize=ACLdt_size[dt]; + tmp_output.format=ACLdt[dt]; +// if(dt==ACL_FLOAT) +// { +// tmp_output.itemsize=4; +// tmp_output.format="float"; +// } +// if(dt==ACL_FLOAT16) +// { +// tmp_output.itemsize=2; +// tmp_output.format="float16"; +// } +// if(dt==ACL_UINT8) +// { +// tmp_output.itemsize=1; +// tmp_output.format="uint8"; +// } +// if(dt==ACL_INT8) +// { +// tmp_output.itemsize=1; +// tmp_output.format="int8"; +// } + + //strides + int strides=tmp_output.itemsize; + std::vector tmp_strides; + std::vector tmp1_strides; + //vector::reverse_iterator it;//声明一个迭代器,来访问vector容器,作用:遍历或者指向vector容器的元素 + for(auto it=tmp_output.shape.rbegin();it!=tmp_output.shape.rend();++it) + { + tmp_strides.push_back(strides); + strides = strides * (*it); + } + //for (int index = 0 ; index < tmp_output.ndim; index++) { + // tmp_strides.push_back(strides); + // strides = strides * tmp_output.shape[index]; + //} + for(auto it=tmp_strides.rbegin();it!=tmp_strides.rend();++it){ + //for (int index=0;index < tmp_strides.size(); index++) { + tmp1_strides.push_back(*it); + } + tmp_output.strides = tmp1_strides; + output.push_back(tmp_output); + } + INFO_LOG("2.output data success"); +} +void ModelProcess::DestroyOutput() +{ + if (output_ == nullptr) { + return; + } + + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + (void)aclrtFree(data); + (void)aclDestroyDataBuffer(dataBuffer); + } + + (void)aclmdlDestroyDataset(output_); + output_ = nullptr; +} + +Result ModelProcess::Execute() +{ + aclError ret = aclmdlExecute(modelId_, input_, output_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("execute model failed, modelId is %u", modelId_); + return FAILED; + } + + INFO_LOG("model execute success"); + return SUCCESS; +} + +void ModelProcess::Unload() +{ + aclError ret; + if (!g_isDevice) { + //INFO_LOG("start Unload::aclrtFreeHost is %d", Utils::getCurrentTime()); + //for (int index = 0 ; index < outputdata.size(); index++) { + // ret = aclrtFreeHost(outputdata[index]); + //} + for(auto it=outputdata.begin();it!=outputdata.end();++it){ + ret = aclrtFreeHost(*it); + } + //INFO_LOG("end Unload::aclrtFreeHost is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + ret = aclmdlUnload(modelId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("unload model failed, modelId is %u", modelId_); + } + + if (modelDesc_ != nullptr) { + (void)aclmdlDestroyDesc(modelDesc_); + modelDesc_ = nullptr; + } + + if (modelMemPtr_ != nullptr) { + aclrtFree(modelMemPtr_); + modelMemPtr_ = nullptr; + modelMemSize_ = 0; + } + + if (modelWeightPtr_ != nullptr) { + aclrtFree(modelWeightPtr_); + modelWeightPtr_ = nullptr; + modelWeightSize_ = 0; + } + + loadFlag_ = false; + INFO_LOG("unload model success, modelId is %u", modelId_); +} diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/sample_process.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/sample_process.cpp new file mode 100644 index 0000000..49156de --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/sample_process.cpp @@ -0,0 +1,249 @@ +/** +* @file sample_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "sample_process.h" +#include +#include "acl/acl.h" +#include "utils.h" +using namespace std; +extern bool g_isDevice; + + +SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) +{ +} + +SampleProcess::~SampleProcess() +{ +} + +Result SampleProcess::InitResource(char* omModelPath) +{ + // ACL init + const char *aclConfigPath; + if((aclConfigPath = getenv("ACL_CONFIG_PATH"))) { + INFO_LOG("acl init with config file:%s", aclConfigPath); + } else { + aclConfigPath = ""; + } + aclError ret = aclInit(aclConfigPath); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl init failed"); + return FAILED; + } + INFO_LOG("acl init success"); + + // open device + ret = aclrtSetDevice(deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl open device %d failed", deviceId_); + return FAILED; + } + INFO_LOG("open device %d success", deviceId_); + + // create context (set current) + ret = aclrtCreateContext(&context_, deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl create context failed"); + return FAILED; + } + INFO_LOG("create context success"); + + // create stream + ret = aclrtCreateStream(&stream_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl create stream failed"); + return FAILED; + } + INFO_LOG("create stream success"); + + // get run mode + aclrtRunMode runMode; + ret = aclrtGetRunMode(&runMode); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("acl get run mode failed"); + return FAILED; + } + g_isDevice = (runMode == ACL_DEVICE); + INFO_LOG("get run mode success"); + Result r_ret = processModel.LoadModelFromFileWithMem(omModelPath); + if (r_ret != SUCCESS) { + ERROR_LOG("load model from file failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("create model description failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("create model output failed"); + return FAILED; + } + + return SUCCESS; +} + +Result SampleProcess::Process(void* binfile,int len) +{ + //for (size_t index = 0; index < sizeof(testFile) / sizeof(testFile[0]); ++index) { + //INFO_LOG("start to process file:%s", binfile.c_str()); + // model process + //INFO_LOG("start memcpy is %d", Utils::getCurrentTime()); + uint32_t devBufferSize = len; + void *picDevBuffer = Utils::GetDeviceBufferOfptr(binfile,len); + //ERROR_LOG("devBufferSize is %d", len); + //ERROR_LOG("picDevBuffer:%f.", *((float*)picDevBuffer)); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", 0); + return FAILED; + } + //INFO_LOG("end memcpy is %d", Utils::getCurrentTime()); + + //INFO_LOG("start CreateInput is %d", Utils::getCurrentTime()); + Result ret = processModel.CreateInput(picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("model create input failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + //INFO_LOG("end CreateInput is %d", Utils::getCurrentTime()); + + INFO_LOG("start Execute is %d", Utils::getCurrentTime()); + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("model execute failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + INFO_LOG("end Execute is %d", Utils::getCurrentTime()); + + //INFO_LOG("start aclrtFree is %d", Utils::getCurrentTime()); + // release model input buffer + aclrtFree(picDevBuffer); + //INFO_LOG("end aclrtFree is %d", Utils::getCurrentTime()); + + // print the top 5 confidence values with indexes.use function DumpModelOutputResult + // if want to dump output result to file in the current directory + processModel.OutputModelResult(); + + //} + // loop end + + + return SUCCESS; +} + +Result SampleProcess::Process(void* binfile,int len, vector &output, long &npuTime) +{ + //for (size_t index = 0; index < sizeof(testFile) / sizeof(testFile[0]); ++index) { + //INFO_LOG("start to process file:%s", binfile.c_str()); + // model process + //INFO_LOG("start memcpy is %d", Utils::getCurrentTime()); + uint32_t devBufferSize = len; + void *picDevBuffer = Utils::GetDeviceBufferOfptr(binfile,len); + //ERROR_LOG("devBufferSize is %d", len); + //ERROR_LOG("picDevBuffer:%f.", *((float*)picDevBuffer)); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", 0); + return FAILED; + } + //INFO_LOG("end memcpy is %d", Utils::getCurrentTime()); + + //INFO_LOG("start CreateInput is %d", Utils::getCurrentTime()); + Result ret = processModel.CreateInput(picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("model create input failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + //INFO_LOG("end CreateInput is %d", Utils::getCurrentTime()); + + INFO_LOG("start Execute is %d", Utils::getCurrentTime()); + long start = Utils::getCurrentTime(); + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("model execute failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + long end = Utils::getCurrentTime(); + INFO_LOG("end Execute is %d", end); + + npuTime = end - start; + if (npuTime < 0) { + ERROR_LOG("NPU time not correct: %d start: %d end: %d", npuTime, start, end); + aclrtFree(picDevBuffer); + return FAILED; + } + INFO_LOG("npu compute cost %f ms", 1.0*(npuTime)/1000.0); + + //INFO_LOG("start aclrtFree is %d", Utils::getCurrentTime()); + // release model input buffer + aclrtFree(picDevBuffer); + //INFO_LOG("end aclrtFree is %d", Utils::getCurrentTime()); + + // print the top 5 confidence values with indexes.use function DumpModelOutputResult + // if want to dump output result to file in the current directory + processModel.OutputModelResult(output); + + //} + // loop end + + + return SUCCESS; +} + +Result SampleProcess::Unload() +{ + processModel.Unload(); + processModel.DestroyDesc(); + processModel.DestroyInput(); + processModel.DestroyOutput(); + DestroyResource(); + return SUCCESS; +} + +void SampleProcess::DestroyResource() +{ + aclError ret; + if (stream_ != nullptr) { + ret = aclrtDestroyStream(stream_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("destroy stream failed"); + } + stream_ = nullptr; + INFO_LOG("end to destroy stream"); + } + + if (context_ != nullptr) { + ret = aclrtDestroyContext(context_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("destroy context failed"); + } + context_ = nullptr; + INFO_LOG("end to destroy context"); + } + + ret = aclrtResetDevice(deviceId_); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("reset device failed"); + } + INFO_LOG("end to reset device is %d", deviceId_); + + ret = aclFinalize(); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("finalize acl failed"); + } + INFO_LOG("end to finalize acl"); + +} diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/utils.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/utils.cpp new file mode 100644 index 0000000..0d11469 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/built-in/src/utils.cpp @@ -0,0 +1,171 @@ +/** +* @file utils.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "utils.h" +#include +#include +#include +#include "acl/acl.h" +#include +#include + +bool g_isDevice = false; + +std::map ACLdt{{ ACL_DT_UNDEFINED , "undefined"}, +{ ACL_FLOAT , "float"}, +{ ACL_FLOAT16 , "float16"}, +{ ACL_INT8 , "int8"}, +{ ACL_INT32 , "int32"}, +{ ACL_UINT8 , "uint8"}, +{ ACL_INT16 , "int16"}, +{ ACL_UINT16 , "uint16"}, +{ ACL_UINT32 , "uint32"}, +{ ACL_INT64 , "int64"}, +{ ACL_UINT64 , "uint64"}, +{ ACL_DOUBLE , "double"}, +{ ACL_BOOL , "bool"}}; +std::map ACLdt_size{{ ACL_DT_UNDEFINED , -1}, +{ ACL_FLOAT , 4}, +{ ACL_FLOAT16 , 2}, +{ ACL_INT8 , 1}, +{ ACL_INT32 , 4}, +{ ACL_UINT8 , 1}, +{ ACL_INT16 , 2}, +{ ACL_UINT16 , 2}, +{ ACL_UINT32 , 4}, +{ ACL_INT64 , 8}, +{ ACL_UINT64 , 8}, +{ ACL_DOUBLE , 8}, +{ ACL_BOOL , 1}}; + +//Config configSettings("cfg/built-in_config.txt"); + +void* Utils::ReadBinFile(std::string fileName, uint32_t &fileSize) +{ + std::ifstream binFile(fileName, std::ifstream::binary); + if (binFile.is_open() == false) { + ERROR_LOG("open file %s failed", fileName.c_str()); + return nullptr; + } + + binFile.seekg(0, binFile.end); + uint32_t binFileBufferLen = binFile.tellg(); + if (binFileBufferLen == 0) { + ERROR_LOG("binfile is empty, filename is %s", fileName.c_str()); + binFile.close(); + return nullptr; + } + //ERROR_LOG("binFileBufferLen is %d", binFileBufferLen); + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc device buffer failed. size is %u", binFileBufferLen); + binFile.close(); + return nullptr; + } + } + binFile.read(static_cast(binFileBufferData), binFileBufferLen); + binFile.close(); + fileSize = binFileBufferLen; + return binFileBufferData; +} + +void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t &fileSize) +{ + uint32_t inputHostBuffSize = 0; + void* inputHostBuff = Utils::ReadBinFile(fileName, inputHostBuffSize); + if (inputHostBuff == nullptr) { + return nullptr; + } + if (!g_isDevice) { + void *inBufferDev = nullptr; + uint32_t inBufferSize = inputHostBuffSize; + aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + + ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u", + inBufferSize, inputHostBuffSize); + aclrtFree(inBufferDev); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + aclrtFreeHost(inputHostBuff); + fileSize = inBufferSize; + return inBufferDev; + } else { + fileSize = inputHostBuffSize; + return inputHostBuff; + } +} + +void* Utils::GetDeviceBufferOfptr(void* fileName, uint32_t len) +{ + uint32_t inputHostBuffSize = len; + void* inputHostBuff = fileName; + if (inputHostBuff == nullptr) { + return nullptr; + } + if (!g_isDevice) { + void *inBufferDev = nullptr; + uint32_t inBufferSize = inputHostBuffSize; + //INFO_LOG("start memcpy::aclrtMalloc is %d", Utils::getCurrentTime()); + aclError ret = aclrtMalloc(&inBufferDev, inBufferSize, (aclrtMemMallocPolicy)(Config::getInstance()->Read("aclrtMemMallocPolicy", 0))); + //INFO_LOG("end memcpy::aclrtMalloc is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc device buffer failed. size is %u", inBufferSize); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + //INFO_LOG("start memcpy::aclrtMemcpy is %d", Utils::getCurrentTime()); + ret = aclrtMemcpy(inBufferDev, inBufferSize, inputHostBuff, inputHostBuffSize, ACL_MEMCPY_HOST_TO_DEVICE); + //INFO_LOG("end memcpy::aclrtMemcpy is %d", Utils::getCurrentTime()); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("memcpy failed. device buffer size is %u, input host buffer size is %u", + inBufferSize, inputHostBuffSize); + aclrtFree(inBufferDev); + aclrtFreeHost(inputHostBuff); + return nullptr; + } + //INFO_LOG("start memcpy::aclrtFreeHost is %d", Utils::getCurrentTime()); + aclrtFreeHost(inputHostBuff); + //INFO_LOG("end memcpy::aclrtFreeHost is %d", Utils::getCurrentTime()); + //fileSize = inBufferSize; + return inBufferDev; + } else { + //fileSize = inputHostBuffSize; + return inputHostBuff; + } +} + + +long Utils::getCurrentTime() +{ + struct timeval tv; + gettimeofday(&tv,NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; + // return tv.tv_usec; +} diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.cpp b/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.cpp new file mode 100644 index 0000000..9811d28 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.cpp @@ -0,0 +1,29 @@ +#include "trtbackend.h" + +CREATE_BACKEND_INIT(TrtBackend,model,data) +{ + INFO_LOG("TrtBackend INIT model success"); + return 0; +} + +CREATE_BACKEND_LOAD(TrtBackend,model,data) +{ + INFO_LOG("TrtBackend LOAD model success"); + return 0; +} + +CREATE_BACKEND_PREDICT(TrtBackend,model,data,len,output,gpuTime) +{ + INFO_LOG("TrtBackend PREDICT model success"); + return 0; +} +CREATE_BACKEND_UNLOAD(TrtBackend,model,data) +{ + INFO_LOG("TrtBackend UNLOAD model success"); + return 0; +} + + +REGISTER_BASE_BACKEND_CREATOR(TRT, TrtBackend) + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.h b/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.h new file mode 100644 index 0000000..42e4592 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/custom/trtbackend.h @@ -0,0 +1,7 @@ +#include "BackendFactory.h" +#include + +CREATE_BACKEND(TrtBackend) + + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/inc/BackendFactory.h b/dnmetis/backend_C++/dnmetis_backend/backend/inc/BackendFactory.h new file mode 100644 index 0000000..6942a20 --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/inc/BackendFactory.h @@ -0,0 +1,91 @@ +/** + * 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 BASE_BACKEND_FACTORY_H_ +#define BASE_BACKEND_FACTORY_H_ + +#include +#include +#include +#include +#include "BaseBackend.h" + + + +typedef std::shared_ptr (*BASE_BACKEND_CREATOR_FUN)(void); + +class BackendFactory { + public: + static BackendFactory *Instance(); + int Init(); + /** + * @ingroup domi_omg + * @brief Create a backend based on the type entered + * @param [in] type Framework type + * @return Created backend + */ + std::shared_ptr CreateBaseBackend(const FrameworkType type); + + /** + * @ingroup domi_omg + * @brief Register create function + * @param [in] type Framework type + * @param [in] fun ModelParser's create function + */ + void RegisterCreator(const FrameworkType type, BASE_BACKEND_CREATOR_FUN fun); + + protected: + BackendFactory() {} + ~BackendFactory(); + + private: + std::map creator_map_; + bool is_init_ = false; +}; // end class BackendFactory + +class BaseBackendRegisterar { + public: + BaseBackendRegisterar(const FrameworkType type, BASE_BACKEND_CREATOR_FUN fun) { + BackendFactory::Instance()->RegisterCreator(type, fun); + } + ~BaseBackendRegisterar() {} +}; + +// Registration macros for backend +typedef std::shared_ptr (*BASE_BACKEND_CREATOR_FUN)(void); + +// Registration macros for BaseBackend +#define REGISTER_BASE_BACKEND_CREATOR(type, clazz) \ + std::shared_ptr Creator_##type##_Base_Backend() { \ + std::shared_ptr ptr = nullptr; \ + try { \ + ptr = std::make_shared(); \ + } catch (...) { \ + ptr = nullptr; \ + } \ + return std::shared_ptr(ptr); \ + } \ + BaseBackendRegisterar g_##type##_Base_Backend_Creator(type, Creator_##type##_Base_Backend); + + +#endif + + + + + + + diff --git a/dnmetis/backend_C++/dnmetis_backend/backend/inc/BaseBackend.h b/dnmetis/backend_C++/dnmetis_backend/backend/inc/BaseBackend.h new file mode 100644 index 0000000..caa9dff --- /dev/null +++ b/dnmetis/backend_C++/dnmetis_backend/backend/inc/BaseBackend.h @@ -0,0 +1,78 @@ + +/** + * 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 BASE_BACKEND_H_ +#define BASE_BACKEND_H_ + +//#include "utils.h" +#include "common.h" +#include +using namespace std; + +class BaseBackend { + public: + BaseBackend() {}; + /** + * @ingroup domi_omg + * @brief Deconstructor + */ + ~BaseBackend() {}; + + virtual int init(char* model,char* data){}; + + virtual int load(char* model,char* data){}; + + virtual int predict(char* model,void* data,int len, std::vector &output, long &deviceTime){}; + + virtual int unload(char* model,char* data){}; + + int param(); + + int runner(); + + int runnerthread(); + + int statistic(); + +}; + + + +#define CREATE_BACKEND(x) \ +class x : public BaseBackend{ \ +public: \ + x(){}; \ + ~x(){}; \ + int init(char* model,char* data); \ + int load(char* model,char* data); \ + int predict(char* model,void* data,int len, vector &output, long &deviceTime); \ + int unload(char* model,char* data); \ + char* model; \ + char* data; \ + }; \ + +#define CREATE_BACKEND_INIT(x,model,data) \ + int x::init(char* model,char* data) +#define CREATE_BACKEND_LOAD(x,model,data) \ + int x::load(char* model,char* data) +#define CREATE_BACKEND_PREDICT(x,model,data,len,output,deviceTime) \ + int x::predict(char* model,void* data,int len,vector &output, long &deviceTime) +#define CREATE_BACKEND_UNLOAD(x,model,data) \ + int x::unload(char* model,char* data) + +#endif +