600 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			600 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | ||
|  * Copyright(C) 2020. Huawei Technologies Co.,Ltd. All rights reserved.
 | ||
|  *
 | ||
|  * 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.
 | ||
|  */
 | ||
| 
 | ||
| #ifdef USE_DCMI_INTERFACE
 | ||
| #include <unistd.h>
 | ||
| #include <termios.h>
 | ||
| #endif
 | ||
| #include "ModelProcess.h"
 | ||
| #include "FileManager.h"
 | ||
| 
 | ||
| ModelProcess::ModelProcess(const int deviceId, const std::string &modelName)
 | ||
| {
 | ||
|     deviceId_ = deviceId;
 | ||
|     modelName_ = modelName;
 | ||
| }
 | ||
| 
 | ||
| ModelProcess::ModelProcess() {}
 | ||
| 
 | ||
| ModelProcess::~ModelProcess()
 | ||
| {
 | ||
|     if (!isDeInit_)
 | ||
|     {
 | ||
|         DeInit();
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| void ModelProcess::DestroyDataset(const aclmdlDataset *dataset) const
 | ||
| {
 | ||
|     // Just release the DataBuffer object and DataSet object, remain the buffer, because it is managerd by user
 | ||
|     if (dataset != nullptr)
 | ||
|     {
 | ||
|         for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(dataset); i++)
 | ||
|         {
 | ||
|             aclDataBuffer *dataBuffer = aclmdlGetDatasetBuffer(dataset, i);
 | ||
|             if (dataBuffer != nullptr)
 | ||
|             {
 | ||
|                 aclDestroyDataBuffer(dataBuffer);
 | ||
|                 dataBuffer = nullptr;
 | ||
|             }
 | ||
|         }
 | ||
|         aclmdlDestroyDataset(dataset);
 | ||
|         dataset = nullptr;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| aclmdlDesc *ModelProcess::GetModelDesc() const
 | ||
| {
 | ||
|     return modelDesc_.get();
 | ||
| }
 | ||
| 
 | ||
| //从device侧获得推理数据
 | ||
| int ModelProcess::ModelInference_from_dvpp(void *buffer, uint32_t buffer_size)
 | ||
| {
 | ||
|     std::vector<void *> inputBuffers{buffer};
 | ||
|     std::vector<size_t> inputSizes{buffer_size};
 | ||
| 
 | ||
|     //创建输入数据集
 | ||
|     aclmdlDataset *input = nullptr;
 | ||
|     input = CreateAndFillDataset(inputBuffers, inputSizes);
 | ||
|     if (input == nullptr)
 | ||
|     {
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
| 
 | ||
|     APP_ERROR ret = 0;
 | ||
| 
 | ||
|     //创建输出数据集
 | ||
|     aclmdlDataset *output = nullptr;
 | ||
|     output = CreateAndFillDataset(outputBuffers_, outputSizes_);
 | ||
|     if (output == nullptr)
 | ||
|     {
 | ||
|         DestroyDataset(input);
 | ||
|         input = nullptr;
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
| 
 | ||
|     //对同一个modelId的模型,由于与模型关联的资源(例如stream、内存等)唯一,因此不能在多线程中并发使用,否则,可能导致业务异常。
 | ||
|     //同一个id的可以加锁,不同id的不用加锁
 | ||
|     mtx_.lock();
 | ||
|     ret = aclmdlExecute(modelId_, input, output);
 | ||
|     mtx_.unlock();
 | ||
| 
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlExecute failed, ret[" << ret << "].";
 | ||
|         //加上,防止内存泄露
 | ||
|         DestroyDataset(input);
 | ||
|         DestroyDataset(output);
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     DestroyDataset(input);
 | ||
|     DestroyDataset(output);
 | ||
| 
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| int ModelProcess::ModelInference(const std::vector<void *> &inputBufs, const std::vector<size_t> &inputSizes,
 | ||
|                                  const std::vector<void *> &ouputBufs, const std::vector<size_t> &outputSizes, size_t dynamicBatchSize)
 | ||
| {
 | ||
|     LogDebug << "ModelProcess:Begin to inference.";
 | ||
|     aclmdlDataset *input = nullptr;
 | ||
|     input = CreateAndFillDataset(inputBufs, inputSizes);
 | ||
|     if (input == nullptr)
 | ||
|     {
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
|     APP_ERROR ret = 0;
 | ||
|     if (dynamicBatchSize != 0)
 | ||
|     {
 | ||
|         size_t index;
 | ||
|         ret = aclmdlGetInputIndexByName(modelDesc_.get(), ACL_DYNAMIC_TENSOR_NAME, &index);
 | ||
|         if (ret != ACL_ERROR_NONE)
 | ||
|         {
 | ||
|             LogError << "aclmdlGetInputIndexByName failed, maybe static model";
 | ||
|             return APP_ERR_COMM_CONNECTION_FAILURE;
 | ||
|         }
 | ||
|         ret = aclmdlSetDynamicBatchSize(modelId_, input, index, dynamicBatchSize);
 | ||
|         if (ret != ACL_ERROR_NONE)
 | ||
|         {
 | ||
|             LogError << "dynamic batch set failed, modelId_=" << modelId_ << ", input=" << input << ", index=" << index
 | ||
|                      << ", dynamicBatchSize=" << dynamicBatchSize;
 | ||
|             return APP_ERR_COMM_CONNECTION_FAILURE;
 | ||
|         }
 | ||
|         LogDebug << "set dynamicBatchSize success, dynamicBatchSize=" << dynamicBatchSize;
 | ||
|     }
 | ||
|     aclmdlDataset *output = nullptr;
 | ||
|     output = CreateAndFillDataset(ouputBufs, outputSizes);
 | ||
|     if (output == nullptr)
 | ||
|     {
 | ||
|         DestroyDataset(input);
 | ||
|         input = nullptr;
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
|     mtx_.lock();
 | ||
|     ret = aclmdlExecute(modelId_, input, output);
 | ||
|     mtx_.unlock();
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlExecute failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     DestroyDataset(input);
 | ||
|     DestroyDataset(output);
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| int ModelProcess::ModelInferDynamicHW(const std::vector<void *> &inputBufs, const std::vector<size_t> &inputSizes,
 | ||
|                                       const std::vector<void *> &ouputBufs, const std::vector<size_t> &outputSizes)
 | ||
| {
 | ||
|     LogDebug << "ModelProcess:Begin to inference with dynamic width and height.";
 | ||
|     aclmdlDataset *input = nullptr;
 | ||
|     input = CreateAndFillDataset(inputBufs, inputSizes);
 | ||
|     if (input == nullptr)
 | ||
|     {
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
|     size_t index;
 | ||
|     APP_ERROR ret = aclmdlGetInputIndexByName(modelDesc_.get(), ACL_DYNAMIC_TENSOR_NAME, &index);
 | ||
|     if (ret != ACL_ERROR_NONE)
 | ||
|     {
 | ||
|         LogError << "Failed to execute aclmdlGetInputIndexByName, maybe static model.";
 | ||
|         return APP_ERR_COMM_CONNECTION_FAILURE;
 | ||
|     }
 | ||
|     ret = aclmdlSetDynamicHWSize(modelId_, input, index, modelHeight_, modelWidth_);
 | ||
|     if (ret != ACL_ERROR_NONE)
 | ||
|     {
 | ||
|         LogError << "Failed to set dynamic HW, modelId_=" << modelId_ << ", input=" << input << ", index="
 | ||
|                  << index << ", dynamicW=" << modelWidth_ << ", dynamicH=" << modelHeight_;
 | ||
|         return APP_ERR_COMM_CONNECTION_FAILURE;
 | ||
|     }
 | ||
|     LogDebug << "Set dynamicHWSize success, dynamicHWSize=" << modelWidth_ << ", " << modelHeight_;
 | ||
| 
 | ||
|     aclmdlDataset *output = nullptr;
 | ||
|     output = CreateAndFillDataset(ouputBufs, outputSizes);
 | ||
|     if (output == nullptr)
 | ||
|     {
 | ||
|         DestroyDataset(input);
 | ||
|         input = nullptr;
 | ||
|         return APP_ERR_COMM_FAILURE;
 | ||
|     }
 | ||
|     mtx_.lock();
 | ||
|     ret = aclmdlExecute(modelId_, input, output);
 | ||
|     mtx_.unlock();
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlExecute failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     DestroyDataset(input);
 | ||
|     DestroyDataset(output);
 | ||
| 
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| int ModelProcess::DeInit()
 | ||
| {
 | ||
|     LogInfo << "Model[" << modelName_ << "][" << deviceId_ << "] deinit begin";
 | ||
| 
 | ||
|     isDeInit_ = true;
 | ||
| 
 | ||
|     //卸载模型
 | ||
|     APP_ERROR ret = aclmdlUnload(modelId_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlUnload  failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     //释放工作内存
 | ||
|     if (modelDevPtr_ != nullptr)
 | ||
|     {
 | ||
|         ret = aclrtFree(modelDevPtr_);
 | ||
|         if (ret != APP_ERR_OK)
 | ||
|         {
 | ||
|             LogError << "aclrtFree  failed, ret[" << ret << "].";
 | ||
|             return ret;
 | ||
|         }
 | ||
|         modelDevPtr_ = nullptr;
 | ||
|     }
 | ||
|     //释放权值内存
 | ||
|     if (weightDevPtr_ != nullptr)
 | ||
|     {
 | ||
|         ret = aclrtFree(weightDevPtr_);
 | ||
|         if (ret != APP_ERR_OK)
 | ||
|         {
 | ||
|             LogError << "aclrtFree  failed, ret[" << ret << "].";
 | ||
|             return ret;
 | ||
|         }
 | ||
|         weightDevPtr_ = nullptr;
 | ||
|     }
 | ||
| 
 | ||
|     //释放输入内存
 | ||
|     for (size_t i = 0; i < inputBuffers_.size(); i++)
 | ||
|     {
 | ||
|         if (inputBuffers_[i] != nullptr)
 | ||
|         {
 | ||
|             aclrtFree(inputBuffers_[i]);
 | ||
|             inputBuffers_[i] = nullptr;
 | ||
|         }
 | ||
|     }
 | ||
|     inputBuffers_.clear();
 | ||
|     inputSizes_.clear();
 | ||
| 
 | ||
|     //释放输出内存
 | ||
|     for (size_t i = 0; i < outputBuffers_.size(); i++)
 | ||
|     {
 | ||
|         if (outputBuffers_[i] != nullptr)
 | ||
|         {
 | ||
|             aclrtFree(outputBuffers_[i]);
 | ||
|             outputBuffers_[i] = nullptr;
 | ||
|         }
 | ||
|     }
 | ||
|     outputBuffers_.clear();
 | ||
|     outputSizes_.clear();
 | ||
| 
 | ||
|     LogInfo << "Model[" << modelName_ << "][" << deviceId_ << "] deinit success";
 | ||
| 
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR ModelProcess::LoadModel(const std::shared_ptr<uint8_t> &modelData, int modelSize)
 | ||
| {
 | ||
|     APP_ERROR ret = aclmdlQuerySizeFromMem(modelData.get(), modelSize, &modelDevPtrSize_, &weightDevPtrSize_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlQuerySizeFromMem failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
|     LogDebug << "modelDevPtrSize_[" << modelDevPtrSize_ << "], weightDevPtrSize_[" << weightDevPtrSize_ << "].";
 | ||
| 
 | ||
|     //申请Device上的内存
 | ||
|     ret = aclrtMalloc(&modelDevPtr_, modelDevPtrSize_, ACL_MEM_MALLOC_HUGE_FIRST);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclrtMalloc dev_ptr failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
|     //申请Device上的内存
 | ||
|     ret = aclrtMalloc(&weightDevPtr_, weightDevPtrSize_, ACL_MEM_MALLOC_HUGE_FIRST);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclrtMalloc weight_ptr failed, ret[" << ret << "] (" << GetAppErrCodeInfo(ret) << ").";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     //从内存加载离线模型数据,由用户自行管理模型运行的内存
 | ||
|     //统完成模型加载后,返回的模型ID,作为后续操作时用于识别模型的标志。
 | ||
|     ret = aclmdlLoadFromMemWithMem(modelData.get(), modelSize, &modelId_, modelDevPtr_, modelDevPtrSize_, weightDevPtr_, weightDevPtrSize_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlLoadFromMemWithMem failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     //对同一个modelId的模型,由于与模型关联的资源(例如stream、内存等)唯一,因此不能在多线程中并发使用,否则,可能导致业务异常。
 | ||
|     //每次加载id都递增
 | ||
|     // printf("modelid:%d\n", modelId_);
 | ||
| 
 | ||
|     ret = aclrtGetCurrentContext(&contextModel_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclrtMalloc weight_ptr failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     // get input and output size
 | ||
|     aclmdlDesc *modelDesc = aclmdlCreateDesc();
 | ||
|     if (modelDesc == nullptr)
 | ||
|     {
 | ||
|         LogError << "aclmdlCreateDesc failed.";
 | ||
|         return APP_ERR_ACL_FAILURE;
 | ||
|     }
 | ||
|     ret = aclmdlGetDesc(modelDesc, modelId_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "aclmdlGetDesc ret fail, ret:" << ret << ".";
 | ||
|         return ret;
 | ||
|     }
 | ||
|     modelDesc_.reset(modelDesc, aclmdlDestroyDesc);
 | ||
| 
 | ||
|     //输入内存不用分配,用dvpp的输出内存
 | ||
| 
 | ||
|     //分配输出内存
 | ||
|     OutputBufferWithSizeMalloc(ACL_MEM_MALLOC_NORMAL_ONLY);
 | ||
| 
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR ModelProcess::Init(std::string modelPath)
 | ||
| {
 | ||
|     LogInfo << "ModelProcess:Begin to init instance.";
 | ||
|     int modelSize = 0;
 | ||
|     std::shared_ptr<uint8_t> modelData = nullptr;
 | ||
| 
 | ||
|     // modelPath should point to an encrypted model when isEncrypted is true
 | ||
|     APP_ERROR ret = ReadBinaryFile(modelPath, modelData, modelSize);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "read model file failed, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     return LoadModel(modelData, modelSize);
 | ||
| }
 | ||
| 
 | ||
| #ifdef USE_DCMI_INTERFACE
 | ||
| void ModelProcess::SetConsoleDispMode(int fd, int option)
 | ||
| {
 | ||
|     struct termios term;
 | ||
|     if (tcgetattr(fd, &term) == -1)
 | ||
|     {
 | ||
|         LogWarn << "Failed to get the attribution of the terminal, errno=" << errno << ".";
 | ||
|         return;
 | ||
|     }
 | ||
| 
 | ||
|     const tcflag_t echoFlags = (ECHO | ECHOE | ECHOK | ECHONL);
 | ||
|     if (option)
 | ||
|     {
 | ||
|         term.c_lflag |= echoFlags;
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         term.c_lflag &= ~echoFlags;
 | ||
|     }
 | ||
|     int err = tcsetattr(fd, TCSAFLUSH, &term);
 | ||
|     if ((err == -1) || (err == EINTR))
 | ||
|     {
 | ||
|         LogWarn << "Failed to set the attribution of the terminal, errno=" << errno << ".";
 | ||
|         return;
 | ||
|     }
 | ||
|     return;
 | ||
| }
 | ||
| 
 | ||
| /*
 | ||
|  * @description: Get id and password of secret key encrypted information
 | ||
|  * @return: APP_ERR_OK success
 | ||
|  * @return: Other values failure
 | ||
|  * @attention: This function needs to be implemented by users.
 | ||
|  */
 | ||
| APP_ERROR ModelProcess::GetKeyIdPassword(unsigned int &id, unsigned char password[], unsigned int &passwordLen) const
 | ||
| {
 | ||
|     LogInfo << "This function should be implemented by users.";
 | ||
| 
 | ||
|     LogInfo << "Please input secret key encryped index:";
 | ||
|     while (1)
 | ||
|     {
 | ||
|         std::cin >> id;
 | ||
|         if (std::cin.rdstate() == std::ios::goodbit)
 | ||
|         {
 | ||
|             // Clear newline character
 | ||
|             std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
 | ||
|             break;
 | ||
|         }
 | ||
|         // Clear the cin state and buffer to receive the next input
 | ||
|         std::cin.clear();
 | ||
|         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
 | ||
|         LogInfo << "Input error, please input secret key encryped index again:";
 | ||
|     }
 | ||
| 
 | ||
|     LogInfo << "Please input secret key encryped password:";
 | ||
|     // Disable the terminal display when entering the password
 | ||
|     SetConsoleDispMode(STDIN_FILENO, 0);
 | ||
|     std::cin.get(reinterpret_cast<char *>(password), MAX_ENCODE_LEN);
 | ||
|     // Enable the terminal display when entering the password
 | ||
|     SetConsoleDispMode(STDIN_FILENO, 1);
 | ||
|     passwordLen = strlen(reinterpret_cast<char *>(password));
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR ModelProcess::Init(const std::string &modelPath, bool isEncrypted, int cardId, int deviceId)
 | ||
| {
 | ||
|     if (!isEncrypted)
 | ||
|     {
 | ||
|         return Init(modelPath);
 | ||
|     }
 | ||
| 
 | ||
|     LogInfo << "ModelProcess:Begin to init instance.";
 | ||
|     int modelSize = 0;
 | ||
|     std::shared_ptr<uint8_t> modelData = nullptr;
 | ||
| 
 | ||
|     // modelPath should point to an encrypted model when isEncrypted is true
 | ||
|     APP_ERROR ret = ReadBinaryFile(modelPath, modelData, modelSize);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "Failed to read model file, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     // Users need to implement this function as required
 | ||
|     ret = GetKeyIdPassword(encryptModelData_.id, encryptModelData_.password, encryptModelData_.password_len);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     ret = dcmi_init();
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "Failed to initialize dcmi, ret = " << ret << ".";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     // Read secret key from dcmi
 | ||
|     ret = dcmi_get_ai_model_info(cardId, deviceId, &encryptModelData_);
 | ||
|     if (ret != APP_ERR_OK)
 | ||
|     {
 | ||
|         LogError << "Failed to get model info from dcmi, ret[" << ret << "].";
 | ||
|         return ret;
 | ||
|     }
 | ||
| 
 | ||
|     // Clear password immediately after use
 | ||
|     aclrtMemset(encryptModelData_.password, sizeof(encryptModelData_.password), 0, sizeof(encryptModelData_.password));
 | ||
|     LogInfo << "Users need to decrypt model before the next operation.";
 | ||
| 
 | ||
|     // User should modify the decryptedModelData and encryptedModelSize according to the actual situation
 | ||
|     std::shared_ptr<uint8_t> decryptedModelData = modelData;
 | ||
|     int encryptedModelSize = modelSize;
 | ||
| 
 | ||
|     // Load decrypted model
 | ||
|     return LoadModel(decryptedModelData, encryptedModelSize);
 | ||
| }
 | ||
| #endif
 | ||
| 
 | ||
| aclmdlDataset *ModelProcess::CreateAndFillDataset(const std::vector<void *> &bufs, const std::vector<size_t> &sizes)
 | ||
|     const
 | ||
| {
 | ||
|     APP_ERROR ret = APP_ERR_OK;
 | ||
|     aclmdlDataset *dataset = aclmdlCreateDataset();
 | ||
|     if (dataset == nullptr)
 | ||
|     {
 | ||
|         LogError << "ACL_ModelInputCreate failed.";
 | ||
|         return nullptr;
 | ||
|     }
 | ||
| 
 | ||
|     for (size_t i = 0; i < bufs.size(); ++i)
 | ||
|     {
 | ||
|         aclDataBuffer *data = aclCreateDataBuffer(bufs[i], sizes[i]);
 | ||
|         if (data == nullptr)
 | ||
|         {
 | ||
|             DestroyDataset(dataset);
 | ||
|             LogError << "aclCreateDataBuffer failed.";
 | ||
|             return nullptr;
 | ||
|         }
 | ||
| 
 | ||
|         ret = aclmdlAddDatasetBuffer(dataset, data);
 | ||
|         if (ret != APP_ERR_OK)
 | ||
|         {
 | ||
|             DestroyDataset(dataset);
 | ||
|             LogError << "ACL_ModelInputDataAdd failed, ret[" << ret << "].";
 | ||
|             return nullptr;
 | ||
|         }
 | ||
|     }
 | ||
|     return dataset;
 | ||
| }
 | ||
| 
 | ||
| size_t ModelProcess::GetModelNumInputs() const
 | ||
| {
 | ||
|     return aclmdlGetNumInputs(modelDesc_.get());
 | ||
| }
 | ||
| 
 | ||
| size_t ModelProcess::GetModelNumOutputs() const
 | ||
| {
 | ||
|     return aclmdlGetNumOutputs(modelDesc_.get());
 | ||
| }
 | ||
| 
 | ||
| size_t ModelProcess::GetModelInputSizeByIndex(const size_t &i) const
 | ||
| {
 | ||
|     return aclmdlGetInputSizeByIndex(modelDesc_.get(), i);
 | ||
| }
 | ||
| 
 | ||
| size_t ModelProcess::GetModelOutputSizeByIndex(const size_t &i) const
 | ||
| {
 | ||
|     return aclmdlGetOutputSizeByIndex(modelDesc_.get(), i);
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR ModelProcess::InputBufferWithSizeMalloc(aclrtMemMallocPolicy policy)
 | ||
| {
 | ||
|     size_t inputNum = aclmdlGetNumInputs(modelDesc_.get());
 | ||
|     LogDebug << modelName_ << "model inputNum is : " << inputNum << ".";
 | ||
|     for (size_t i = 0; i < inputNum; ++i)
 | ||
|     {
 | ||
|         void *buffer = nullptr;
 | ||
|         // modify size
 | ||
|         size_t size = aclmdlGetInputSizeByIndex(modelDesc_.get(), i);
 | ||
|         APP_ERROR ret = aclrtMalloc(&buffer, size, policy);
 | ||
|         if (ret != APP_ERR_OK)
 | ||
|         {
 | ||
|             LogFatal << modelName_ << "model input aclrtMalloc fail(ret=" << ret
 | ||
|                      << "), buffer=" << buffer << ", size=" << size << ".";
 | ||
|             // Free the buffer malloced successfully before return error
 | ||
|             ReleaseModelBuffer(inputBuffers_);
 | ||
|             return ret;
 | ||
|         }
 | ||
|         inputBuffers_.push_back(buffer);
 | ||
|         inputSizes_.push_back(size);
 | ||
|         LogDebug << modelName_ << "model inputBuffer i=" << i << ", size=" << size << ".";
 | ||
|     }
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| APP_ERROR ModelProcess::OutputBufferWithSizeMalloc(aclrtMemMallocPolicy policy)
 | ||
| {
 | ||
|     size_t outputNum = aclmdlGetNumOutputs(modelDesc_.get());
 | ||
|     LogDebug << modelName_ << "model outputNum is : " << outputNum << ".";
 | ||
|     for (size_t i = 0; i < outputNum; ++i)
 | ||
|     {
 | ||
|         void *buffer = nullptr;
 | ||
|         // modify size
 | ||
| 
 | ||
|         size_t size = aclmdlGetOutputSizeByIndex(modelDesc_.get(), i);
 | ||
|         APP_ERROR ret = aclrtMalloc(&buffer, size, policy);
 | ||
|         if (ret != APP_ERR_OK)
 | ||
|         {
 | ||
|             LogFatal << modelName_ << "model output aclrtMalloc fail(ret=" << ret
 | ||
|                      << "), buffer=" << buffer << ", size=" << size << ".";
 | ||
|             // Free the buffer malloced successfully before return error
 | ||
|             ReleaseModelBuffer(outputBuffers_);
 | ||
|             return ret;
 | ||
|         }
 | ||
|         outputBuffers_.push_back(buffer);
 | ||
|         outputSizes_.push_back(size);
 | ||
|         LogDebug << modelName_ << "," << aclmdlGetOutputNameByIndex(modelDesc_.get(), i) << ",model outputBuffer i=" << i << ", size=" << size << ".";
 | ||
|     }
 | ||
|     return APP_ERR_OK;
 | ||
| }
 | ||
| 
 | ||
| void ModelProcess::ReleaseModelBuffer(std::vector<void *> &modelBuffers) const
 | ||
| {
 | ||
|     for (size_t i = 0; i < modelBuffers.size(); i++)
 | ||
|     {
 | ||
|         if (modelBuffers[i] != nullptr)
 | ||
|         {
 | ||
|             aclrtFree(modelBuffers[i]);
 | ||
|             modelBuffers[i] = nullptr;
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| void ModelProcess::SetModelWH(uint32_t width, uint32_t height)
 | ||
| {
 | ||
|     modelWidth_ = width;
 | ||
|     modelHeight_ = height;
 | ||
| }
 |