From f7cd15e0d9e51cf6daf3de46f71c338f806d7a84 Mon Sep 17 00:00:00 2001 From: zhang__sss Date: Sat, 8 May 2021 18:02:59 +0800 Subject: [PATCH] ascend310_infer --- model_zoo/official/cv/lenet_quant/Readme.md | 33 ++ .../official/cv/lenet_quant/Readme_CN.md | 35 +- .../ascend310_infer/inc/ModelProcess.h | 112 ++++++ .../ascend310_infer/inc/SampleProcess.h | 62 ++++ .../lenet_quant/ascend310_infer/inc/utils.h | 53 +++ .../ascend310_infer/src/CMakeLists.txt | 41 +++ .../ascend310_infer/src/ModelProcess.cpp | 326 +++++++++++++++++ .../ascend310_infer/src/SampleProcess.cpp | 199 +++++++++++ .../lenet_quant/ascend310_infer/src/acl.json | 1 + .../lenet_quant/ascend310_infer/src/build.sh | 55 +++ .../lenet_quant/ascend310_infer/src/main.cpp | 58 +++ .../lenet_quant/ascend310_infer/src/utils.cpp | 113 ++++++ .../cv/lenet_quant/export_bin_file.py | 63 ++++ .../official/cv/lenet_quant/postprocess.py | 57 +++ .../cv/lenet_quant/scripts/run_infer_310.sh | 107 ++++++ .../cv/mobilenetv2_quant/README_CN.md | 26 ++ .../official/cv/mobilenetv2_quant/Readme.md | 28 +- .../ascend310_infer/inc/ModelProcess.h | 112 ++++++ .../ascend310_infer/inc/SampleProcess.h | 62 ++++ .../ascend310_infer/inc/utils.h | 53 +++ .../ascend310_infer/src/CMakeLists.txt | 41 +++ .../ascend310_infer/src/ModelProcess.cpp | 326 +++++++++++++++++ .../ascend310_infer/src/SampleProcess.cpp | 199 +++++++++++ .../ascend310_infer/src/acl.json | 1 + .../ascend310_infer/src/build.sh | 55 +++ .../ascend310_infer/src/main.cpp | 58 +++ .../ascend310_infer/src/utils.cpp | 113 ++++++ .../cv/mobilenetv2_quant/export_bin_file.py | 65 ++++ .../cv/mobilenetv2_quant/postprocess.py | 57 +++ .../scripts/run_infer_310.sh | 107 ++++++ .../official/cv/resnet50_quant/README.md | 34 ++ .../official/cv/resnet50_quant/README_CN.md | 34 ++ .../ascend310_infer/inc/ModelProcess.h | 112 ++++++ .../ascend310_infer/inc/SampleProcess.h | 62 ++++ .../ascend310_infer/inc/utils.h | 53 +++ .../ascend310_infer/src/CMakeLists.txt | 41 +++ .../ascend310_infer/src/ModelProcess.cpp | 326 +++++++++++++++++ .../ascend310_infer/src/SampleProcess.cpp | 199 +++++++++++ .../ascend310_infer/src/acl.json | 1 + .../ascend310_infer/src/build.sh | 55 +++ .../ascend310_infer/src/main.cpp | 58 +++ .../ascend310_infer/src/utils.cpp | 113 ++++++ .../cv/resnet50_quant/export_bin_file.py | 64 ++++ .../official/cv/resnet50_quant/postprocess.py | 57 +++ .../resnet50_quant/scripts/run_infer_310.sh | 107 ++++++ .../cv/yolov3_darknet53_quant/README.md | 46 +++ .../cv/yolov3_darknet53_quant/README_CN.md | 48 ++- .../ascend310_infer/inc/ModelProcess.h | 114 ++++++ .../ascend310_infer/inc/SampleProcess.h | 62 ++++ .../ascend310_infer/inc/utils.h | 53 +++ .../ascend310_infer/src/CMakeLists.txt | 42 +++ .../ascend310_infer/src/ModelProcess.cpp | 337 ++++++++++++++++++ .../ascend310_infer/src/SampleProcess.cpp | 214 +++++++++++ .../ascend310_infer/src/acl.json | 1 + .../ascend310_infer/src/build.sh | 55 +++ .../ascend310_infer/src/main.cpp | 58 +++ .../ascend310_infer/src/utils.cpp | 113 ++++++ .../yolov3_darknet53_quant/export_bin_file.py | 111 ++++++ .../cv/yolov3_darknet53_quant/postprocess.py | 66 ++++ .../scripts/run_infer_310.sh | 114 ++++++ 60 files changed, 5365 insertions(+), 3 deletions(-) create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/inc/ModelProcess.h create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/inc/SampleProcess.h create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/inc/utils.h create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/CMakeLists.txt create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/ModelProcess.cpp create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/SampleProcess.cpp create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/acl.json create mode 100755 model_zoo/official/cv/lenet_quant/ascend310_infer/src/build.sh create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/main.cpp create mode 100644 model_zoo/official/cv/lenet_quant/ascend310_infer/src/utils.cpp create mode 100644 model_zoo/official/cv/lenet_quant/export_bin_file.py create mode 100644 model_zoo/official/cv/lenet_quant/postprocess.py create mode 100644 model_zoo/official/cv/lenet_quant/scripts/run_infer_310.sh create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/ModelProcess.h create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/SampleProcess.h create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/utils.h create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/CMakeLists.txt create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/ModelProcess.cpp create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/SampleProcess.cpp create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/acl.json create mode 100755 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/build.sh create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/main.cpp create mode 100644 model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/utils.cpp create mode 100644 model_zoo/official/cv/mobilenetv2_quant/export_bin_file.py create mode 100644 model_zoo/official/cv/mobilenetv2_quant/postprocess.py create mode 100644 model_zoo/official/cv/mobilenetv2_quant/scripts/run_infer_310.sh create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/ModelProcess.h create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/SampleProcess.h create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/utils.h create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/CMakeLists.txt create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/ModelProcess.cpp create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/SampleProcess.cpp create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/acl.json create mode 100755 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/build.sh create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/main.cpp create mode 100644 model_zoo/official/cv/resnet50_quant/ascend310_infer/src/utils.cpp create mode 100644 model_zoo/official/cv/resnet50_quant/export_bin_file.py create mode 100644 model_zoo/official/cv/resnet50_quant/postprocess.py create mode 100644 model_zoo/official/cv/resnet50_quant/scripts/run_infer_310.sh create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/ModelProcess.h create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/SampleProcess.h create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/utils.h create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/CMakeLists.txt create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/ModelProcess.cpp create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/SampleProcess.cpp create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/acl.json create mode 100755 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/build.sh create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/main.cpp create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/utils.cpp create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/export_bin_file.py create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/postprocess.py create mode 100644 model_zoo/official/cv/yolov3_darknet53_quant/scripts/run_infer_310.sh diff --git a/model_zoo/official/cv/lenet_quant/Readme.md b/model_zoo/official/cv/lenet_quant/Readme.md index d70dcb420d2..993b0ee132f 100644 --- a/model_zoo/official/cv/lenet_quant/Readme.md +++ b/model_zoo/official/cv/lenet_quant/Readme.md @@ -84,6 +84,9 @@ python eval.py --device_target=Ascend --data_path=[DATA_PATH] --ckpt_path=[CKPT_ ├── README.md // descriptions about all the models ├── lenet_quant ├── README.md // descriptions about LeNet-Quant + ├── ascend310_infer // application for 310 inference + ├── scripts + ├── run_infer_310.sh // shell script for 310 inference ├── src │ ├── config.py // parameter configuration │ ├── dataset.py // creating dataset @@ -93,6 +96,8 @@ python eval.py --device_target=Ascend --data_path=[DATA_PATH] --ckpt_path=[CKPT_ ├── requirements.txt // package needed ├── train.py // training LeNet-Quant network with device Ascend ├── eval.py // evaluating LeNet-Quant network with device Ascend + ├── export_bin_file.py // export bin file of MNIST for 310 inference + ├── postprocess.py // post process for 310 inference ``` ## [Script Parameters](#contents) @@ -152,6 +157,34 @@ You can view the results through the file "log.txt". The accuracy of the test da 'Accuracy': 0.9842 ``` +## [Model Export](#contents) + +```shell +python export.py --ckpt_path [CKPT_PATH] --data_path [DATA_PATH] --device_target [PLATFORM] +``` + +## [Ascend 310 inference](#contents) + +You should export AIR model at Ascend 910 before running the command below. +You can use export_bin_file.py to export MNIST bin and label for 310 inference. + +```shell +python export_bin_file.py --dataset_dir [DATASET_PATH] --save_dir [SAVE_PATH] +``` + +Run run_infer_310.sh and get the accuracy: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +You can view the results through the file "acc.log". The accuracy of the test dataset will be as follows: + +```bash +'Accuracy':0.9883 +``` + ## [Model Description](#contents) ### [Performance](#contents) diff --git a/model_zoo/official/cv/lenet_quant/Readme_CN.md b/model_zoo/official/cv/lenet_quant/Readme_CN.md index 52a20303cd4..23645dbc89d 100644 --- a/model_zoo/official/cv/lenet_quant/Readme_CN.md +++ b/model_zoo/official/cv/lenet_quant/Readme_CN.md @@ -90,6 +90,9 @@ python eval.py --device_target=Ascend --data_path=[DATA_PATH] --ckpt_path=[CKPT_ ├── README.md // 所有型号的描述 ├── lenet_quant ├── README.md // LeNet-Quant描述 + ├── ascend310_infer //实现310推理源代码 + ├── scripts + ├── run_infer_310.sh // Ascend推理shell脚本 ├──src │ ├── config.py // 参数配置 │ ├── dataset.py // 创建数据集 @@ -98,7 +101,9 @@ python eval.py --device_target=Ascend --data_path=[DATA_PATH] --ckpt_path=[CKPT_ │ ├── loss_monitor.py // 监控网络损失和其他数据 ├── requirements.txt // 需要的包 ├── train.py // 使用Ascend训练LeNet-Quant网络 - ├── eval.py // 使用Ascend评估LeNet-Quant网络d + ├── eval.py // 使用Ascend评估LeNet-Quant网络 + ├── export_bin_file.py // 导出MNIST数据集的bin文件用于310推理 + ├── postprocess.py // 310推理后处理脚本 ``` ### 脚本参数 @@ -156,6 +161,34 @@ python eval.py --data_path Data --ckpt_path ckpt/checkpoint_lenet-1_937.ckpt > l 'Accuracy':0.9842 ``` +### 模型导出 + +```shell +python export.py --ckpt_path [CKPT_PATH] --data_path [DATA_PATH] --device_target [PLATFORM] +``` + +### Ascend 310推理 + +在推理之前需要在昇腾910环境上完成AIR模型的导出。 +并使用export_bin_file.py导出MNIST数据集的bin文件和对应的label文件: + +```shell +python export_bin_file.py --dataset_dir [DATASET_PATH] --save_dir [SAVE_PATH] +``` + +执行推理并得到推理精度: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +您可以通过acc.log文件查看结果。推理准确性如下: + +```bash +'Accuracy':0.9883 +``` + ## 模型描述 ### 性能 diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/ModelProcess.h b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/ModelProcess.h new file mode 100644 index 00000000000..9acb683bee2 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/ModelProcess.h @@ -0,0 +1,112 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MODELPROCESS_H +#define MODELPROCESS_H + +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* 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(); + + /** + * @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(); + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief dump model output result to file + */ + void DumpModelOutputResult(char *output_name); + + /** + * @brief get model output result + */ + void OutputModelResult(); + + private: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; +#endif diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/SampleProcess.h b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/SampleProcess.h new file mode 100644 index 00000000000..30a77f4248c --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/SampleProcess.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLEPROCESS_H +#define SAMPLEPROCESS_H + +#include +#include +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* SampleProcess +*/ +class SampleProcess { + public: + /** + * @brief Constructor + */ + explicit SampleProcess(int32_t deviceId); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(const char *acl_config_path); + + /** + * @brief sample process + * @return result + */ + Result Process(const char *om_path, const char *input_folder); + + void GetAllFiles(std::string path, std::vector *files); + + private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + +#endif diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/utils.h b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/utils.h new file mode 100644 index 00000000000..b21e418a1f4 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/inc/utils.h @@ -0,0 +1,53 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_INFERENCE_UTILS_H_ +#define MINDSPORE_INFERENCE_UTILS_H_ + +#include +#include + +#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) +#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +/** +* Utils +*/ +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 Read bin 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); +}; +#endif diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/src/CMakeLists.txt b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/CMakeLists.txt new file mode 100644 index 00000000000..a8c1eb0fd33 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) +# project information +project(InferClassification) +# Check environment variable +if(NOT DEFINED ENV{ASCEND_HOME}) + message(FATAL_ERROR "please define environment variable:ASCEND_HOME") +endif() + +# Compile options +add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined") + +# Skip build rpath +set(CMAKE_SKIP_BUILD_RPATH True) + +# Set output directory +set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/out) + +# Set include directory and library directory +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib) +set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib) + +# Header path +include_directories(${ACL_LIB_DIR}/include/) +include_directories(${ATLAS_ACL_LIB_DIR}/include/) +include_directories(${PROJECT_SRC_ROOT}/../inc) + +# add host lib path +link_directories(${ACL_LIB_DIR}) +find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64) + +add_executable(main utils.cpp + SampleProcess.cpp + ModelProcess.cpp + main.cpp) + +target_link_libraries(main ${acl} gflags pthread) diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/src/ModelProcess.cpp b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/ModelProcess.cpp new file mode 100644 index 00000000000..5586ebbd9f9 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/ModelProcess.cpp @@ -0,0 +1,326 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/ModelProcess.h" +#include +#include +#include +#include +#include "../inc/utils.h" + +extern bool g_isDevice; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) { +} + +ModelProcess::~ModelProcess() { + Unload(); + DestroyDesc(); + DestroyInput(); + DestroyOutput(); +} + +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; + } + + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST); + 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; + } + + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + 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 output 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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(char *output_name) { + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + std::string homePath = "./result_Files"; + for (size_t i = 0; i < outputNum; ++i) { + std::string fileName = std::string(output_name) + '_' + std::to_string(i) + ".bin"; + std::string outputFileName = homePath + "/" + fileName; + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(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() { + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(dataBuffer); + void *outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + float *outData = NULL; + 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); + return; + } + outData = reinterpret_cast(outHostData); + } else { + outData = reinterpret_cast(data); + } + std::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); + } + if (!g_isDevice) { + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + } + INFO_LOG("output data success"); + return; +} + +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() { + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError 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/model_zoo/official/cv/lenet_quant/ascend310_infer/src/SampleProcess.cpp b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/SampleProcess.cpp new file mode 100644 index 00000000000..658e24251df --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/SampleProcess.cpp @@ -0,0 +1,199 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/SampleProcess.h" +#include +#include +#include +#include +#include +#include "../inc/utils.h" +#include "../inc/ModelProcess.h" +#include "acl/acl.h" + +extern bool g_isDevice; +using std::string; +using std::vector; + +SampleProcess::SampleProcess(int32_t deviceId) : context_(nullptr), stream_(nullptr) { + deviceId_ = deviceId; +} + +SampleProcess::~SampleProcess() { + DestroyResource(); +} + +Result SampleProcess::InitResource(const char *aclConfigPath) { + // ACL init + 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"); + return SUCCESS; +} + +void SampleProcess::GetAllFiles(std::string path, std::vector *files) { + DIR *pDir; + struct dirent* ptr; + if (!(pDir = opendir(path.c_str()))) + return; + while ((ptr = readdir(pDir)) != 0) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) + files->push_back(path + "/" + ptr->d_name); + } + closedir(pDir); +} + +Result SampleProcess::Process(const char *om_path, const char *input_folder) { + // model init + ModelProcess processModel; + + Result ret = processModel.LoadModelFromFileWithMem(om_path); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModelFromFileWithMem failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateDesc failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateOutput failed"); + return FAILED; + } + + std::vector testFile; + GetAllFiles(input_folder, &testFile); + + if (testFile.size() == 0) { + WARN_LOG("no input data under folder"); + } + + // loop begin + for (size_t index = 0; index < testFile.size(); ++index) { + INFO_LOG("start to process file:%s", testFile[index].c_str()); + // model process + uint32_t devBufferSize; + void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); + return FAILED; + } + ret = processModel.CreateInput(picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateInput failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("execute inference failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + int pos = testFile[index].find_last_of('/'); + std::string name = testFile[index].substr(pos+1); + std::string outputname = name.substr(0, name.rfind(".")); + + // print the top 5 confidence values + processModel.OutputModelResult(); + // dump output result to file in the current directory + processModel.DumpModelOutputResult(const_cast(outputname.c_str())); + + // release model input buffer + aclrtFree(picDevBuffer); + processModel.DestroyInput(); + } + // loop end + + 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/model_zoo/official/cv/lenet_quant/ascend310_infer/src/acl.json b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/acl.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/acl.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/src/build.sh b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/build.sh new file mode 100755 index 00000000000..b5979b68e60 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +path_cur=$(cd "`dirname $0`" || exit; pwd) + +function preparePath() { + rm -rf $1 + mkdir -p $1 + cd $1 || exit +} + +function buildA300() { + if [ ! "${ARCH_PATTERN}" ]; then + # set ARCH_PATTERN to acllib when it was not specified by user + export ARCH_PATTERN=acllib + echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}" + else + echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib" + export ARCH_PATTERN=${ARCH_PATTERN}/acllib + fi + + path_build=$path_cur/build + preparePath $path_build + cmake .. + make -j + ret=$? + cd .. + return ${ret} +} + +# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user +if [ ! "${ASCEND_VERSION}" ]; then + export ASCEND_VERSION=ascend-toolkit/latest + echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}" +else + echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user" +fi + +buildA300 + +if [ $? -ne 0 ]; then + exit 1 +fi diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/src/main.cpp b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/main.cpp new file mode 100644 index 00000000000..ca47f0635ef --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/main.cpp @@ -0,0 +1,58 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "../inc/SampleProcess.h" +#include "../inc/utils.h" + +bool g_isDevice = false; + +DEFINE_string(om_path, "", "om path"); +DEFINE_string(dataset_path, "", "dataset path"); +DEFINE_string(acljson_path, "", "acl json path"); +DEFINE_int32(device_id, 0, "device id"); + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + std::string om_path = FLAGS_om_path; + std::string dataset_path = FLAGS_dataset_path; + std::string acljson_path = FLAGS_acljson_path; + int32_t device_id = FLAGS_device_id; + std::ifstream fin(om_path); + if (!fin) { + std::cout << "Invalid om path." << std::endl; + return FAILED; + } + SampleProcess processSample(device_id); + // acl.json is deployed for dump data. + Result ret = processSample.InitResource(acljson_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + ret = processSample.Process(om_path.c_str(), dataset_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + + INFO_LOG("execute sample success"); + return SUCCESS; +} diff --git a/model_zoo/official/cv/lenet_quant/ascend310_infer/src/utils.cpp b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/utils.cpp new file mode 100644 index 00000000000..6e669f3f329 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/ascend310_infer/src/utils.cpp @@ -0,0 +1,113 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/utils.h" +#include +#include +#include +#include +#include "acl/acl.h" + +extern bool g_isDevice; + +void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) { + struct stat sBuf; + int fileStatus = stat(fileName.data(), &sBuf); + if (fileStatus == -1) { + ERROR_LOG("failed to get file"); + return nullptr; + } + if (S_ISREG(sBuf.st_mode) == 0) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return nullptr; + } + + 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; + } + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc for binFileBufferData failed"); + binFile.close(); + return nullptr; + } + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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; + } +} diff --git a/model_zoo/official/cv/lenet_quant/export_bin_file.py b/model_zoo/official/cv/lenet_quant/export_bin_file.py new file mode 100644 index 00000000000..428d4545178 --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/export_bin_file.py @@ -0,0 +1,63 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +export mnist dataset to bin. +""" +import os +import argparse +from mindspore import context +from src.dataset import create_dataset + +def parse_args(): + parser = argparse.ArgumentParser(description='MNIST to bin') + parser.add_argument('--device_target', type=str, default="Ascend", + choices=['Ascend', 'GPU'], + help='device where the code will be implemented (default: Ascend)') + parser.add_argument('--dataset_dir', type=str, default='', help='dataset path') + parser.add_argument('--save_dir', type=str, default='', help='path to save bin file') + parser.add_argument('--batch_size', type=int, default=1, help='batch size for bin') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + os.environ["RANK_SIZE"] = '1' + os.environ["RANK_ID"] = '0' + device_id = int(os.getenv('DEVICE_ID')) if os.getenv('DEVICE_ID') else 0 + context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target, device_id=device_id) + mnist_path = os.path.join(args.dataset_dir, 'test') + batch_size = args.batch_size + save_dir = os.path.join(args.save_dir, 'lenet_quant_mnist_310_infer_data') + folder = os.path.join(save_dir, 'mnist_bs_' + str(batch_size) + '_bin') + if not os.path.exists(folder): + os.makedirs(folder) + ds = create_dataset(mnist_path, batch_size) + iter_num = 0 + label_file = os.path.join(save_dir, './mnist_bs_' + str(batch_size) + '_label.txt') + with open(label_file, 'w') as f: + for data in ds.create_dict_iterator(): + image = data['image'] + label = data['label'] + file_name = "mnist_" + str(iter_num) + ".bin" + file_path = folder + "/" + file_name + image.asnumpy().tofile(file_path) + f.write(file_name) + for i in label: + f.write(',' + str(i)) + f.write('\n') + iter_num += 1 + print("=====iter_num:{}=====".format(iter_num)) + print("=====image_data:{}=====".format(image)) + print("=====label_data:{}=====".format(label)) diff --git a/model_zoo/official/cv/lenet_quant/postprocess.py b/model_zoo/official/cv/lenet_quant/postprocess.py new file mode 100644 index 00000000000..91f497a27fa --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/postprocess.py @@ -0,0 +1,57 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +post process for 310 inference. +""" +import os +import argparse +import numpy as np + +def parse_args(): + parser = argparse.ArgumentParser(description='lenet_quant inference') + parser.add_argument('--result_path', type=str, default='', help='result files path') + parser.add_argument('--label_path', type=str, default='', help='label file path') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + path = args.result_path + label_path = args.label_path + files = os.listdir(path) + step = 0 + sum_right = 0 + label_dict = {} + with open(label_path, 'r') as f: + for line in f.readlines(): + batch_label = line.strip().split(',') + label_dict[batch_label[0]] = batch_label[1:] + for file in files: + full_file_path = os.path.join(path, file) + if os.path.isfile(full_file_path): + label_file = file.split('_0.bin')[0] + '.bin' + label_array = np.array(label_dict[label_file]) + line = np.fromfile(full_file_path, dtype=np.float32) + batch_size = label_array.shape[0] + line_comp = line.reshape(batch_size, int(line.shape[0] / batch_size)) + for i in range(0, batch_size): + pred = np.argmax(line_comp[i], axis=0) + step += 1 + if pred == label_array[i].astype(np.int64): + sum_right += 1 + print("=====step:{}=====".format(step)) + print("=====sum_right:{}=====".format(sum_right)) + accuracy = sum_right * 100.0 / step + print("=====accuracy:{}=====".format(accuracy)) diff --git a/model_zoo/official/cv/lenet_quant/scripts/run_infer_310.sh b/model_zoo/official/cv/lenet_quant/scripts/run_infer_310.sh new file mode 100644 index 00000000000..b6d527c9a0c --- /dev/null +++ b/model_zoo/official/cv/lenet_quant/scripts/run_infer_310.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +if [[ $# -lt 3 || $# -gt 4 ]]; then + echo "Usage: bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] + DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero" +exit 1 +fi + +get_real_path(){ + if [ "${1:0:1}" == "/" ]; then + echo "$1" + else + echo "$(realpath -m $PWD/$1)" + fi +} +model=$(get_real_path $1) +data_path=$(get_real_path $2) +label_path=$(get_real_path $3) + +device_id=0 +if [ $# == 4 ]; then + device_id=$4 +fi + +echo "mindir name: "$model +echo "dataset path: "$data_path +echo "label path: "$label_path +echo "device id: "$device_id + +export ASCEND_HOME=/usr/local/Ascend/ +if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then + export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe + export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp +else + export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/opp +fi + +function air_to_om() +{ + atc --input_format=NCHW --framework=1 --model=$model --output=lenet_quant --soc_version=Ascend310 &> atc.log +} + +function compile_app() +{ + cd ../ascend310_infer/src || exit + bash build.sh &> build.log +} + +function infer() +{ + cd - || exit + if [ -d result_Files ]; then + rm -rf ./result_Files + fi + if [ -d time_Result ]; then + rm -rf ./time_Result + fi + mkdir result_Files + mkdir time_Result + ../ascend310_infer/src/out/main --om_path=./lenet_quant.om --dataset_path=$data_path --acljson_path=../ascend310_infer/src/acl.json --device_id=$device_id &> infer.log +} + +function cal_acc() +{ + python3.7 ../postprocess.py --result_path=./result_Files --label_path=$label_path &> acc.log +} + +air_to_om +if [ $? -ne 0 ]; then + echo " air to om failed" + exit 1 +fi +compile_app +if [ $? -ne 0 ]; then + echo "compile app code failed" + exit 1 +fi +infer +if [ $? -ne 0 ]; then + echo " execute inference failed" + exit 1 +fi +cal_acc +if [ $? -ne 0 ]; then + echo "calculate accuracy failed" + exit 1 +fi \ No newline at end of file diff --git a/model_zoo/official/cv/mobilenetv2_quant/README_CN.md b/model_zoo/official/cv/mobilenetv2_quant/README_CN.md index 34c4af3553d..e2ed3673f27 100644 --- a/model_zoo/official/cv/mobilenetv2_quant/README_CN.md +++ b/model_zoo/official/cv/mobilenetv2_quant/README_CN.md @@ -86,11 +86,13 @@ MobileNetV2总体网络架构如下: ```python ├── mobileNetv2_quant ├── Readme.md # MobileNetV2-Quant相关描述 + ├── ascend310_infer # 实现310推理源代码 ├── scripts │ ├──run_train.sh # 使用Ascend或GPU进行训练的shell脚本 │ ├──run_infer.sh # 使用Ascend或GPU进行评估的shell脚本 │ ├──run_lsq_train.sh # 使用Ascend或GPU进行LSQ训练的shell脚本 │ ├──run_lsq_infer.sh # 使用Ascend或GPU进行LSQ评估的shell脚本 + │ ├──run_infer_310.sh # Ascend 310 推理shell脚本 ├── src │ ├──config.py # 参数配置 │ ├──dataset.py # 创建数据集 @@ -101,6 +103,8 @@ MobileNetV2总体网络架构如下: ├── train.py # 训练脚本 ├── eval.py # 评估脚本 ├── export.py # 导出检查点文件到air/mindir中 + ├── export_bin_file.py # 导出ImageNet数据集的bin文件用于310推理 + ├── postprocess.py # 310推理后处理脚本 ``` ## 脚本参数 @@ -241,6 +245,28 @@ python export.py --checkpoint_path [CKPT_PATH] --file_format [EXPORT_FORMAT] --d `OptimizeOption` 可选 ["QAT", "LEARNED_SCALE"]. +## Ascend 310 推理 + +在推理之前需要在昇腾910环境上完成AIR模型的导出。 +并使用export_bin_file.py导出ImageNet数据集的bin文件和对应的label文件: + +```shell +python export_bin_file.py --dataset_dir [EVAL_DATASET_PATH] --save_dir [SAVE_PATH] +``` + +执行推理并得到推理精度: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +您可以通过acc.log文件查看结果。QAT量化推理准确性如下: + +```bash +'Accuracy':0.7221 +``` + # 模型描述 ## 性能 diff --git a/model_zoo/official/cv/mobilenetv2_quant/Readme.md b/model_zoo/official/cv/mobilenetv2_quant/Readme.md index 3e31b8b4657..280756fe0ff 100644 --- a/model_zoo/official/cv/mobilenetv2_quant/Readme.md +++ b/model_zoo/official/cv/mobilenetv2_quant/Readme.md @@ -73,11 +73,13 @@ Users are free to choose whether to use the LEARNED_SCALE optimize option for qu ```python ├── mobileNetv2_quant ├── Readme.md # descriptions about MobileNetV2-Quant + ├── ascend310_infer # application for 310 inference ├── scripts │ ├──run_train.sh # shell script for train on Ascend or GPU │ ├──run_infer.sh # shell script for evaluation on Ascend or GPU │ ├──run_lsq_train.sh # shell script for train (using the LEARNED_SCALE optimize option) on Ascend or GPU │ ├──run_lsq_infer.sh # shell script for evaluation (using the LEARNED_SCALE optimize option) on Ascend or GPU + │ ├──run_infer_310.sh # shell script for 310 inference ├── src │ ├──config.py # parameter configuration │ ├──dataset.py # creating dataset @@ -87,7 +89,9 @@ Users are free to choose whether to use the LEARNED_SCALE optimize option for qu │ ├──utils.py # supply the monitor module ├── train.py # training script ├── eval.py # evaluation script - ├── export.py # export checkpoint files into air/onnx + ├── export.py # export checkpoint files into air/mindir + ├── export_bin_file.py # export bin file of ImageNet for 310 inference + ├── postprocess.py # post process for 310 inference ``` ## [Script Parameters](#contents) @@ -231,6 +235,28 @@ python export.py --checkpoint_path [CKPT_PATH] --file_format [EXPORT_FORMAT] --d `EXPORT_FORMAT` should be in ["AIR", "MINDIR"]. `OptimizeOption` should be in ["QAT", "LEARNED_SCALE"]. +## [Ascend 310 inference](#contents) + +You should export AIR model at Ascend 910 before running the command below. +You can use export_bin_file.py to export ImageNet bin and label for 310 inference. + +```shell +python export_bin_file.py --dataset_dir [EVAL_DATASET_PATH] --save_dir [SAVE_PATH] +``` + +Run run_infer_310.sh and get the accuracy: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +You can view the results through the file "acc.log". The accuracy of the test dataset will be as follows: + +```bash +'Accuracy':0.7221 +``` + # [Model description](#contents) ## [Performance](#contents) diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/ModelProcess.h b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/ModelProcess.h new file mode 100644 index 00000000000..9acb683bee2 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/ModelProcess.h @@ -0,0 +1,112 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MODELPROCESS_H +#define MODELPROCESS_H + +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* 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(); + + /** + * @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(); + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief dump model output result to file + */ + void DumpModelOutputResult(char *output_name); + + /** + * @brief get model output result + */ + void OutputModelResult(); + + private: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; +#endif diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/SampleProcess.h b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/SampleProcess.h new file mode 100644 index 00000000000..30a77f4248c --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/SampleProcess.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLEPROCESS_H +#define SAMPLEPROCESS_H + +#include +#include +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* SampleProcess +*/ +class SampleProcess { + public: + /** + * @brief Constructor + */ + explicit SampleProcess(int32_t deviceId); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(const char *acl_config_path); + + /** + * @brief sample process + * @return result + */ + Result Process(const char *om_path, const char *input_folder); + + void GetAllFiles(std::string path, std::vector *files); + + private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + +#endif diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/utils.h b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/utils.h new file mode 100644 index 00000000000..b21e418a1f4 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/inc/utils.h @@ -0,0 +1,53 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_INFERENCE_UTILS_H_ +#define MINDSPORE_INFERENCE_UTILS_H_ + +#include +#include + +#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) +#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +/** +* Utils +*/ +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 Read bin 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); +}; +#endif diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/CMakeLists.txt b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/CMakeLists.txt new file mode 100644 index 00000000000..a8c1eb0fd33 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) +# project information +project(InferClassification) +# Check environment variable +if(NOT DEFINED ENV{ASCEND_HOME}) + message(FATAL_ERROR "please define environment variable:ASCEND_HOME") +endif() + +# Compile options +add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined") + +# Skip build rpath +set(CMAKE_SKIP_BUILD_RPATH True) + +# Set output directory +set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/out) + +# Set include directory and library directory +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib) +set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib) + +# Header path +include_directories(${ACL_LIB_DIR}/include/) +include_directories(${ATLAS_ACL_LIB_DIR}/include/) +include_directories(${PROJECT_SRC_ROOT}/../inc) + +# add host lib path +link_directories(${ACL_LIB_DIR}) +find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64) + +add_executable(main utils.cpp + SampleProcess.cpp + ModelProcess.cpp + main.cpp) + +target_link_libraries(main ${acl} gflags pthread) diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/ModelProcess.cpp b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/ModelProcess.cpp new file mode 100644 index 00000000000..5586ebbd9f9 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/ModelProcess.cpp @@ -0,0 +1,326 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/ModelProcess.h" +#include +#include +#include +#include +#include "../inc/utils.h" + +extern bool g_isDevice; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) { +} + +ModelProcess::~ModelProcess() { + Unload(); + DestroyDesc(); + DestroyInput(); + DestroyOutput(); +} + +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; + } + + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST); + 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; + } + + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + 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 output 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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(char *output_name) { + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + std::string homePath = "./result_Files"; + for (size_t i = 0; i < outputNum; ++i) { + std::string fileName = std::string(output_name) + '_' + std::to_string(i) + ".bin"; + std::string outputFileName = homePath + "/" + fileName; + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(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() { + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(dataBuffer); + void *outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + float *outData = NULL; + 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); + return; + } + outData = reinterpret_cast(outHostData); + } else { + outData = reinterpret_cast(data); + } + std::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); + } + if (!g_isDevice) { + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + } + INFO_LOG("output data success"); + return; +} + +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() { + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError 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/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/SampleProcess.cpp b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/SampleProcess.cpp new file mode 100644 index 00000000000..057f97f8624 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/SampleProcess.cpp @@ -0,0 +1,199 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/SampleProcess.h" +#include +#include +#include +#include +#include +#include "../inc/utils.h" +#include "../inc/ModelProcess.h" +#include "acl/acl.h" + +extern bool g_isDevice; +using std::string; +using std::vector; + +SampleProcess::SampleProcess(int32_t deviceId) : context_(nullptr), stream_(nullptr) { + deviceId_ = deviceId; +} + +SampleProcess::~SampleProcess() { + DestroyResource(); +} + +Result SampleProcess::InitResource(const char *aclConfigPath) { + // ACL init + 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"); + return SUCCESS; +} + +void SampleProcess::GetAllFiles(std::string path, std::vector *files) { + DIR *pDir; + struct dirent* ptr; + if (!(pDir = opendir(path.c_str()))) + return; + while ((ptr = readdir(pDir)) != 0) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) + files->push_back(path + "/" + ptr->d_name); + } + closedir(pDir); +} + +Result SampleProcess::Process(const char *om_path, const char *input_folder) { + // model init + ModelProcess processModel; + + Result ret = processModel.LoadModelFromFileWithMem(om_path); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModelFromFileWithMem failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateDesc failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateOutput failed"); + return FAILED; + } + + std::vector testFile; + GetAllFiles(input_folder, &testFile); + + if (testFile.size() == 0) { + WARN_LOG("no input data under folder"); + } + + // loop begin + for (size_t index = 0; index < testFile.size(); ++index) { + INFO_LOG("start to process file:%s", testFile[index].c_str()); + // model process + uint32_t devBufferSize; + void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); + return FAILED; + } + ret = processModel.CreateInput(picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateInput failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("execute inference failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + int pos = testFile[index].find_last_of('/'); + std::string name = testFile[index].substr(pos+1); + std::string outputname = name.substr(0, name.rfind(".")); + + // print the top 5 confidence values + processModel.OutputModelResult(); + // dump output result to file in the current directory + processModel.DumpModelOutputResult(const_cast(outputname.c_str())); + + // release model input buffer + aclrtFree(picDevBuffer); + processModel.DestroyInput(); + } + // loop end + + 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/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/acl.json b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/acl.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/acl.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/build.sh b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/build.sh new file mode 100755 index 00000000000..b5979b68e60 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +path_cur=$(cd "`dirname $0`" || exit; pwd) + +function preparePath() { + rm -rf $1 + mkdir -p $1 + cd $1 || exit +} + +function buildA300() { + if [ ! "${ARCH_PATTERN}" ]; then + # set ARCH_PATTERN to acllib when it was not specified by user + export ARCH_PATTERN=acllib + echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}" + else + echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib" + export ARCH_PATTERN=${ARCH_PATTERN}/acllib + fi + + path_build=$path_cur/build + preparePath $path_build + cmake .. + make -j + ret=$? + cd .. + return ${ret} +} + +# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user +if [ ! "${ASCEND_VERSION}" ]; then + export ASCEND_VERSION=ascend-toolkit/latest + echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}" +else + echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user" +fi + +buildA300 + +if [ $? -ne 0 ]; then + exit 1 +fi diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/main.cpp b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/main.cpp new file mode 100644 index 00000000000..ca47f0635ef --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/main.cpp @@ -0,0 +1,58 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "../inc/SampleProcess.h" +#include "../inc/utils.h" + +bool g_isDevice = false; + +DEFINE_string(om_path, "", "om path"); +DEFINE_string(dataset_path, "", "dataset path"); +DEFINE_string(acljson_path, "", "acl json path"); +DEFINE_int32(device_id, 0, "device id"); + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + std::string om_path = FLAGS_om_path; + std::string dataset_path = FLAGS_dataset_path; + std::string acljson_path = FLAGS_acljson_path; + int32_t device_id = FLAGS_device_id; + std::ifstream fin(om_path); + if (!fin) { + std::cout << "Invalid om path." << std::endl; + return FAILED; + } + SampleProcess processSample(device_id); + // acl.json is deployed for dump data. + Result ret = processSample.InitResource(acljson_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + ret = processSample.Process(om_path.c_str(), dataset_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + + INFO_LOG("execute sample success"); + return SUCCESS; +} diff --git a/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/utils.cpp b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/utils.cpp new file mode 100644 index 00000000000..6e669f3f329 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/ascend310_infer/src/utils.cpp @@ -0,0 +1,113 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/utils.h" +#include +#include +#include +#include +#include "acl/acl.h" + +extern bool g_isDevice; + +void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) { + struct stat sBuf; + int fileStatus = stat(fileName.data(), &sBuf); + if (fileStatus == -1) { + ERROR_LOG("failed to get file"); + return nullptr; + } + if (S_ISREG(sBuf.st_mode) == 0) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return nullptr; + } + + 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; + } + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc for binFileBufferData failed"); + binFile.close(); + return nullptr; + } + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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; + } +} diff --git a/model_zoo/official/cv/mobilenetv2_quant/export_bin_file.py b/model_zoo/official/cv/mobilenetv2_quant/export_bin_file.py new file mode 100644 index 00000000000..ef1e33d4a91 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/export_bin_file.py @@ -0,0 +1,65 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +export imagenet2012 dataset to bin. +""" +import os +import argparse +from mindspore import context +from src.dataset import create_dataset +from src.config import config_ascend_quant + +def parse_args(): + parser = argparse.ArgumentParser(description='ImageNet2012 to bin') + parser.add_argument('--device_target', type=str, default="Ascend", + choices=['Ascend', 'GPU'], + help='device where the code will be implemented (default: Ascend)') + parser.add_argument('--dataset_dir', type=str, default='', help='dataset path') + parser.add_argument('--save_dir', type=str, default='', help='path to save bin file') + parser.add_argument('--batch_size', type=int, default=1, help='batch size for bin') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + os.environ["RANK_SIZE"] = '1' + os.environ["RANK_ID"] = '0' + device_id = int(os.getenv('DEVICE_ID')) if os.getenv('DEVICE_ID') else 0 + context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target, device_id=device_id) + imagenet2012_path = args.dataset_dir + batch_size = args.batch_size + save_dir = os.path.join(args.save_dir, 'imagenet2012_310_infer_data') + folder = os.path.join(save_dir, 'imagenet2012_bs_' + str(batch_size) + '_bin') + if not os.path.exists(folder): + os.makedirs(folder) + ds = create_dataset(imagenet2012_path, do_train=False, config=config_ascend_quant, + device_target=args.device_target, repeat_num=1, batch_size=batch_size) + iter_num = 0 + label_file = os.path.join(save_dir, './imagenet2012_bs_' + str(batch_size) + '_label.txt') + with open(label_file, 'w') as f: + for data in ds.create_dict_iterator(): + image = data['image'] + label = data['label'] + file_name = "imagenet2012_" + str(iter_num) + ".bin" + file_path = folder + "/" + file_name + image.asnumpy().tofile(file_path) + f.write(file_name) + for i in label: + f.write(',' + str(i)) + f.write('\n') + iter_num += 1 + print("=====iter_num:{}=====".format(iter_num)) + print("=====image_data:{}=====".format(image)) + print("=====label_data:{}=====".format(label)) diff --git a/model_zoo/official/cv/mobilenetv2_quant/postprocess.py b/model_zoo/official/cv/mobilenetv2_quant/postprocess.py new file mode 100644 index 00000000000..101ef3e2d92 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/postprocess.py @@ -0,0 +1,57 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +post process for 310 inference. +""" +import os +import argparse +import numpy as np + +def parse_args(): + parser = argparse.ArgumentParser(description='mobilenetv2_quant inference') + parser.add_argument('--result_path', type=str, default='', help='result files path') + parser.add_argument('--label_path', type=str, default='', help='label file path') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + path = args.result_path + label_path = args.label_path + files = os.listdir(path) + step = 0 + sum_right = 0 + label_dict = {} + with open(label_path, 'r') as f: + for line in f.readlines(): + batch_label = line.strip().split(',') + label_dict[batch_label[0]] = batch_label[1:] + for file in files: + full_file_path = os.path.join(path, file) + if os.path.isfile(full_file_path): + label_file = file.split('_0.bin')[0] + '.bin' + label_array = np.array(label_dict[label_file]) + line = np.fromfile(full_file_path, dtype=np.float32) + batch_size = label_array.shape[0] + line_comp = line.reshape(batch_size, int(line.shape[0] / batch_size)) + for i in range(0, batch_size): + pred = np.argmax(line_comp[i], axis=0) + step += 1 + if pred == label_array[i].astype(np.int64): + sum_right += 1 + print("=====step:{}=====".format(step)) + print("=====sum_right:{}=====".format(sum_right)) + accuracy = sum_right * 100.0 / step + print("=====accuracy:{}=====".format(accuracy)) diff --git a/model_zoo/official/cv/mobilenetv2_quant/scripts/run_infer_310.sh b/model_zoo/official/cv/mobilenetv2_quant/scripts/run_infer_310.sh new file mode 100644 index 00000000000..14c991fd054 --- /dev/null +++ b/model_zoo/official/cv/mobilenetv2_quant/scripts/run_infer_310.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +if [[ $# -lt 3 || $# -gt 4 ]]; then + echo "Usage: bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] + DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero" +exit 1 +fi + +get_real_path(){ + if [ "${1:0:1}" == "/" ]; then + echo "$1" + else + echo "$(realpath -m $PWD/$1)" + fi +} +model=$(get_real_path $1) +data_path=$(get_real_path $2) +label_path=$(get_real_path $3) + +device_id=0 +if [ $# == 4 ]; then + device_id=$4 +fi + +echo "mindir name: "$model +echo "dataset path: "$data_path +echo "label path: "$label_path +echo "device id: "$device_id + +export ASCEND_HOME=/usr/local/Ascend/ +if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then + export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe + export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp +else + export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/opp +fi + +function air_to_om() +{ + atc --input_format=NCHW --framework=1 --model=$model --output=mobilenetv2_quant --soc_version=Ascend310 &> atc.log +} + +function compile_app() +{ + cd ../ascend310_infer/src || exit + bash build.sh &> build.log +} + +function infer() +{ + cd - || exit + if [ -d result_Files ]; then + rm -rf ./result_Files + fi + if [ -d time_Result ]; then + rm -rf ./time_Result + fi + mkdir result_Files + mkdir time_Result + ../ascend310_infer/src/out/main --om_path=./mobilenetv2_quant.om --dataset_path=$data_path --acljson_path=../ascend310_infer/src/acl.json --device_id=$device_id &> infer.log +} + +function cal_acc() +{ + python3.7 ../postprocess.py --result_path=./result_Files --label_path=$label_path &> acc.log +} + +air_to_om +if [ $? -ne 0 ]; then + echo " air to om failed" + exit 1 +fi +compile_app +if [ $? -ne 0 ]; then + echo "compile app code failed" + exit 1 +fi +infer +if [ $? -ne 0 ]; then + echo " execute inference failed" + exit 1 +fi +cal_acc +if [ $? -ne 0 ]; then + echo "calculate accuracy failed" + exit 1 +fi \ No newline at end of file diff --git a/model_zoo/official/cv/resnet50_quant/README.md b/model_zoo/official/cv/resnet50_quant/README.md index 6fc08b13d17..73a0fead4e1 100644 --- a/model_zoo/official/cv/resnet50_quant/README.md +++ b/model_zoo/official/cv/resnet50_quant/README.md @@ -73,9 +73,11 @@ For FP16 operators, if the input data type is FP32, the backend of MindSpore wil ```python ├── resnet50_quant ├── README.md # descriptions about Resnet50-Quant + ├── ascend310_infer # application for 310 inference ├── scripts │ ├──run_train.sh # shell script for train on Ascend │ ├──run_infer.sh # shell script for evaluation on Ascend + │ ├──run_infer_310.sh # shell script for 310 inference ├── models │ ├──resnet_quant.py # define the network model of resnet50-quant │ ├──resnet_quant_manual.py # define the manually quantized network model of resnet50-quant @@ -88,6 +90,8 @@ For FP16 operators, if the input data type is FP32, the backend of MindSpore wil ├── train.py # training script ├── eval.py # evaluation script ├── export.py # export script + ├── export_bin_file.py # export bin file of ImageNet for 310 inference + ├── postprocess.py # post process for 310 inference ``` @@ -169,6 +173,36 @@ Inference result will be stored in the example path, you can find result like th result: {'acc': 0.76576314102564111} ``` +## [Model Export](#contents) + +```shell +python export.py --checkpoint_path [CKPT_PATH] --file_format [EXPORT_FORMAT] --device_target [PLATFORM] +``` + +`EXPORT_FORMAT` should be in ["AIR", "MINDIR"]. + +## [Ascend 310 inference](#contents) + +You should export AIR model at Ascend 910 before running the command below. +You can use export_bin_file.py to export ImageNet bin and label for 310 inference. + +```shell +python export_bin_file.py --dataset_dir [EVAL_DATASET_PATH] --save_dir [SAVE_PATH] +``` + +Run run_infer_310.sh and get the accuracy: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +You can view the results through the file "acc.log". The accuracy of the test dataset will be as follows: + +```bash +'Accuracy':0.77052 +``` + # [Model description](#contents) ## [Performance](#contents) diff --git a/model_zoo/official/cv/resnet50_quant/README_CN.md b/model_zoo/official/cv/resnet50_quant/README_CN.md index 7b1f5fc008f..edd18a89183 100644 --- a/model_zoo/official/cv/resnet50_quant/README_CN.md +++ b/model_zoo/official/cv/resnet50_quant/README_CN.md @@ -82,9 +82,11 @@ ResNet-50总体网络架构如下: ```python ├── resnet50_quant ├── Readme.md # ResNet-50-Quant相关描述 + ├── ascend310_infer # 实现310推理源代码 ├── scripts │ ├──run_train.sh # 使用昇腾处理器进行训练的shell脚本 │ ├──run_infer.sh # 使用昇腾处理器进行评估的shell脚本 + │ ├──run_infer_310.sh # Ascend 310 推理shell脚本 ├── model │ ├──resnet_quant.py # 定义ResNet50-Quant的网络模型 ├──src @@ -96,6 +98,8 @@ ResNet-50总体网络架构如下: ├── train.py # 训练脚本 ├── eval.py # 评估脚本 ├── export.py # 导出脚本 + ├── export_bin_file.py # 导出ImageNet数据集的bin文件用于310推理 + ├── postprocess.py # 310推理后处理脚本 ``` @@ -177,6 +181,36 @@ epoch: 5 step: 5004, loss is 3.1978393 result:{'acc':0.76576314102564111} ``` +## 模型导出 + +```shell +python export.py --checkpoint_path [CKPT_PATH] --file_format [EXPORT_FORMAT] --device_target [PLATFORM] +``` + +`EXPORT_FORMAT` 可选 ["AIR", "MINDIR"]. + +## Ascend 310 推理 + +在推理之前需要在昇腾910环境上完成AIR模型的导出。 +并使用export_bin_file.py导出ImageNet数据集的bin文件和对应的label文件: + +```shell +python export_bin_file.py --dataset_dir [EVAL_DATASET_PATH] --save_dir [SAVE_PATH] +``` + +执行推理并得到推理精度: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] +``` + +您可以通过acc.log文件查看结果。推理准确性如下: + +```bash +'Accuracy':0.77052 +``` + # 模型描述 ## 性能 diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/ModelProcess.h b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/ModelProcess.h new file mode 100644 index 00000000000..9acb683bee2 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/ModelProcess.h @@ -0,0 +1,112 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MODELPROCESS_H +#define MODELPROCESS_H + +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* 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(); + + /** + * @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(); + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief dump model output result to file + */ + void DumpModelOutputResult(char *output_name); + + /** + * @brief get model output result + */ + void OutputModelResult(); + + private: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; +#endif diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/SampleProcess.h b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/SampleProcess.h new file mode 100644 index 00000000000..30a77f4248c --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/SampleProcess.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLEPROCESS_H +#define SAMPLEPROCESS_H + +#include +#include +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* SampleProcess +*/ +class SampleProcess { + public: + /** + * @brief Constructor + */ + explicit SampleProcess(int32_t deviceId); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(const char *acl_config_path); + + /** + * @brief sample process + * @return result + */ + Result Process(const char *om_path, const char *input_folder); + + void GetAllFiles(std::string path, std::vector *files); + + private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + +#endif diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/utils.h b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/utils.h new file mode 100644 index 00000000000..b21e418a1f4 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/inc/utils.h @@ -0,0 +1,53 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_INFERENCE_UTILS_H_ +#define MINDSPORE_INFERENCE_UTILS_H_ + +#include +#include + +#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) +#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +/** +* Utils +*/ +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 Read bin 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); +}; +#endif diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/CMakeLists.txt b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/CMakeLists.txt new file mode 100644 index 00000000000..a8c1eb0fd33 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) +# project information +project(InferClassification) +# Check environment variable +if(NOT DEFINED ENV{ASCEND_HOME}) + message(FATAL_ERROR "please define environment variable:ASCEND_HOME") +endif() + +# Compile options +add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined") + +# Skip build rpath +set(CMAKE_SKIP_BUILD_RPATH True) + +# Set output directory +set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/out) + +# Set include directory and library directory +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib) +set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib) + +# Header path +include_directories(${ACL_LIB_DIR}/include/) +include_directories(${ATLAS_ACL_LIB_DIR}/include/) +include_directories(${PROJECT_SRC_ROOT}/../inc) + +# add host lib path +link_directories(${ACL_LIB_DIR}) +find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64) + +add_executable(main utils.cpp + SampleProcess.cpp + ModelProcess.cpp + main.cpp) + +target_link_libraries(main ${acl} gflags pthread) diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/ModelProcess.cpp b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/ModelProcess.cpp new file mode 100644 index 00000000000..5586ebbd9f9 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/ModelProcess.cpp @@ -0,0 +1,326 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/ModelProcess.h" +#include +#include +#include +#include +#include "../inc/utils.h" + +extern bool g_isDevice; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) { +} + +ModelProcess::~ModelProcess() { + Unload(); + DestroyDesc(); + DestroyInput(); + DestroyOutput(); +} + +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; + } + + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST); + 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; + } + + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer, bufferSize); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + 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 output 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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(char *output_name) { + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + std::string homePath = "./result_Files"; + for (size_t i = 0; i < outputNum; ++i) { + std::string fileName = std::string(output_name) + '_' + std::to_string(i) + ".bin"; + std::string outputFileName = homePath + "/" + fileName; + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(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() { + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(dataBuffer); + void *outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + float *outData = NULL; + 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); + return; + } + outData = reinterpret_cast(outHostData); + } else { + outData = reinterpret_cast(data); + } + std::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); + } + if (!g_isDevice) { + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + } + INFO_LOG("output data success"); + return; +} + +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() { + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError 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/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/SampleProcess.cpp b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/SampleProcess.cpp new file mode 100644 index 00000000000..057f97f8624 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/SampleProcess.cpp @@ -0,0 +1,199 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/SampleProcess.h" +#include +#include +#include +#include +#include +#include "../inc/utils.h" +#include "../inc/ModelProcess.h" +#include "acl/acl.h" + +extern bool g_isDevice; +using std::string; +using std::vector; + +SampleProcess::SampleProcess(int32_t deviceId) : context_(nullptr), stream_(nullptr) { + deviceId_ = deviceId; +} + +SampleProcess::~SampleProcess() { + DestroyResource(); +} + +Result SampleProcess::InitResource(const char *aclConfigPath) { + // ACL init + 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"); + return SUCCESS; +} + +void SampleProcess::GetAllFiles(std::string path, std::vector *files) { + DIR *pDir; + struct dirent* ptr; + if (!(pDir = opendir(path.c_str()))) + return; + while ((ptr = readdir(pDir)) != 0) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) + files->push_back(path + "/" + ptr->d_name); + } + closedir(pDir); +} + +Result SampleProcess::Process(const char *om_path, const char *input_folder) { + // model init + ModelProcess processModel; + + Result ret = processModel.LoadModelFromFileWithMem(om_path); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModelFromFileWithMem failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateDesc failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateOutput failed"); + return FAILED; + } + + std::vector testFile; + GetAllFiles(input_folder, &testFile); + + if (testFile.size() == 0) { + WARN_LOG("no input data under folder"); + } + + // loop begin + for (size_t index = 0; index < testFile.size(); ++index) { + INFO_LOG("start to process file:%s", testFile[index].c_str()); + // model process + uint32_t devBufferSize; + void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); + return FAILED; + } + ret = processModel.CreateInput(picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateInput failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("execute inference failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + int pos = testFile[index].find_last_of('/'); + std::string name = testFile[index].substr(pos+1); + std::string outputname = name.substr(0, name.rfind(".")); + + // print the top 5 confidence values + processModel.OutputModelResult(); + // dump output result to file in the current directory + processModel.DumpModelOutputResult(const_cast(outputname.c_str())); + + // release model input buffer + aclrtFree(picDevBuffer); + processModel.DestroyInput(); + } + // loop end + + 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/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/acl.json b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/acl.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/acl.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/build.sh b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/build.sh new file mode 100755 index 00000000000..b5979b68e60 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +path_cur=$(cd "`dirname $0`" || exit; pwd) + +function preparePath() { + rm -rf $1 + mkdir -p $1 + cd $1 || exit +} + +function buildA300() { + if [ ! "${ARCH_PATTERN}" ]; then + # set ARCH_PATTERN to acllib when it was not specified by user + export ARCH_PATTERN=acllib + echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}" + else + echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib" + export ARCH_PATTERN=${ARCH_PATTERN}/acllib + fi + + path_build=$path_cur/build + preparePath $path_build + cmake .. + make -j + ret=$? + cd .. + return ${ret} +} + +# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user +if [ ! "${ASCEND_VERSION}" ]; then + export ASCEND_VERSION=ascend-toolkit/latest + echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}" +else + echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user" +fi + +buildA300 + +if [ $? -ne 0 ]; then + exit 1 +fi diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/main.cpp b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/main.cpp new file mode 100644 index 00000000000..ca47f0635ef --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/main.cpp @@ -0,0 +1,58 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "../inc/SampleProcess.h" +#include "../inc/utils.h" + +bool g_isDevice = false; + +DEFINE_string(om_path, "", "om path"); +DEFINE_string(dataset_path, "", "dataset path"); +DEFINE_string(acljson_path, "", "acl json path"); +DEFINE_int32(device_id, 0, "device id"); + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + std::string om_path = FLAGS_om_path; + std::string dataset_path = FLAGS_dataset_path; + std::string acljson_path = FLAGS_acljson_path; + int32_t device_id = FLAGS_device_id; + std::ifstream fin(om_path); + if (!fin) { + std::cout << "Invalid om path." << std::endl; + return FAILED; + } + SampleProcess processSample(device_id); + // acl.json is deployed for dump data. + Result ret = processSample.InitResource(acljson_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + ret = processSample.Process(om_path.c_str(), dataset_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + + INFO_LOG("execute sample success"); + return SUCCESS; +} diff --git a/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/utils.cpp b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/utils.cpp new file mode 100644 index 00000000000..6e669f3f329 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/ascend310_infer/src/utils.cpp @@ -0,0 +1,113 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/utils.h" +#include +#include +#include +#include +#include "acl/acl.h" + +extern bool g_isDevice; + +void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) { + struct stat sBuf; + int fileStatus = stat(fileName.data(), &sBuf); + if (fileStatus == -1) { + ERROR_LOG("failed to get file"); + return nullptr; + } + if (S_ISREG(sBuf.st_mode) == 0) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return nullptr; + } + + 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; + } + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc for binFileBufferData failed"); + binFile.close(); + return nullptr; + } + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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; + } +} diff --git a/model_zoo/official/cv/resnet50_quant/export_bin_file.py b/model_zoo/official/cv/resnet50_quant/export_bin_file.py new file mode 100644 index 00000000000..0f4e44fd321 --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/export_bin_file.py @@ -0,0 +1,64 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +export imagenet2012 dataset to bin. +""" +import os +import argparse +from mindspore import context +from src.dataset import create_dataset + +def parse_args(): + parser = argparse.ArgumentParser(description='ImageNet2012 to bin') + parser.add_argument('--device_target', type=str, default="Ascend", + choices=['Ascend', 'GPU'], + help='device where the code will be implemented (default: Ascend)') + parser.add_argument('--dataset_dir', type=str, default='', help='dataset path') + parser.add_argument('--save_dir', type=str, default='', help='path to save bin file') + parser.add_argument('--batch_size', type=int, default=1, help='batch size for bin') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + os.environ["RANK_SIZE"] = '1' + os.environ["RANK_ID"] = '0' + device_id = int(os.getenv('DEVICE_ID')) if os.getenv('DEVICE_ID') else 0 + context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target, device_id=device_id) + imagenet2012_path = args.dataset_dir + batch_size = args.batch_size + save_dir = os.path.join(args.save_dir, 'imagenet2012_310_infer_data') + folder = os.path.join(save_dir, 'imagenet2012_bs_' + str(batch_size) + '_bin') + if not os.path.exists(folder): + os.makedirs(folder) + ds = create_dataset(imagenet2012_path, do_train=False, repeat_num=1, batch_size=batch_size, + target=args.device_target) + iter_num = 0 + label_file = os.path.join(save_dir, './imagenet2012_bs_' + str(batch_size) + '_label.txt') + with open(label_file, 'w') as f: + for data in ds.create_dict_iterator(): + image = data['image'] + label = data['label'] + file_name = "imagenet2012_" + str(iter_num) + ".bin" + file_path = folder + "/" + file_name + image.asnumpy().tofile(file_path) + f.write(file_name) + for i in label: + f.write(',' + str(i)) + f.write('\n') + iter_num += 1 + print("=====iter_num:{}=====".format(iter_num)) + print("=====image_data:{}=====".format(image)) + print("=====label_data:{}=====".format(label)) diff --git a/model_zoo/official/cv/resnet50_quant/postprocess.py b/model_zoo/official/cv/resnet50_quant/postprocess.py new file mode 100644 index 00000000000..9bbc3301b3c --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/postprocess.py @@ -0,0 +1,57 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" +post process for 310 inference. +""" +import os +import argparse +import numpy as np + +def parse_args(): + parser = argparse.ArgumentParser(description='resnet50_quant inference') + parser.add_argument('--result_path', type=str, default='', help='result files path') + parser.add_argument('--label_path', type=str, default='', help='label file path') + args_, _ = parser.parse_known_args() + return args_ + +if __name__ == "__main__": + args = parse_args() + path = args.result_path + label_path = args.label_path + files = os.listdir(path) + step = 0 + sum_right = 0 + label_dict = {} + with open(label_path, 'r') as f: + for line in f.readlines(): + batch_label = line.strip().split(',') + label_dict[batch_label[0]] = batch_label[1:] + for file in files: + full_file_path = os.path.join(path, file) + if os.path.isfile(full_file_path): + label_file = file.split('_0.bin')[0] + '.bin' + label_array = np.array(label_dict[label_file]) + line = np.fromfile(full_file_path, dtype=np.float32) + batch_size = label_array.shape[0] + line_comp = line.reshape(batch_size, int(line.shape[0] / batch_size)) + for i in range(0, batch_size): + pred = np.argmax(line_comp[i], axis=0) + step += 1 + if pred == label_array[i].astype(np.int64): + sum_right += 1 + print("=====step:{}=====".format(step)) + print("=====sum_right:{}=====".format(sum_right)) + accuracy = sum_right * 100.0 / step + print("=====accuracy:{}=====".format(accuracy)) diff --git a/model_zoo/official/cv/resnet50_quant/scripts/run_infer_310.sh b/model_zoo/official/cv/resnet50_quant/scripts/run_infer_310.sh new file mode 100644 index 00000000000..5aa3e4bf77f --- /dev/null +++ b/model_zoo/official/cv/resnet50_quant/scripts/run_infer_310.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +if [[ $# -lt 3 || $# -gt 4 ]]; then + echo "Usage: bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [LABEL_PATH] [DEVICE_ID] + DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero" +exit 1 +fi + +get_real_path(){ + if [ "${1:0:1}" == "/" ]; then + echo "$1" + else + echo "$(realpath -m $PWD/$1)" + fi +} +model=$(get_real_path $1) +data_path=$(get_real_path $2) +label_path=$(get_real_path $3) + +device_id=0 +if [ $# == 4 ]; then + device_id=$4 +fi + +echo "mindir name: "$model +echo "dataset path: "$data_path +echo "label path: "$label_path +echo "device id: "$device_id + +export ASCEND_HOME=/usr/local/Ascend/ +if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then + export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe + export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp +else + export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/opp +fi + +function air_to_om() +{ + atc --input_format=NCHW --framework=1 --model=$model --output=resnet50_quant --soc_version=Ascend310 &> atc.log +} + +function compile_app() +{ + cd ../ascend310_infer/src || exit + bash build.sh &> build.log +} + +function infer() +{ + cd - || exit + if [ -d result_Files ]; then + rm -rf ./result_Files + fi + if [ -d time_Result ]; then + rm -rf ./time_Result + fi + mkdir result_Files + mkdir time_Result + ../ascend310_infer/src/out/main --om_path=./resnet50_quant.om --dataset_path=$data_path --acljson_path=../ascend310_infer/src/acl.json --device_id=$device_id &> infer.log +} + +function cal_acc() +{ + python3.7 ../postprocess.py --result_path=./result_Files --label_path=$label_path &> acc.log +} + +air_to_om +if [ $? -ne 0 ]; then + echo " air to om failed" + exit 1 +fi +compile_app +if [ $? -ne 0 ]; then + echo "compile app code failed" + exit 1 +fi +infer +if [ $? -ne 0 ]; then + echo " execute inference failed" + exit 1 +fi +cal_acc +if [ $? -ne 0 ]; then + echo "calculate accuracy failed" + exit 1 +fi \ No newline at end of file diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/README.md b/model_zoo/official/cv/yolov3_darknet53_quant/README.md index dd3879b6f37..4cbb90d8c68 100644 --- a/model_zoo/official/cv/yolov3_darknet53_quant/README.md +++ b/model_zoo/official/cv/yolov3_darknet53_quant/README.md @@ -106,11 +106,13 @@ sh run_eval.sh dataset/coco2014/ checkpoint/yolov3_quant.ckpt 0 . └─yolov3_darknet53_quant ├─README.md + ├─ascend310_infer # application for 310 inference ├─mindspore_hub_conf.md # config for mindspore hub ├─scripts ├─run_standalone_train.sh # launch standalone training(1p) in ascend ├─run_distribute_train.sh # launch distributed training(8p) in ascend └─run_eval.sh # launch evaluating in ascend + └─run_infer_310.sh # shell script for 310 inference ├─src ├─__init__.py # python init file ├─config.py # parameter configuration @@ -126,6 +128,8 @@ sh run_eval.sh dataset/coco2014/ checkpoint/yolov3_quant.ckpt 0 ├─yolo_dataset.py # create dataset for YOLOV3 ├─eval.py # eval net └─train.py # train net + └─export_bin_file.py # export bin file of coco2014 for 310 inference + └─postprocess.py # post process for 310 inference ``` ### [Script Parameters](#contents) @@ -257,6 +261,48 @@ Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.450 Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.558 ``` +## [Model Export](#contents) + +```shell +python export.py --ckpt_file [CKPT_PATH] --file_format [EXPORT_FORMAT] +``` + +`EXPORT_FORMAT` should be in ["AIR", "MINDIR"]. + +## [Ascend 310 inference](#contents) + +You should export AIR model at Ascend 910 before running the command below. +You can use export_bin_file.py to export coco2014 bin, image_shape.npy and image_id.npy for 310 inference. + +```shell +python export_bin_file.py --data_dir [DATASET_PATH] --save_path [SAVE_PATH] +``` + +Run run_infer_310.sh and get the accuracy: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [ANNO_PATH] [IMAGESHAPE_PATH] [IMAGEID_PATH] [DEVICE_ID] +``` + +You can view the results through the file "acc.log". The accuracy of the test dataset will be as follows: + +```bash +=============coco eval reulst========= +Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.306 +Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.528 +Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.315 +Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.122 +Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.322 +Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.426 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.259 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.398 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.423 +Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.226 +Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.442 +Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.555 +``` + ## [Model Description](#contents) ### [Performance](#contents) diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/README_CN.md b/model_zoo/official/cv/yolov3_darknet53_quant/README_CN.md index 8def97db471..2684f08280c 100644 --- a/model_zoo/official/cv/yolov3_darknet53_quant/README_CN.md +++ b/model_zoo/official/cv/yolov3_darknet53_quant/README_CN.md @@ -116,11 +116,13 @@ sh run_eval.sh dataset/coco2014/ checkpoint/yolov3_quant.ckpt 0 . └─yolov3_darknet53_quant ├─README.md + ├─ascend310_infer # 实现310推理源代码 ├─mindspore_hub_conf.md # Mindspore Hub配置 ├─scripts ├─run_standalone_train.sh # 在Ascend中启动单机训练(1卡) ├─run_distribute_train.sh # 在Ascend中启动分布式训练(8卡) - └─run_eval.sh # 在Ascend中启动评估 + ├─run_eval.sh # 在Ascend中启动评估 + ├─run_infer_310.sh # Ascend 310 推理shell脚本 ├─src ├─__init__.py # python初始化文件 ├─config.py # 参数配置 @@ -136,6 +138,8 @@ sh run_eval.sh dataset/coco2014/ checkpoint/yolov3_quant.ckpt 0 ├─yolo_dataset.py # 为YOLOV3创建数据集 ├─eval.py # 评估网络 └─train.py # 训练网络 + ├─export_bin_file.py # 导出coco2014数据集的bin文件用于310推理 + ├─postprocess.py # 310推理后处理脚本 ``` ### 脚本参数 @@ -266,6 +270,48 @@ Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.450 Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.558 ``` +## 模型导出 + +```shell +python export.py --ckpt_file [CKPT_PATH] --file_format [EXPORT_FORMAT] +``` + +`EXPORT_FORMAT` 可选 ["AIR", "MINDIR"]. + +## Ascend 310 推理 + +在推理之前需要在昇腾910环境上完成AIR模型的导出。 +并使用export_bin_file.py导出coco2014数据集的bin文件和对应的image_shape, image_id文件: + +```shell +python export_bin_file.py --data_dir [DATASET_PATH] --save_path [SAVE_PATH] +``` + +执行推理并得到推理精度: + +```shell +# Ascend310 inference +bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [ANNO_PATH] [IMAGESHAPE_PATH] [IMAGEID_PATH] [DEVICE_ID] +``` + +您可以通过acc.log文件查看结果。推理准确性如下: + +```bash +=============coco eval reulst========= +Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.306 +Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.528 +Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.315 +Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.122 +Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.322 +Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.426 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.259 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.398 +Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.423 +Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.226 +Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.442 +Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.555 +``` + ## 模型描述 ### 性能 diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/ModelProcess.h b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/ModelProcess.h new file mode 100644 index 00000000000..e0a91396f09 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/ModelProcess.h @@ -0,0 +1,114 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MODELPROCESS_H +#define MODELPROCESS_H + +#include +#include +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* 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(); + + /** + * @brief create model input + * @param [in] inputDataBuffer: input buffer + * @param [in] bufferSize: input buffer size + * @return result + */ + Result CreateInput(const std::vector &inputDataBuffer, const std::vector &bufferSize); + + /** + * @brief destroy input resource + */ + void DestroyInput(); + + /** + * @brief create output buffer + * @return result + */ + Result CreateOutput(); + + /** + * @brief destroy output resource + */ + void DestroyOutput(); + + /** + * @brief model execute + * @return result + */ + Result Execute(); + + /** + * @brief dump model output result to file + */ + void DumpModelOutputResult(char *output_name); + + /** + * @brief get model output result + */ + void OutputModelResult(); + + private: + uint32_t modelId_; + size_t modelMemSize_; + size_t modelWeightSize_; + void *modelMemPtr_; + void *modelWeightPtr_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + aclmdlDataset *input_; + aclmdlDataset *output_; +}; +#endif diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/SampleProcess.h b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/SampleProcess.h new file mode 100644 index 00000000000..30a77f4248c --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/SampleProcess.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLEPROCESS_H +#define SAMPLEPROCESS_H + +#include +#include +#include "acl/acl.h" +#include "../inc/utils.h" + +/** +* SampleProcess +*/ +class SampleProcess { + public: + /** + * @brief Constructor + */ + explicit SampleProcess(int32_t deviceId); + + /** + * @brief Destructor + */ + ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(const char *acl_config_path); + + /** + * @brief sample process + * @return result + */ + Result Process(const char *om_path, const char *input_folder); + + void GetAllFiles(std::string path, std::vector *files); + + private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + +#endif diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/utils.h b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/utils.h new file mode 100644 index 00000000000..b21e418a1f4 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/inc/utils.h @@ -0,0 +1,53 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_INFERENCE_UTILS_H_ +#define MINDSPORE_INFERENCE_UTILS_H_ + +#include +#include + +#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) +#define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +/** +* Utils +*/ +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 Read bin 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); +}; +#endif diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/CMakeLists.txt b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/CMakeLists.txt new file mode 100644 index 00000000000..8c4cea6aae8 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) +# project information +project(InferClassification) +# Check environment variable +if(NOT DEFINED ENV{ASCEND_HOME}) + message(FATAL_ERROR "please define environment variable:ASCEND_HOME") +endif() + +# Compile options +add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -std=c++17 -Werror -Wall -fPIE -Wl,--allow-shlib-undefined") + +# Skip build rpath +set(CMAKE_SKIP_BUILD_RPATH True) + +# Set output directory +set(PROJECT_SRC_ROOT ${CMAKE_CURRENT_LIST_DIR}/) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SRC_ROOT}/out) + +# Set include directory and library directory +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/acllib) +set(ATLAS_ACL_LIB_DIR $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib) + +# Header path +include_directories(${ACL_LIB_DIR}/include/) +include_directories(${ATLAS_ACL_LIB_DIR}/include/) +include_directories(${PROJECT_SRC_ROOT}/../inc) + +# add host lib path +link_directories(${ACL_LIB_DIR}) +find_library(acl libascendcl.so ${ACL_LIB_DIR}/lib64 ${ATLAS_ACL_LIB_DIR}/lib64) + +add_executable(main utils.cpp + SampleProcess.cpp + ModelProcess.cpp + main.cpp) + +target_link_libraries(main ${acl} gflags pthread) + diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/ModelProcess.cpp b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/ModelProcess.cpp new file mode 100644 index 00000000000..76cb1fa2594 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/ModelProcess.cpp @@ -0,0 +1,337 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/ModelProcess.h" +#include +#include +#include +#include +#include "../inc/utils.h" + +extern bool g_isDevice; + +ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) { +} + +ModelProcess::~ModelProcess() { + Unload(); + DestroyDesc(); + DestroyInput(); + DestroyOutput(); +} + +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; + } + + ret = aclrtMalloc(&modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc buffer for mem failed, require size is %zu", modelMemSize_); + return FAILED; + } + + ret = aclrtMalloc(&modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST); + 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(const std::vector &inputDataBuffer, const std::vector &bufferSize) { + input_ = aclmdlCreateDataset(); + if (input_ == nullptr) { + ERROR_LOG("can't create dataset, create input failed"); + return FAILED; + } + for (size_t i = 0; i < inputDataBuffer.size(); ++i) { + aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuffer[i], bufferSize[i]); + if (inputData == nullptr) { + ERROR_LOG("can't create data buffer, create input failed"); + return FAILED; + } + aclError ret = aclmdlAddDatasetBuffer(input_, inputData); + 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 output 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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(char *output_name) { + size_t outputNum = aclmdlGetDatasetNumBuffers(output_); + std::string homePath = "./result_Files"; + for (size_t i = 0; i < outputNum; ++i) { + std::string fileName = std::string(output_name) + '_' + std::to_string(i) + ".bin"; + std::string outputFileName = homePath + "/" + fileName; + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(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() { + for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) { + aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i); + void* data = aclGetDataBufferAddr(dataBuffer); + uint32_t len = aclGetDataBufferSizeV2(dataBuffer); + + void *outHostData = NULL; + aclError ret = ACL_ERROR_NONE; + float *outData = NULL; + 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); + return; + } + + outData = reinterpret_cast(outHostData); + } else { + outData = reinterpret_cast(data); + } + std::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); + } + if (!g_isDevice) { + ret = aclrtFreeHost(outHostData); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("aclrtFreeHost failed, ret[%d]", ret); + return; + } + } + } + + INFO_LOG("output data success"); + return; +} + +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() { + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError 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/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/SampleProcess.cpp b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/SampleProcess.cpp new file mode 100644 index 00000000000..ed35f79626e --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/SampleProcess.cpp @@ -0,0 +1,214 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/SampleProcess.h" +#include +#include +#include +#include +#include +#include "../inc/utils.h" +#include "../inc/ModelProcess.h" +#include "acl/acl.h" + +extern bool g_isDevice; +using std::string; +using std::vector; + +SampleProcess::SampleProcess(int32_t deviceId) : context_(nullptr), stream_(nullptr) { + deviceId_ = deviceId; +} + +SampleProcess::~SampleProcess() { + DestroyResource(); +} + +Result SampleProcess::InitResource(const char *aclConfigPath) { + // ACL init + 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"); + return SUCCESS; +} + +void SampleProcess::GetAllFiles(std::string path, std::vector *files) { + DIR *pDir; + struct dirent* ptr; + if (!(pDir = opendir(path.c_str()))) + return; + while ((ptr = readdir(pDir)) != 0) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) + files->push_back(path + "/" + ptr->d_name); + } + closedir(pDir); +} + +Result SampleProcess::Process(const char *om_path, const char *input_folder) { + // model init + ModelProcess processModel; + + Result ret = processModel.LoadModelFromFileWithMem(om_path); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModelFromFileWithMem failed"); + return FAILED; + } + + ret = processModel.CreateDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateDesc failed"); + return FAILED; + } + + ret = processModel.CreateOutput(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateOutput failed"); + return FAILED; + } + + std::vector testFile; + GetAllFiles(input_folder, &testFile); + + if (testFile.size() == 0) { + WARN_LOG("no input data under folder"); + } + float *inputShape = reinterpret_cast(malloc(sizeof(float) * 2)); + inputShape[0] = 416; + inputShape[1] = 416; + void *inputShapeBuffer = nullptr; + int mret = aclrtMalloc(&inputShapeBuffer, 8, ACL_MEM_MALLOC_NORMAL_ONLY); + if (mret != ACL_ERROR_NONE) { + aclrtFree(inputShapeBuffer); + return FAILED; + } + mret = aclrtMemcpy(reinterpret_cast(inputShapeBuffer), 8, inputShape, 8, ACL_MEMCPY_HOST_TO_DEVICE); + if (mret != ACL_ERROR_NONE) { + aclrtFree(inputShapeBuffer); + return FAILED; + } + // loop begin + for (size_t index = 0; index < testFile.size(); ++index) { + INFO_LOG("start to process file:%s", testFile[index].c_str()); + // model process + uint32_t devBufferSize; + void *picDevBuffer = Utils::GetDeviceBufferOfFile(testFile[index], &devBufferSize); + if (picDevBuffer == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); + return FAILED; + } + std::vector inputBuffers({picDevBuffer, inputShapeBuffer}); + std::vector inputSizes({devBufferSize, 8}); + ret = processModel.CreateInput(inputBuffers, inputSizes); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateInput failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + ret = processModel.Execute(); + if (ret != SUCCESS) { + ERROR_LOG("execute inference failed"); + aclrtFree(picDevBuffer); + return FAILED; + } + + int pos = testFile[index].find_last_of('/'); + std::string name = testFile[index].substr(pos+1); + std::string outputname = name.substr(0, name.rfind(".")); + + // print the top 5 confidence values + processModel.OutputModelResult(); + // dump output result to file in the current directory + processModel.DumpModelOutputResult(const_cast(outputname.c_str())); + + // release model input buffer + aclrtFree(picDevBuffer); + processModel.DestroyInput(); + } + // loop end + + 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/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/acl.json b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/acl.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/acl.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/build.sh b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/build.sh new file mode 100755 index 00000000000..b5979b68e60 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +path_cur=$(cd "`dirname $0`" || exit; pwd) + +function preparePath() { + rm -rf $1 + mkdir -p $1 + cd $1 || exit +} + +function buildA300() { + if [ ! "${ARCH_PATTERN}" ]; then + # set ARCH_PATTERN to acllib when it was not specified by user + export ARCH_PATTERN=acllib + echo "ARCH_PATTERN is set to the default value: ${ARCH_PATTERN}" + else + echo "ARCH_PATTERN is set to ${ARCH_PATTERN} by user, reset it to ${ARCH_PATTERN}/acllib" + export ARCH_PATTERN=${ARCH_PATTERN}/acllib + fi + + path_build=$path_cur/build + preparePath $path_build + cmake .. + make -j + ret=$? + cd .. + return ${ret} +} + +# set ASCEND_VERSION to ascend-toolkit/latest when it was not specified by user +if [ ! "${ASCEND_VERSION}" ]; then + export ASCEND_VERSION=ascend-toolkit/latest + echo "Set ASCEND_VERSION to the default value: ${ASCEND_VERSION}" +else + echo "ASCEND_VERSION is set to ${ASCEND_VERSION} by user" +fi + +buildA300 + +if [ $? -ne 0 ]; then + exit 1 +fi diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/main.cpp b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/main.cpp new file mode 100644 index 00000000000..0f1354613bc --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/main.cpp @@ -0,0 +1,58 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "../inc/SampleProcess.h" +#include "../inc/utils.h" + +bool g_isDevice = false; + +DEFINE_string(om_path, "", "om path"); +DEFINE_string(dataset_path, "", "dataset path"); +DEFINE_string(acljson_path, "", "acl json path"); +DEFINE_int32(device_id, 0, "device id"); + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + std::string om_path = FLAGS_om_path; + std::string dataset_path = FLAGS_dataset_path; + std::string acljson_path = FLAGS_acljson_path; + int32_t device_id = FLAGS_device_id; + std::ifstream fin(om_path); + if (!fin) { + std::cout << "Invalid om path." << std::endl; + return FAILED; + } + SampleProcess processSample(device_id); + // acl.json is deployed for dump data. + Result ret = processSample.InitResource(acljson_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + ret = processSample.Process(om_path.c_str(), dataset_path.c_str()); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + + INFO_LOG("execute sample success"); + return SUCCESS; +} diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/utils.cpp b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/utils.cpp new file mode 100644 index 00000000000..6e669f3f329 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/ascend310_infer/src/utils.cpp @@ -0,0 +1,113 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../inc/utils.h" +#include +#include +#include +#include +#include "acl/acl.h" + +extern bool g_isDevice; + +void* Utils::ReadBinFile(std::string fileName, uint32_t *fileSize) { + struct stat sBuf; + int fileStatus = stat(fileName.data(), &sBuf); + if (fileStatus == -1) { + ERROR_LOG("failed to get file"); + return nullptr; + } + if (S_ISREG(sBuf.st_mode) == 0) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return nullptr; + } + + 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; + } + + binFile.seekg(0, binFile.beg); + + void* binFileBufferData = nullptr; + aclError ret = ACL_ERROR_NONE; + if (!g_isDevice) { + ret = aclrtMallocHost(&binFileBufferData, binFileBufferLen); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("malloc for binFileBufferData failed"); + binFile.close(); + return nullptr; + } + if (binFileBufferData == nullptr) { + ERROR_LOG("malloc binFileBufferData failed"); + binFile.close(); + return nullptr; + } + } else { + ret = aclrtMalloc(&binFileBufferData, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + 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, ACL_MEM_MALLOC_NORMAL_ONLY); + 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; + } +} diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/export_bin_file.py b/model_zoo/official/cv/yolov3_darknet53_quant/export_bin_file.py new file mode 100644 index 00000000000..ccbad7ff5e7 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/export_bin_file.py @@ -0,0 +1,111 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""YoloV3_quant export coco bin.""" +import os +import argparse +import datetime +import numpy as np +import mindspore as ms +from mindspore import Tensor +from mindspore.context import ParallelMode +from mindspore import context + +from src.logger import get_logger +from src.yolo_dataset import create_yolo_dataset +from src.config import ConfigYOLOV3DarkNet53 + +def parse_args(): + """Parse arguments.""" + parser = argparse.ArgumentParser('mindspore coco export bin') + parser.add_argument('--device_target', type=str, default="Ascend", + choices=['Ascend', 'GPU'], + help='device where the code will be implemented (default: Ascend)') + # dataset related + parser.add_argument('--data_dir', type=str, default="", help='Eval data dir. Default: ""') + parser.add_argument('--per_batch_size', default=1, type=int, help='Batch size for per device, Default: 1') + + # logging related + parser.add_argument('--log_path', type=str, default="outputs/", help='Log save location, Default: "outputs/"') + parser.add_argument('--save_path', type=str, default="", help='Bin file save location') + + # detect_related + parser.add_argument('--nms_thresh', type=float, default=0.5, help='Threshold for NMS. Default: 0.5') + parser.add_argument('--annFile', type=str, default="", help='The path to annotation. Default: ""') + parser.add_argument('--testing_shape', type=str, default="", help='Shape for test. Default: ""') + + args_, _ = parser.parse_known_args() + + args_.data_root = os.path.join(args_.data_dir, 'val2014') + args_.annFile = os.path.join(args_.data_dir, 'annotations/instances_val2014.json') + + return args_ + +def conver_testing_shape(args_org): + """Convert testing shape to list.""" + testing_shape = [int(args_org.testing_shape), int(args_org.testing_shape)] + return testing_shape + +if __name__ == "__main__": + args = parse_args() + devid = int(os.getenv('DEVICE_ID')) if os.getenv('DEVICE_ID') else 0 + context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target, device_id=devid) + + # logger + args.outputs_dir = os.path.join(args.log_path, + datetime.datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S')) + rank_id = int(os.environ.get('RANK_ID')) if os.environ.get('RANK_ID') else 0 + args.logger = get_logger(args.outputs_dir, rank_id) + + context.reset_auto_parallel_context() + parallel_mode = ParallelMode.STAND_ALONE + context.set_auto_parallel_context(parallel_mode=parallel_mode, gradients_mean=True, device_num=1) + + config = ConfigYOLOV3DarkNet53() + if args.testing_shape: + config.test_img_shape = conver_testing_shape(args) + data_root = args.data_root + ann_file = args.annFile + + ds, data_size = create_yolo_dataset(data_root, ann_file, is_training=False, batch_size=args.per_batch_size, + max_epoch=1, device_num=1, rank=rank_id, shuffle=False, + config=config) + + args.logger.info('testing shape : {}'.format(config.test_img_shape)) + args.logger.info('totol {} images to eval'.format(data_size)) + + cur_dir = args.save_path + save_folder = os.path.join(cur_dir, "yolov3_quant_coco_310_infer_data") + image_folder = os.path.join(save_folder, "image_bin") + if not os.path.exists(image_folder): + os.makedirs(image_folder) + + list_image_shape = [] + list_image_id = [] + + input_shape = Tensor(tuple(config.test_img_shape), ms.float32) + args.logger.info('Start inference....') + for i, data in enumerate(ds.create_dict_iterator()): + image = data["image"].asnumpy() + image_shape = data["image_shape"] + image_id = data["img_id"] + file_name = "YoloV3-DarkNet_coco_bs_" + str(args.per_batch_size) + "_" + str(i) + ".bin" + file_path = image_folder + "/" + file_name + image.tofile(file_path) + list_image_shape.append(image_shape.asnumpy()) + list_image_id.append(image_id.asnumpy()) + shapes = np.array(list_image_shape) + ids = np.array(list_image_id) + np.save(save_folder + "/image_shape.npy", shapes) + np.save(save_folder + "/image_id.npy", ids) diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/postprocess.py b/model_zoo/official/cv/yolov3_darknet53_quant/postprocess.py new file mode 100644 index 00000000000..6ce52b97a26 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/postprocess.py @@ -0,0 +1,66 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""YoloV3 postprocess.""" +import os +import argparse +import datetime +import numpy as np +from eval import DetectionEngine + +parser = argparse.ArgumentParser('YoloV3_quant postprocess') +parser.add_argument('--result_path', type=str, required=True, help='result files path.') +parser.add_argument('--per_batch_size', default=1, type=int, help='batch size for per gpu') +parser.add_argument('--nms_thresh', type=float, default=0.5, help='threshold for NMS') +parser.add_argument('--annFile', type=str, default='', help='path to annotation') +parser.add_argument('--image_shape', type=str, default='./image_shape.npy', help='path to image_shape.npy') +parser.add_argument('--image_id', type=str, default='./image_id.npy', help='path to image_id.npy') +parser.add_argument('--ignore_threshold', type=float, default=0.001, help='threshold to throw low quality boxes') +parser.add_argument('--log_path', type=str, default='outputs/', help='inference result save location') + +args, _ = parser.parse_known_args() + +if __name__ == "__main__": + args.outputs_dir = os.path.join(args.log_path, + datetime.datetime.now().strftime('%Y-%m-%d_time_%H_%M_%S')) + if not os.path.exists(args.outputs_dir): + os.makedirs(args.outputs_dir) + + detection = DetectionEngine(args) + bs = args.per_batch_size + + f_list = os.listdir(args.result_path) + shape_list = np.load(args.image_shape) + id_list = np.load(args.image_id) + prefix = "YoloV3-DarkNet_coco_bs_" + str(bs) + "_" + iter_num = 0 + for image_id in id_list: + image_shape = shape_list[iter_num] + path_small = os.path.join(args.result_path, prefix + str(iter_num) + '_0.bin') + path_medium = os.path.join(args.result_path, prefix + str(iter_num) + '_1.bin') + path_big = os.path.join(args.result_path, prefix + str(iter_num) + '_2.bin') + if os.path.exists(path_small) and os.path.exists(path_medium) and os.path.exists(path_big): + output_small = np.fromfile(path_small, np.float32).reshape(bs, 13, 13, 3, 85) + output_medium = np.fromfile(path_medium, np.float32).reshape(bs, 26, 26, 3, 85) + output_big = np.fromfile(path_big, np.float32).reshape(bs, 52, 52, 3, 85) + detection.detect([output_small, output_medium, output_big], bs, image_shape, image_id) + else: + print("Error: Image ", iter_num, " is not exist.") + iter_num += 1 + + detection.do_nms_for_results() + result_file_path = detection.write_result() + eval_result = detection.get_eval_result() + + print('\n=============coco eval result=========\n' + eval_result) diff --git a/model_zoo/official/cv/yolov3_darknet53_quant/scripts/run_infer_310.sh b/model_zoo/official/cv/yolov3_darknet53_quant/scripts/run_infer_310.sh new file mode 100644 index 00000000000..495617faf40 --- /dev/null +++ b/model_zoo/official/cv/yolov3_darknet53_quant/scripts/run_infer_310.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +if [[ $# -lt 5 || $# -gt 6 ]]; then + echo "Usage: bash run_infer_310.sh [AIR_PATH] [DATA_PATH] [ANNO_PATH] [IMAGESHAPE_PATH] [IMAGEID_PATH] [DEVICE_ID] + DEVICE_ID is optional, it can be set by environment variable device_id, otherwise the value is zero" +exit 1 +fi + +get_real_path(){ + if [ "${1:0:1}" == "/" ]; then + echo "$1" + else + echo "$(realpath -m $PWD/$1)" + fi +} +model=$(get_real_path $1) +data_path=$(get_real_path $2) +anno_path=$(get_real_path $3) +image_shape_path=$(get_real_path $4) +image_id_path=$(get_real_path $5) + +device_id=0 +if [ $# == 6 ]; then + device_id=$6 +fi + +echo "mindir name: "$model +echo "dataset path: "$data_path +echo "annotation path: "$anno_path +echo "image shape path: "$image_shape_path +echo "image id path: "$image_id_path +echo "device id: "$device_id + +export ASCEND_HOME=/usr/local/Ascend/ +if [ -d ${ASCEND_HOME}/ascend-toolkit ]; then + export PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/ccec_compiler/bin:$ASCEND_HOME/ascend-toolkit/latest/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/ascend-toolkit/latest/atc/lib64:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export TBE_IMPL_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp/op_impl/built-in/ai_core/tbe + export PYTHONPATH=${TBE_IMPL_PATH}:$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/ascend-toolkit/latest/opp +else + export PATH=$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH + export LD_LIBRARY_PATH=/usr/local/lib:$ASCEND_HOME/atc/lib64:$ASCEND_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$ASCEND_HOME/add-ons:$LD_LIBRARY_PATH + export PYTHONPATH=$ASCEND_HOME/atc/python/site-packages:$PYTHONPATH + export ASCEND_OPP_PATH=$ASCEND_HOME/opp +fi + +function air_to_om() +{ + atc --input_format=NCHW --framework=1 --model=$model --output=yolov3_darknet53_quant --soc_version=Ascend310 &> atc.log +} + +function compile_app() +{ + cd ../ascend310_infer/src || exit + bash build.sh &> build.log +} + +function infer() +{ + cd - || exit + if [ -d result_Files ]; then + rm -rf ./result_Files + fi + if [ -d time_Result ]; then + rm -rf ./time_Result + fi + mkdir result_Files + mkdir time_Result + + ../ascend310_infer/src/out/main --om_path=./yolov3_darknet53_quant.om --dataset_path=$data_path --acljson_path=../ascend310_infer/src/acl.json --device_id=$device_id &> infer.log + +} + +function cal_acc() +{ + python3.7 ../postprocess.py --result_path=./result_Files --img_path=$data_path --annFile=$anno_path --image_shape=$image_shape_path --image_id=$image_id_path &> acc.log +} + +air_to_om +if [ $? -ne 0 ]; then + echo "air to om code failed" + exit 1 +fi + +compile_app +if [ $? -ne 0 ]; then + echo "compile app code failed" + exit 1 +fi +infer +if [ $? -ne 0 ]; then + echo " execute inference failed" + exit 1 +fi +cal_acc +if [ $? -ne 0 ]; then + echo "calculate accuracy failed" + exit 1 +fi \ No newline at end of file