From 8af0ab26a9ec6d3e8c799d08cea39f7382e17782 Mon Sep 17 00:00:00 2001 From: ywx1101276 Date: Wed, 26 Jan 2022 16:13:47 +0800 Subject: [PATCH] =?UTF-8?q?fixed=2048cb355=20from=20https://gitee.com/tang?= =?UTF-8?q?-haojie/samples/pulls/1074=20=E6=96=B0=E5=A2=9EwithQ=E7=9A=84sa?= =?UTF-8?q?mple?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.project | 8 + .../CMakeLists.txt | 9 + .../README.md | 471 +++++++++++++++ .../README_5.0.3.alpha003.MD | 275 +++++++++ .../README_CN.md | 544 ++++++++++++++++++ .../data/.keep | 0 .../inc/model_process.h | 156 +++++ .../inc/sample_process.h | 45 ++ .../inc/utils.h | 52 ++ .../script/transferPic.py | 48 ++ .../scripts/host_version.conf | 4 + .../scripts/testcase_200dk.sh | 208 +++++++ .../scripts/testcase_300.sh | 208 +++++++ .../src/CMakeLists.txt | 82 +++ .../src/Makefile | 318 ++++++++++ .../src/acl.json | 1 + .../src/main.cpp | 33 ++ .../src/model_process.cpp | 400 +++++++++++++ .../src/sample_process.cpp | 288 ++++++++++ .../src/utils.cpp | 128 +++++ 20 files changed, 3278 insertions(+) create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/.project create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/CMakeLists.txt create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README.md create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_5.0.3.alpha003.MD create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_CN.md create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/data/.keep create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/model_process.h create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/sample_process.h create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/utils.h create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/script/transferPic.py create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/host_version.conf create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_200dk.sh create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_300.sh create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeLists.txt create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/Makefile create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/acl.json create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/main.cpp create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/model_process.cpp create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/sample_process.cpp create mode 100644 cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/utils.cpp diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/.project b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/.project new file mode 100644 index 000000000..c39109a4b --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/.project @@ -0,0 +1,8 @@ +{ + "type": "Ascend ACL App", + "project_type": "Custom", + "project_desc": "", + "target": "", + "target_id": "", + "adk_version": "" +} diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/CMakeLists.txt b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/CMakeLists.txt new file mode 100644 index 000000000..cf812eaca --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) + +# project information +project(ACL_RESNET50) + +add_subdirectory("./src") diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README.md b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README.md new file mode 100644 index 000000000..1f7d78ef6 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README.md @@ -0,0 +1,471 @@ +# Image Classification with Caffe ResNet-50 \(Synchronous Inference\) + +## Overview + +This sample shows how to classify images based on the Caffe ResNet-50 network \(single input with batch size = 1\). + +Specifically, + +1. Converts two .jpg images to the binary format by calling the **transferPic.py** script provided in the sample and resizes the images from 1024 x 683 to 224 x 224. +2. Loads the .om offline model to perform synchronous inference on the two images, processes the obtained inference results, and outputs the class index with the top 5 confidence value of each image. + + Convert the Caffe ResNet-50 model file into an offline model that adapts to the Ascend AI Processor in advance. + + +## Principles + +This sample involves the following key functions: + +- Initialization + - **aclInit**: initializes AscendCL. + - **aclFinalize**: deinitializes AscendCL. + +- Device management + - **aclrtSetDevice**: sets the compute device. + - **aclrtGetRunMode**: obtains the run mode of the Ascend AI Software Stack. The internal processing varies with the run mode. + - **aclrtResetDevice**: resets the compute device and cleans up all resources associated with the device. + +- **Context management** + - **aclrtCreateContext**: creates a context. + - **aclrtDestroyContext**: destroys a context. + +- Stream management + - **aclrtCreateStream**: creates a stream. + - **aclrtDestroyStream**: destroys a stream. + +- Memory management + - **aclrtMalloc**: allocates device memory. + - **aclrtFree**: frees device memory. + - **malloc**: allocates host memory. + - **free**: frees host memory. + +- Data transfer + + **aclrtMemcpy**: copies memory. + +- Model inference + - **aclmdlLoadFromFileWithQ**: loads a model from an .om file. + - **acltdtEnqueueData**: passes in the model input data and then performs model reasoning, performs asynchronous model inference. + - **acltdtDequeueData**: Get model output data, performs asynchronous model inference. + - **aclmdlUnload**: unloads a model. + +- Data postprocessing + + Provides sample code to process the model inference result and display the class indexes with top 5 confidence values of each image. + + The sample provides a user-defined API **DumpModelOutputResult**, which is used to write the model inference result to a file \(after the executable file is executed, the inference result file is generated in the directory of the executable file in the operating environment\). This API is not called by default. To call this API, you need to add the following code before the **OutputModelResult** call in **sample\_process.cpp** in advance. + + ``` + // Print the top 5 confidence values with indexes using DumpModelOutputResult + // if want to dump output result to file in the current directory + processModel.DumpModelOutputResult(); + processModel.OutputModelResult(); + ``` + + +## Directory Structure + +The sample directory is organized as follows: + +``` +├── data +│ ├── dog1_1024_683.jpg //Test image. Obtain the test image according to the guide and save it to the data directory. +│ ├── dog2_1024_683.jpg //Test image. Obtain the test image according to the guide and save it to the data directory. + +├── inc +│ ├── model_process.h //Header file that declares functions related to model processing +│ ├── sample_process.h //Header file that declares functions related to resource initialization and destruction +│ ├── utils.h //Header file that declares common functions (such as file reading function) + +├── script +│ ├── transferPic.py //Convert a .jpg image to a .bin file and resize the image from 1024 x 683 to 224 x 224. + +├── src +│ ├── acl.json //Configuration file for system initialization +│ ├── CMakeLists.txt //Build script +│ ├── main.cpp //Main function, which is the implementation file of image classification +│ ├── model_process.cpp //Implementation file of model processing functions +│ ├── sample_process.cpp //Implementation file of functions related to resource initialization and destruction +│ ├── utils.cpp //Implementation file of common functions (such as the file reading function) + +├── .project //Project information file, including the project type, project description, and type of the target device +├── CMakeLists.txt //Build script that calls the CMakeLists file in the src directory +``` + +## Environment Requirements + +- OS and architecture: CentOS 7.6 x86\_64, CentOS AArch64, or Ubuntu 18.04 x86\_64 +- Compiler: + - Ascend 310 EP/Ascend 710: g++ or aarch64-linux-gnu-g++ + - Atlas 200 DK: aarch64-linux-gnu-g++ + +- SoC: Ascend 310 AI Processor or Ascend 710 AI Processor +- Python and its dependency library: Python 3.7.5 and Pillow +- Ascend AI Software Stack deployed + +## Environment Variables + +- **Ascend 310 EP/Ascend 710:** + 1. In the development environment, set the environment variables on which model conversion depends. + + Replace _**$\{install\_path\}**_ with the actual Ascend-CANN-Toolkit installation path. + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 2. Set the header file path and library file path environment variables for the **src/CMakeLists.txt** build script in the development environment. + + The following is an example. Replace ****_$HOME/Ascend_**_**/ascend-toolkit/latest**_/_\{os\_arch\}_** with the ACLlib path under the Ascend-CANN-Toolkit directory of the corresponding architecture. + + - x86 operating environment: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux/acllib/lib64/stub + ``` + + - ARM operating environment: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub + ``` + + + Use the .so library files in the ****_$HOME/Ascend_**_**/ascend-toolkit/latest**_/_\{os\_arch\}_/acllib/lib64/stub** directory to build the code logic using AscendCL APIs, without depending on any .so library files of other components \(such as Driver\). At run time on the host, the app links to the .so library files in the ****_$HOME/Ascend_**_**/nnrt/latest**_/acllib/lib64** directory on the host through the configured environment variable and automatically links to the .so library files of other components. + + 3. Set the library path environment variable in the operating environment for app execution. + + The following is an example. Replace ****_$HOME/Ascend_**_**/nnrt/latest**_** with the ACLlib path. + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/nnrt/latest/acllib/lib64 + ``` + + +- **Atlas 200 DK:** + + You only need to set environment variables in the development environment. Environment variables in the operating environment have been set in the phase of preparing a bootable SD card. + + 1. In the development environment, set the environment variables on which model conversion depends. + + Replace _**$\{install\_path\}**_ with the actual Ascend-CANN-Toolkit installation path. + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 2. Set the header file path and library file path environment variables for the **src/CMakeLists.txt** build script in the development environment. + + The following is an example. Replace ****_$HOME/Ascend_**_**/ascend-toolkit/latest**_/arm64-linux** with the ACLlib path under the ARM Ascend-CANN-Toolkit directory. + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub + ``` + + The .so library files in the **_$HOME/Ascend_**_**/ascend-toolkit/latest**_**/arm64-linux/acllib/lib64/stub** directory are required to build code using AscendCL APIs, without depending on any .so library files of other components \(such as Driver\). At run time in the board environment, the app links to the .so library files in the **$HOME/Ascend/acllib/lib64** directory in the open-form ACLlib installation path in the board environment through the configured environment variable and automatically links to the .so library files of other components. + + + +## Build and Run \(Ascend310 EP/Ascend 710\) + +1. Convert your model. + 1. Log in to the development environment as the running user. + 2. Set environment variables. + + Replace _**$\{install\_path\}**_ with the Ascend-CANN-Toolkit installation path. + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 3. Prepare data. + + Download the .prototxt model file and .caffemodel pre-trained model file of the ResNet-50 network and upload the files to **/caffe\_model** under the sample directory in the development environment as the running user. If the directory does not exist, create it. + + Click [link](https://github.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE), find the download links in the **README.md** file. + + 4. Convert the ResNet-50 network to an .om offline model adapted to Ascend AI ProcessorHiSilicon SoC. + + Go to the sample directory and run the following command: + + ``` + atc --model=caffe_model/resnet50.prototxt --weight=caffe_model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=${soc_version} --input_format=NCHW --input_fp16_nodes=data -output_type=FP32 --out_nodes=prob:0 + ``` + + - **--model**: directory of the source model file. + - **--weight**: directory of the weight file. + - **--framework**: source framework type, selected from **0** \(Caffe\), **1** \(MindSpore\), **3** \(TensorFlow\), and **5** \(ONNX\). + - **--soc\_version**: SoC version, either **Ascend310** or **Ascend710**. + - **--input\_format**: input format. + - **--input\_fp16\_nodes**: input nodes to specify as FP16 nodes. + - **--output\_type** and **--out\_nodes**: specify the data type of the first output as float32. + - **--output**: directory for storing the generated **resnet50.om** file, that is, **/model** under the sample directory. The default path in the command example is recommended. To specify another path, you need to change the value of **omModelPath** in **sample\_process.cpp** before building the code. + + ``` + const char* omModelPath = "../model/resnet50.om"; + ``` + + + +2. Build the code. + 1. Go to the sample directory and create a directory for storing build outputs. For example, the directory created in this sample is **build/intermediates/host**. + + ``` + mkdir -p build/intermediates/host + ``` + + 2. Go to the **build/intermediates/host** directory and run the **cmake** command. + + Replace **../../../src** with the actual directory of **CMakeLists.txt**. + + - If the operating system architecture of the development environment is the same as that of the running environment, run the following commands to perform compilation. + + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + - If the operating system architecture of the development environment is different from that of the running environment, run the following commands to perform cross compilation. + + For example, if the development environment is x86 and the running environment is AArch64, run the following command: + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + + 3. Run the **make **command. The **main** executable file is generated in **/out** under the sample directory. + + ``` + make + ``` + + +3. Prepare input images. + 1. Obtain the input images of the sample from the following link and upload the obtained images to **/data** under the sample directory in the development environment as the running user. If the directory does not exist, create it. + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg) + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg) + + 2. Log in to the development environment as the running user. + 3. Go to the **/data** directory under the sample directory, run the **transferPic.py** script to convert the two .jpg images into .bin files, and resize the image from 1024 x 683 to 224 x 224. Find the generated .bin files in **/data** under the sample directory. + + ``` + python3.7.5 ../script/transferPic.py + ``` + + If the error message "ModuleNotFoundError: No module named'PIL'" is displayed during script execution, the Pillow library does not exist. In this case, run the **pip3.7.5 install Pillow --user** command to install the Pillow library. + + +4. Run the app. + 1. As the running user, upload the sample folder in the development environment to the operating environment \(host\), for example, **$HOME/acl\_resnet50**. + 2. Log in to the operating environment \(host\) as the running user. + 3. Go to the directory where the executable file **main** is located \(for example, **$HOME/acl\_resnet50/out**\) and grant execute permission on the **main** file in the directory. + + ``` + chmod +x main + ``` + + 4. Go to the directory where the executable file **main** is located \(for example, **$HOME/acl\_resnet50/out**\) and run the executable file. + + ``` + ./main + ``` + + The following messages indicate that the file is successfully executed. In the displayed information, index indicates the category ID, value indicates the maximum confidence level of the category. These values may vary according to the version and environment. + + ``` + [INFO] acl init success + [INFO] open device 0 success + [INFO] create context success + [INFO] create stream success + [INFO] load model ../model/resnet50.om success + [INFO] create model description success + [INFO] create model output success + [INFO] start to process file:../data/dog1_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[161] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] start to process file:../data/dog2_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[267] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] Unload model success, modelId is 1 + [INFO] execute sample success + [INFO] end to destroy stream + [INFO] end to destroy context + [INFO] end to reset device is 0 + ``` + + + +## Build and Run \(Atlas 200 DK\) + +1. Convert your model. + 1. Log in to the development environment as the running user. + 2. Set environment variables. + + Replace _**$\{install\_path\}**_ with the Ascend-CANN-Toolkit installation path. + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 3. Prepare data. + + Download the .prototxt model file and .caffemodel pre-trained model file of the ResNet-50 network and upload the files to **/caffe\_model** under the sample directory in the development environment as the running user. If the directory does not exist, create it. + + Click [link](https://github.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE), find the download links in the **README.md** file. + + 4. Convert the ResNet-50 network to an .om offline model adapted to Ascend AI ProcessorHiSilicon SoC. + + Go to the sample directory and run the following command: + + ``` + atc --model=caffe_model/resnet50.prototxt --weight=caffe_model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=${soc_version} --input_format=NCHW --input_fp16_nodes=data -output_type=FP32 --out_nodes=prob:0 + ``` + + - **--model**: directory of the source model file. + - **--weight**: directory of the weight file. + - **--framework**: source framework type, selected from **0** \(Caffe\), **1** \(MindSpore\), **3** \(TensorFlow\), and **5** \(ONNX\). + - **--soc\_version**: SoC version, either **Ascend310** or **Ascend710**. + - **--input\_format**: input format. + - **--input\_fp16\_nodes**: input nodes to specify as FP16 nodes. + - **--output\_type** and **--out\_nodes**: specify the data type of the first output as float32. + - **--output**: directory for storing the generated **resnet50.om** file, that is, **/model** under the sample directory. The default path in the command example is recommended. To specify another path, you need to change the value of **omModelPath** in **sample\_process.cpp** before building the code. + + ``` + const char* omModelPath = "../model/resnet50.om"; + ``` + + + +2. Build the code. + 1. Log in to the development environment as the running user. + 2. Go to the **acl\_resnet50/data** directory, run the **transferPic.py** script to convert the .jpg image to a .bin file, and resize the image from 1024 x 683 to 224 x 224. Find the generated .bin files in **/data** under the sample directory. + + ``` + python3.7.5 ../script/transferPic.py + ``` + + If the error message "ModuleNotFoundError: No module named'PIL'" is displayed during script execution, the Pillow library does not exist. In this case, run the **pip3.7.5 install Pillow --user** command to install the Pillow library. + + 3. Go to the sample directory and create a directory for storing build outputs. For example, the directory created in this sample is **build/intermediates/minirc**. + + ``` + mkdir -p build/intermediates/minirc + ``` + + 4. Go to the **build/intermediates/minirc** directory and run the **cmake** command. + + Replace **../../../src** with the actual directory of **CMakeLists.txt**. + + ``` + cd build/intermediates/minirc + cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + 5. Run the **make **command. The **main** executable file is generated in **/out** under the sample directory. + + ``` + make + ``` + + +3. Prepare input images. + 1. Obtain the input images of the sample from the following link and upload the obtained images to **/data** under the sample directory in the development environment as the running user. If the directory does not exist, create it. + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg) + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg) + + 2. Log in to the development environment as the running user. + 3. Go to the **/data** directory under the sample directory, run the **transferPic.py** script to convert the two .jpg images into .bin files, and resize the image from 1024 x 683 to 224 x 224. Find the generated .bin files in **/data** under the sample directory. + + ``` + python3.7.5 ../script/transferPic.py + ``` + + If the error message "ModuleNotFoundError: No module named'PIL'" is displayed during script execution, the Pillow library does not exist. In this case, run the **pip3.7.5 install Pillow --user** command to install the Pillow library. + + +4. Run the app. + 1. As the running user, upload the sample folder in the development environment to the board environment, for example, **$HOME/acl\_resnet50**. + 2. Log in to the board environment as the running user. + 3. Set environment variables. + + The following is an example only. Replace the path with the actual one. + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/acllib/lib64 + ``` + + 4. Go to the directory where the executable file **main** is located \(for example, **$HOME/acl\_resnet50/out**\) and grant execute permission on the **main** file in the directory. + + ``` + chmod +x main + ``` + + 5. Go to the directory where the executable file **main** is located \(for example, **$HOME/acl\_resnet50/out**\) and run the executable file. + + ``` + ./main + ``` + + The following messages indicate that the file is successfully executed. In the displayed information, index indicates the category ID, value indicates the maximum confidence level of the category. These values may vary according to the version and environment. + + ``` + [INFO] acl init success + [INFO] set device 0 success + [INFO] create context success + [INFO] create stream success + [INFO] create input queue success + [INFO] create output queue success + [INFO] load model ../model/resnet50.om success + [INFO] create model description success + [INFO] start to process file:../data/dog1_1024_683.bin + [INFO] enqueue success + [INFO] dequeue success + [INFO] top 1: index[161] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] start to process file:../data/dog2_1024_683.bin + [INFO] enqueue success + [INFO] dequeue success + [INFO] top 1: index[267] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] destroy input queue success + [INFO] destroy output queue success + [INFO] destroy model description success + [INFO] Unload model success, modelId is 1 + [INFO] execute sample success + [INFO] end to destroy stream + [INFO] end to destroy context + [INFO] end to reset device is 0 + ``` + + + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_5.0.3.alpha003.MD b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_5.0.3.alpha003.MD new file mode 100644 index 000000000..53298caa2 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_5.0.3.alpha003.MD @@ -0,0 +1,275 @@ +# 基于Caffe ResNet-50网络实现图片分类(同步推理) + +## 功能描述 + +该样例主要是基于Caffe ResNet-50网络(单输入、单Batch)实现图片分类的功能。 + +在该样例中: + +1. 先使用样例提供的脚本transferPic.py,将2张\*.jpg图片都转换为\*.bin格式,同时将图片从1024\*683的分辨率缩放为224\*224。 +2. 加载离线模型om文件,对2张图片进行同步推理,分别得到推理结果,再对推理结果进行处理,输出top5置信度的类别标识。 + + 在加载离线模型前,提前将Caffe ResNet-50网络的模型文件转换为适配昇腾AI处理器的离线模型。 + + +## 原理介绍 + +在该Sample中,涉及的关键功能点,如下所示: + +- **初始化** + - 调用aclInit接口初始化AscendCL配置。 + - 调用aclFinalize接口实现AscendCL去初始化。 + +- **Device管理** + - 调用aclrtSetDevice接口指定用于运算的Device。 + - 调用aclrtGetRunMode接口获取昇腾AI软件栈的运行模式,根据运行模式的不同,内部处理流程不同。 + - 调用aclrtResetDevice接口复位当前运算的Device,回收Device上的资源。 + +- **Context管理** + - 调用aclrtCreateContext接口创建Context。 + - 调用aclrtDestroyContext接口销毁Context。 + +- **Stream管理** + - 调用aclrtCreateStream接口创建Stream。 + - 调用aclrtDestroyStream接口销毁Stream。 + +- **内存管理** + - 调用aclrtMalloc接口申请Device上的内存。 + - 调用aclrtFree接口释放Device上的内存。 + +- **数据传输** + + 调用aclrtMemcpy接口通过内存复制的方式实现数据传输。 + +- **模型推理** + - 调用aclmdlLoadFromFileWithMem接口从\*.om文件加载模型。 + - 调用aclmdlExecute接口执行模型推理,同步接口。 + - 调用aclmdlUnload接口卸载模型。 + +- **数据后处理** + + 提供样例代码,处理模型推理的结果,直接在终端上显示top5置信度的类别编号。 + + 另外,样例中提供了自定义接口DumpModelOutputResult,用于将模型推理的结果写入文件(运行可执行文件后,推理结果文件在运行环境上的应用可执行文件的同级目录下),默认未调用该接口,用户可在sample\_process.cpp中,在调用OutputModelResult接口前,增加如下代码调用DumpModelOutputResult接口: + + ``` + // print the top 5 confidence values with indexes.use function DumpModelOutputResult + // if want to dump output result to file in the current directory + processModel.DumpModelOutputResult(); + processModel.OutputModelResult(); + ``` + + +## 目录结构 + +样例代码结构如下所示。 + +``` +├── data +│ ├── dog1_1024_683.jpg //测试数据,需要按指导获取测试图片,放到data目录下 +│ ├── dog2_1024_683.jpg //测试数据,需要按指导获取测试图片,放到data目录下 + +├── inc +│ ├── model_process.h //声明模型处理相关函数的头文件 +│ ├── sample_process.h //声明资源初始化/销毁相关函数的头文件 +│ ├── utils.h //声明公共函数(例如:文件读取函数)的头文件 + +├── script +│ ├── transferPic.py //将*.jpg转换为*.bin,同时将图片从1024*683的分辨率缩放为224*224 + +├── src +│ ├── acl.json //系统初始化的配置文件 +│ ├── CMakeLists.txt //编译脚本 +│ ├── main.cpp //主函数,图片分类功能的实现文件 +│ ├── model_process.cpp //模型处理相关函数的实现文件 +│ ├── sample_process.cpp //资源初始化/销毁相关函数的实现文件 +│ ├── utils.cpp //公共函数(例如:文件读取函数)的实现文件 + +├── .project //工程信息文件,包含工程类型、工程描述、运行目标设备类型等 +├── CMakeLists.txt //编译脚本,调用src目录下的CMakeLists文件 +``` + +## 环境要求 + +- 操作系统及架构:CentOS 7.6 x86\_64、CentOS aarch64、Ubuntu 18.04 x86\_64、EulerOS x86、EulerOS aarch64 +- 编译器: + - Ascend 310 EP/Ascend 710/Ascend 910形态编译器:g++ 或 aarch64-linux-gnu-g++ + + - Atlas 200 DK编译器:aarch64-linux-gnu-g++ + +- 芯片:Ascend 310、Ascend 710、Ascend 910 + +- python及依赖的库:python3.7.5、Pillow库 +- 已在环境上部署昇腾AI软件栈。 + + +## 获取样例 + +单击[Link](https://gitee.com/ascend/samples/tree/master/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classification)下载样例包后,解压缩样例包,从“cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classification”目录下获取本样例的代码。 + + +## 配置环境变量 + +1. 安装CANN软件后,使用CANN运行用户编译、运行应用前,需以运行用户登录环境,设置公共环境变量。 + 如下为设置环境变量的命令,其中,$\{install\_path\}表示CANN软件的安装目录,以root用户安装CANN软件时,默认安装目录为“/usr/local/Ascend”;以普通用户安装CANN软件时,默认安装目录为“普通用户家目录/Ascend”。 + ``` + source ${install_path}/bin/setenv.bash + ``` + +2. 开发环境上,以运行用户登录环境,设置模型转换依赖的环境变量。 + 如下为设置环境变量的命令,其中,Python3.7.5安装路径请根据实际情况替换。 + ``` + export LD_LIBRARY_PATH=/usr/local/python3.7.5/lib:$LD_LIBRARY_PATH + export PATH=/usr/local/python3.7.5/bin:$PATH + ``` + + +3. 开发环境上,以运行用户登录环境,设置编译依赖的环境变量,编译脚本src/CMakeLists.txt通过环境变量所设置的头文件、库文件的路径来编译代码。 + 如下为设置环境变量的命令,其中,$\{install\_path\}表示CANN软件的安装目录。 + ``` + export DDK_PATH=${install_path} + export NPU_HOST_LIB=${install_path}/acllib/lib64/stub + ``` + + 使用“lib64/stub”目录下的\*.so库,是为了编译基于AscendCL接口的代码逻辑时,不依赖其它组件(例如Driver)的任何\*.so库。编译通过后,运行应用时,会根据环境变量LD\_LIBRARY\_PATH链接到“acllib/lib64“目录下的\*.so库,并自动链接到依赖其它组件的\*.so库。 + + + +## 编译运行 + +1. 模型转换。 + 1. 以运行用户登录开发环境。 + + 2. 准备数据。 + + 您可以从以下链接中获取ResNet-50网络的模型文件(\*.prototxt)、预训练模型文件(\*.caffemodel),并以运行用户将获取的文件上传至开发环境的“样例目录/caffe\_model“目录下。如果目录不存在,需要自行创建。 + + - 从gitee上获取:单击[Link](https://gitee.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + - 从GitHub上获取:单击[Link](https://github.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + + 3. 将ResNet-50网络转换为适配昇腾AI处理器的离线模型(\*.om文件)。 + + 切换到样例目录,执行如下命令(以Ascend310芯片为例): + + ``` + atc --model=caffe_model/resnet50.prototxt --weight=caffe_model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=Ascend310 --input_format=NCHW --input_fp16_nodes=data -output_type=FP32 --out_nodes=prob:0 + ``` + + - --model:原始模型文件路径。 + - --weight:权重文件路径。 + - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。 + - --soc\_version: + - Ascend 310芯片,此处配置为Ascend310。 + - Ascend 710芯片,此处配置为Ascend710。 + - Ascend 910芯片,此处配置为Ascend910A或Ascend910B或Ascend910ProA或Ascend910ProB或Ascend910PremiumA,其中,Pro或Premium表示芯片性能提升等级、A或B表示PartialGood等级,请根据实际情况选择。 + + - --input\_format:输入数据的Format。 + - --input\_fp16\_nodes:指定输入数据类型为FP16的输入节点名称。 + - --output\_type和--out\_nodes:这2个参数配合使用,指定prob节点的第一个输出的数据类型为float32。 + - --output:生成的resnet50.om文件存放在“样例目录/model“目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_process.cpp中的omModelPath参数值。 + + ``` + const char* omModelPath = "../model/resnet50.om"; + ``` + + + +2. 编译代码。 + 1. 切换到样例目录,创建目录用于存放编译文件,例如,本文中,创建的目录为“build/intermediates/host“。 + + ``` + mkdir -p build/intermediates/host + ``` + + 2. 切换到“build/intermediates/host“目录,执行**cmake**生成编译文件。 + + “../../../src“表示CMakeLists.txt文件所在的目录,请根据实际目录层级修改。 + + - 当开发环境与运行环境操作系统架构相同时,执行如下命令编译。 + + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + - 当开发环境与运行环境操作系统架构不同时,执行以下命令进行交叉编译。 + + 例如,当开发环境为X86架构,运行环境为AArch64架构时,执行以下命令进行交叉编译。 + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + + 3. 执行**make**命令,生成的可执行文件main在“样例目录/out“目录下。 + + ``` + make + ``` + + +3. 准备输入图片。 + 1. 请从以下链接获取该样例的输入图片,并以运行用户将获取的文件上传至开发环境的“样例目录/data“目录下。如果目录不存在,需自行创建。 + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg) + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg) + + 2. 以运行用户登录开发环境。 + 3. 切换到“样例目录/data“目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在“样例目录/data“目录下生成2个\*.bin文件。 + + ``` + python3.7.5 ../script/transferPic.py + ``` + + 如果执行脚本报错“ModuleNotFoundError: No module named 'PIL'”,则表示缺少Pillow库,请使用**pip3.7.5 install Pillow --user**命令安装Pillow库。 + + +4. 运行应用。 + 1. 以运行用户将开发环境的样例目录及目录下的文件上传到运行环境(Host),例如“$HOME/acl\_resnet50”。 + 2. 以运行用户登录运行环境(Host)。 + 3. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,给该目录下的main文件加执行权限。 + + ``` + chmod +x main + ``` + + 4. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,运行可执行文件。 + + ``` + ./main + ``` + + 执行成功后,在屏幕上的关键提示信息示例如下,提示信息中的index表示类别标识、value表示该分类的最大置信度,这些值可能会根据版本、环境有所不同,请以实际情况为准: + + ``` + [INFO] acl init success + [INFO] open device 0 success + [INFO] create context success + [INFO] create stream success + [INFO] load model ../model/resnet50.om success + [INFO] create model description success + [INFO] create model output success + [INFO] start to process file:../data/dog1_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[161] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] start to process file:../data/dog2_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[267] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] Unload model success, modelId is 1 + [INFO] execute sample success + [INFO] end to destroy stream + [INFO] end to destroy context + [INFO] end to reset device is 0 + ``` + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_CN.md b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_CN.md new file mode 100644 index 000000000..6d6da939c --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/README_CN.md @@ -0,0 +1,544 @@ +# 基于Caffe ResNet-50网络实现图片分类(同步推理) + +## 功能描述 + +该样例主要是基于Caffe ResNet-50网络(单输入、单Batch)实现图片分类的功能。 + +在该样例中: + +1. 先使用样例提供的脚本transferPic.py,将2张\*.jpg图片都转换为\*.bin格式,同时将图片从1024\*683的分辨率缩放为224\*224。 +2. 加载离线模型om文件,对2张图片进行同步推理,分别得到推理结果,再对推理结果进行处理,输出top5置信度的类别标识。 + + 在加载离线模型前,提前将Caffe ResNet-50网络的模型文件转换为适配昇腾AI处理器的离线模型。 + + +## 原理介绍 + +在该Sample中,涉及的关键功能点,如下所示: + +- **初始化** + - 调用aclInit接口初始化AscendCL配置。 + - 调用aclFinalize接口实现AscendCL去初始化。 + +- **Device管理** + - 调用aclrtSetDevice接口指定用于运算的Device。 + - 调用aclrtGetRunMode接口获取昇腾AI软件栈的运行模式,根据运行模式的不同,内部处理流程不同。 + - 调用aclrtResetDevice接口复位当前运算的Device,回收Device上的资源。 + +- **Context管理** + - 调用aclrtCreateContext接口创建Context。 + - 调用aclrtDestroyContext接口销毁Context。 + +- **Stream管理** + - 调用aclrtCreateStream接口创建Stream。 + - 调用aclrtDestroyStream接口销毁Stream。 + +- **内存管理** + - 调用aclrtMalloc接口申请Device上的内存。 + - 调用aclrtFree接口释放Device上的内存。 + - 调用malloc接口申请Host上的内存。 + - 调用free接口释放Host上的内存。 + +- **数据传输** + + 调用aclrtMemcpy接口通过内存复制的方式实现数据传输。 + +- **模型推理** + - 调用aclmdlLoadFromFileWithQ接口从\*.om文件加载模型。 + - 调用acltdtEnqueueData接口将模型输入数据传入然后执行模型推理,异步接口。 + - 调用acltdtDequeueData接口获取模型输出数据,异步接口。 + - 调用aclmdlUnload接口卸载模型。 + +- **数据后处理** + + 提供样例代码,处理模型推理的结果,直接在终端上显示top5置信度的类别编号。 + + 另外,样例中提供了自定义接口DumpModelOutputResult,用于将模型推理的结果写入文件(运行可执行文件后,推理结果文件在运行环境上的应用可执行文件的同级目录下),默认未调用该接口,用户可在sample\_process.cpp中,在调用OutputModelResult接口前,增加如下代码调用DumpModelOutputResult接口: + + ``` + // print the top 5 confidence values with indexes.use function DumpModelOutputResult + // if want to dump output result to file in the current directory + processModel.DumpModelOutputResult(); + processModel.OutputModelResult(); + ``` + + +## 目录结构 + +样例代码结构如下所示。 + +``` +├── data +│ ├── dog1_1024_683.jpg //测试数据,需要按指导获取测试图片,放到data目录下 +│ ├── dog2_1024_683.jpg //测试数据,需要按指导获取测试图片,放到data目录下 + +├── inc +│ ├── model_process.h //声明模型处理相关函数的头文件 +│ ├── sample_process.h //声明资源初始化/销毁相关函数的头文件 +│ ├── utils.h //声明公共函数(例如:文件读取函数)的头文件 + +├── script +│ ├── transferPic.py //将*.jpg转换为*.bin,同时将图片从1024*683的分辨率缩放为224*224 + +├── src +│ ├── acl.json //系统初始化的配置文件 +│ ├── CMakeLists.txt //编译脚本 +│ ├── main.cpp //主函数,图片分类功能的实现文件 +│ ├── model_process.cpp //模型处理相关函数的实现文件 +│ ├── sample_process.cpp //资源初始化/销毁相关函数的实现文件 +│ ├── utils.cpp //公共函数(例如:文件读取函数)的实现文件 + +├── .project //工程信息文件,包含工程类型、工程描述、运行目标设备类型等 +├── CMakeLists.txt //编译脚本,调用src目录下的CMakeLists文件 +``` + +## 环境要求 + +- 操作系统及架构:CentOS 7.6 x86\_64、CentOS aarch64、Ubuntu 18.04 x86\_64、EulerOS x86、EulerOS aarch64 +- 编译器: + - Ascend 310 EP/Ascend 710/Ascend 910形态编译器:g++ 或 aarch64-linux-gnu-g++ + + - Atlas 200 DK编译器:aarch64-linux-gnu-g++ + +- 芯片:Ascend 310、Ascend 710、Ascend 910 + +- python及依赖的库:python3.7.5、Pillow库 +- 已在环境上部署昇腾AI软件栈。 + +## 配置环境变量 + +- **Ascend 310 EP/Ascend 910:** + 1. 开发环境上,设置模型转换依赖的环境变量。 + + $\{install\_path\}表示开发套件包Ascend-cann-toolkit所在的路径。 + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 2. 开发环境上,设置环境变量,编译脚本src/CMakeLists.txt通过环境变量所设置的头文件、库文件的路径来编译代码。 + + 如下为设置环境变量的示例,请将$HOME/Ascend/ascend-toolkit/latest/_\{os\_arch\}_替换为开发套件包Ascend-cann-toolkit下对应架构的FwkACLlib的路径。 + + - 当运行环境操作系统架构为x86时,执行以下命令: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux/fwkacllib/lib64/stub + ``` + + - 当运行环境操作系统架构为Arm时,执行以下命令: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/arm64-linux/fwkacllib/lib64/stub + ``` + + + 使用“$HOME/Ascend/ascend-toolkit/latest/_\{os\_arch\}_/fwkacllib/lib64/stub”目录下的\*.so库,是为了编译基于AscendCL接口的代码逻辑时,不依赖其它组件(例如Driver)的任何\*.so库。编译通过后,在Host上运行应用时,会根据环境变量LD\_LIBRARY\_PATH链接到“fwkacllib/lib64“或“acllib/lib64“目录下的\*.so库,并自动链接到依赖其它组件的\*.so库。 + + 设置环境变量后,还需修改src/CMakeLists.txt文件中的如下配置段,将“**acllib**”修改为“**fwkacllib**”。 + + ``` + # Header path + include_directories( + ${INC_PATH}/acllib/include/ + ../inc/ + ) + ``` + + 3. 运行环境上,设置环境变量,运行应用时需要根据环境变量找到对应的库文件。 + - 若运行环境上安装的是开发套件包Ascend-cann-toolkit,环境变量设置如下: + + 如下为设置环境变量的示例,请将$HOME/Ascend/ascend-toolkit/latest替换为FwkACLlib的路径。 + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/ascend-toolkit/latest/fwkacllib/lib64 + ``` + + - 若运行环境上安装的是Ascend-cann-nnrt包,环境变量设置如下: + + 如下为设置环境变量的示例,请将$HOME/Ascend/nnrt/latest替换为ACLlib的路径。 + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/nnrt/latest/acllib/lib64 + ``` + + + +- **Ascend 710:** + 1. 开发环境上,设置模型转换依赖的环境变量。 + + $\{install\_path\}表示开发套件包Ascend-cann-toolkit所在的路径。 + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 2. 开发环境上,设置环境变量,编译脚本src/CMakeLists.txt通过环境变量所设置的头文件、库文件的路径来编译代码。 + + 如下为设置环境变量的示例,请将$HOME/Ascend/ascend-toolkit/latest/_\{os\_arch\}_替换为开发套件包Ascend-cann-toolkit下对应架构的ACLlib的路径。 + + - 当运行环境操作系统架构为x86时,执行以下命令: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/x86_64-linux/acllib/lib64/stub + ``` + + - 当运行环境操作系统架构为Arm时,执行以下命令: + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub + ``` + + + 使用“$HOME/Ascend/ascend-toolkit/latest/_\{os\_arch\}_/acllib/lib64/stub”目录下的\*.so库,是为了编译基于AscendCL接口的代码逻辑时,不依赖其它组件(例如Driver)的任何\*.so库。编译通过后,在Host上运行应用时,会根据环境变量LD\_LIBRARY\_PATH链接到“$HOME/Ascend/nnrt/latest/acllib/lib64”目录下的\*.so库,并自动链接到依赖其它组件的\*.so库。 + + 3. 运行环境上,设置环境变量,运行应用时需要根据环境变量找到对应的库文件。 + + 如下为设置环境变量的示例,请将$HOME/Ascend/nnrt/latest替换为ACLlib的路径。 + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/nnrt/latest/acllib/lib64 + ``` + + +- **Atlas 200 DK:** + + 仅需在开发环境上设置环境变量,运行环境上的环境变量在制卡时已配置,此处无需单独配置。 + + 1. 开发环境上,设置模型转换依赖的环境变量。 + + $\{install\_path\}表示开发套件包Ascend-cann-toolkit所在的路径。 + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 2. 开发环境上,设置环境变量,编译脚本src/CMakeLists.txt通过环境变量所设置的头文件、库文件的路径来编译代码。 + + 如下为设置环境变量的示例,请将$HOME/Ascend/ascend-toolkit/latest/arm64-linux替换为开发套件包Ascend-cann-toolkit下Arm架构的ACLlib的路径。 + + ``` + export DDK_PATH=$HOME/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=$HOME/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub + ``` + + 使用“$HOME/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64/stub”目录下的\*.so库,是为了编译基于AscendCL接口的代码逻辑时,不依赖其它组件(例如Driver)的任何\*.so库。编译通过后,在板端环境上运行应用时,会根据环境变量LD\_LIBRARY\_PATH链接到“$HOME/Ascend/acllib/lib64”目录下的\*.so库,并自动链接到依赖其它组件的\*.so库。 + + + +## 编译运行(Ascend 310 EP/Ascend 710/Ascend 910) + +1. 模型转换。 + 1. 以运行用户登录开发环境。 + 2. 设置环境变量。 + + $\{install\_path\}表示开发套件包Ascend-cann-toolkit的安装路径。 + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 3. 准备数据。 + + 您可以从以下链接中获取ResNet-50网络的模型文件(\*.prototxt)、预训练模型文件(\*.caffemodel),并以运行用户将获取的文件上传至开发环境的“样例目录/caffe\_model“目录下。如果目录不存在,需要自行创建。 + + - 从gitee上获取:单击[Link](https://gitee.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + - 从GitHub上获取:单击[Link](https://github.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + + 4. 将ResNet-50网络转换为适配昇腾AI处理器的离线模型适配海思SoC的离线模型(\*.om文件)。 + + 切换到样例目录,执行如下命令: + + ``` + atc --model=caffe_model/resnet50.prototxt --weight=caffe_model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=${soc_version} --input_format=NCHW --input_fp16_nodes=data -output_type=FP32 --out_nodes=prob:0 + ``` + + - --model:原始模型文件路径。 + - --weight:权重文件路径。 + - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。 + - --soc\_version: + - Ascend 310芯片,此处配置为Ascend310。 + - Ascend 710芯片,此处配置为Ascend710。 + - Ascend 910芯片,此处配置为Ascend910A或Ascend910B或Ascend910ProA或Ascend910ProB或Ascend910PremiumA,其中,Pro或Premium表示芯片性能提升等级、A或B表示PartialGood等级,请根据实际情况选择。 + + - --input\_format:输入数据的Format。 + - --input\_fp16\_nodes:指定输入数据类型为FP16的输入节点名称。 + - --output\_type和--out\_nodes:这2个参数配合使用,指定prob节点的第一个输出的数据类型为float32。 + - --output:生成的resnet50.om文件存放在“样例目录/model“目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_process.cpp中的omModelPath参数值。 + + ``` + const char* omModelPath = "../model/resnet50.om"; + ``` + + + +2. 编译代码。 + 1. 切换到样例目录,创建目录用于存放编译文件,例如,本文中,创建的目录为“build/intermediates/host“。 + + ``` + mkdir -p build/intermediates/host + ``` + + 2. 切换到“build/intermediates/host“目录,执行**cmake**生成编译文件。 + + “../../../src“表示CMakeLists.txt文件所在的目录,请根据实际目录层级修改。 + + - 当开发环境与运行环境操作系统架构相同时,执行如下命令编译。 + + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + - 当开发环境与运行环境操作系统架构不同时,执行以下命令进行交叉编译。 + + 例如,当开发环境为X86架构,运行环境为AArch64架构时,执行以下命令进行交叉编译。 + ``` + cd build/intermediates/host + cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + + 3. 执行**make**命令,生成的可执行文件main在“样例目录/out“目录下。 + + ``` + make + ``` + + +3. 准备输入图片。 + 1. 请从以下链接获取该样例的输入图片,并以运行用户将获取的文件上传至开发环境的“样例目录/data“目录下。如果目录不存在,需自行创建。 + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg) + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg) + + 2. 以运行用户登录开发环境。 + 3. 切换到“样例目录/data“目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在“样例目录/data“目录下生成2个\*.bin文件。 + + ``` + python3.7.5 ../script/transferPic.py + ``` + + 如果执行脚本报错“ModuleNotFoundError: No module named 'PIL'”,则表示缺少Pillow库,请使用**pip3.7.5 install Pillow --user**命令安装Pillow库。 + + +4. 运行应用。 + 1. 以运行用户将开发环境的样例目录及目录下的文件上传到运行环境(Host),例如“$HOME/acl\_resnet50”。 + 2. 以运行用户登录运行环境(Host)。 + 3. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,给该目录下的main文件加执行权限。 + + ``` + chmod +x main + ``` + + 4. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,运行可执行文件。 + + ``` + ./main + ``` + + 执行成功后,在屏幕上的关键提示信息示例如下,提示信息中的index表示类别标识、value表示该分类的最大置信度,这些值可能会根据版本、环境有所不同,请以实际情况为准: + + ``` + [INFO] acl init success + [INFO] set device 0 success + [INFO] create context success + [INFO] create stream success + [INFO] create input queue success + [INFO] create output queue success + [INFO] load model ../model/resnet50.om success + [INFO] create model description success + [INFO] start to process file:../data/dog1_1024_683.bin + [INFO] enqueue success + [INFO] dequeue success + [INFO] top 1: index[161] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] start to process file:../data/dog2_1024_683.bin + [INFO] enqueue success + [INFO] dequeue success + [INFO] top 1: index[267] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] destroy input queue success + [INFO] destroy output queue success + [INFO] destroy model description success + [INFO] Unload model success, modelId is 1 + [INFO] execute sample success + [INFO] end to destroy stream + [INFO] end to destroy context + [INFO] end to reset device is 0 + ``` + + + +## 编译运行(Atlas 200 DK) + +1. 模型转换。 + 1. 以运行用户登录开发环境。 + 2. 设置环境变量。 + + $\{install\_path\}表示开发套件包Ascend-cann-toolkit的安装路径。 + + ``` + export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + ``` + + 3. 准备数据。 + + 您可以从以下链接中获取ResNet-50网络的模型文件(\*.prototxt)、预训练模型文件(\*.caffemodel),并以运行用户将获取的文件上传至开发环境的“样例目录/caffe\_model“目录下。如果目录不存在,需要自行创建。 + + - 从gitee上获取:单击[Link](https://gitee.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + - 从GitHub上获取:单击[Link](https://github.com/ascend/modelzoo/tree/master/contrib/TensorFlow/Research/cv/resnet50/ATC_resnet50_caffe_AE),查看README.md,查找获取原始模型的链接。 + + + 4. 将ResNet-50网络转换为适配昇腾AI处理器的离线模型适配海思SoC的离线模型(\*.om文件)。 + + 切换到样例目录,执行如下命令: + + ``` + atc --model=caffe_model/resnet50.prototxt --weight=caffe_model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=${soc_version} --input_format=NCHW --input_fp16_nodes=data -output_type=FP32 --out_nodes=prob:0 + ``` + + - --model:原始模型文件路径。 + - --weight:权重文件路径。 + - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。 + - --soc\_version: + - Ascend 310芯片,此处配置为Ascend310。 + - Ascend 710芯片,此处配置为Ascend710。 + - Ascend 910芯片,此处配置为Ascend910A或Ascend910B或Ascend910ProA或Ascend910ProB或Ascend910PremiumA,其中,Pro或Premium表示芯片性能提升等级、A或B表示PartialGood等级,请根据实际情况选择。 + + - --input\_format:输入数据的Format。 + - --input\_fp16\_nodes:指定输入数据类型为FP16的输入节点名称。 + - --output\_type和--out\_nodes:这2个参数配合使用,指定prob节点的第一个输出的数据类型为float32。 + - --output:生成的resnet50.om文件存放在“样例目录/model“目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_process.cpp中的omModelPath参数值。 + + ``` + const char* omModelPath = "../model/resnet50.om"; + ``` + + + +2. 编译代码。 + 1. 以运行用户登录开发环境。 + 2. 切换到“acl\_resnet50/data“目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在“样例目录/data“目录下生成2个\*.bin文件。 + + ``` + python3.7.5 ../script/transferPic.py + ``` + + 如果执行脚本报错“ModuleNotFoundError: No module named 'PIL'”,则表示缺少Pillow库,请使用**pip3.7.5 install Pillow --user**命令安装Pillow库。 + + 3. 切换到样例目录,创建目录用于存放编译文件,例如,本文中,创建的目录为“build/intermediates/minirc“。 + + ``` + mkdir -p build/intermediates/minirc + ``` + + 4. 切换到“build/intermediates/minirc“目录,执行**cmake**生成编译文件。 + + “../../../src“表示CMakeLists.txt文件所在的目录,请根据实际目录层级修改。 + + ``` + cd build/intermediates/minirc + cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + ``` + + 5. 执行**make**命令,生成的可执行文件main在“样例目录/out“目录下。 + + ``` + make + ``` + + +3. 准备输入图片。 + 1. 请从以下链接获取该样例的输入图片,并以运行用户将获取的文件上传至开发环境的“样例目录/data“目录下。如果目录不存在,需自行创建。 + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg) + + [https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg) + + 2. 以运行用户登录开发环境。 + 3. 切换到“样例目录/data“目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在“样例目录/data“目录下生成2个\*.bin文件。 + + ``` + python3.7.5 ../script/transferPic.py + ``` + + 如果执行脚本报错“ModuleNotFoundError: No module named 'PIL'”,则表示缺少Pillow库,请使用**pip3.7.5 install Pillow --user**命令安装Pillow库。 + + +4. 运行应用。 + 1. 以运行用户将开发环境的样例目录及目录下的文件上传到板端环境,例如“$HOME/acl\_resnet50”。 + 2. 以运行用户登录板端环境。 + 3. 设置环境变量。 + + 如下为设置环境变量的示例,请根据实际安装情况替换路径。 + + ``` + export LD_LIBRARY_PATH=$HOME/Ascend/acllib/lib64 + ``` + + 4. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,给该目录下的main文件加执行权限。 + + ``` + chmod +x main + ``` + + 5. 切换到可执行文件main所在的目录,例如“$HOME/acl\_resnet50/out”,运行可执行文件。 + + ``` + ./main + ``` + + 执行成功后,在屏幕上的关键提示信息示例如下,提示信息中的index表示类别标识、value表示该分类的最大置信度,这些值可能会根据版本、环境有所不同,请以实际情况为准: + + ``` + [INFO] acl init success + [INFO] open device 0 success + [INFO] create context success + [INFO] create stream success + [INFO] load model ../model/resnet50.om success + [INFO] create model description success + [INFO] create model output success + [INFO] start to process file:../data/dog1_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[161] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] start to process file:../data/dog2_1024_683.bin + [INFO] model execute success + [INFO] top 1: index[267] value[xxxxxx] + [INFO] top 2: index[xxx] value[xxxxxx] + [INFO] top 3: index[xxx] value[xxxxxx] + [INFO] top 4: index[xxx] value[xxxxxx] + [INFO] top 5: index[xxx] value[xxxxxx] + [INFO] output data success + [INFO] Unload model success, modelId is 1 + [INFO] execute sample success + [INFO] end to destroy stream + [INFO] end to destroy context + [INFO] end to reset device is 0 + ``` + + + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/data/.keep b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/data/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/model_process.h b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/model_process.h new file mode 100644 index 000000000..c913cda49 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/model_process.h @@ -0,0 +1,156 @@ +/** +* @file model_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include +#include +#include "utils.h" +#include "acl/acl.h" +#include "acl/acl_tdt_queue.h" + +typedef struct { + char data[5]; +} UserData; + +typedef struct { + int32_t index; + void* data; + size_t len; + size_t* retDataSize; + Result* res; +} OutDataRes; + +class ModelProcess { +public: + /** + * @brief Constructor + */ + ModelProcess(); + + /** + * @brief Destructor + */ + virtual ~ModelProcess(); + + /** + * @brief load model + * @param [in] modelPath: model path + * @param [in] inputNum: queue input num + * @param [in] outputNum: queue output num + * @return result + */ + Result LoadModel(const char *modelPath, int32_t inputNum, int32_t outputNum); + + /** + * @brief unload model + */ + void UnloadModel(); + + /** + * @brief create model desc + * @return result + */ + Result CreateModelDesc(); + + /** + * @brief destroy desc + */ + void DestroyModelDesc(); + + /** + * @get input size by index + * @param [in] index: input index + * @param [out] inputSize: input size of index + * @return result + */ + Result GetInputSizeByIndex(const size_t index, size_t &inputSize); + + /** + * @get output size by index + * @param [in] index: output index + * @param [out] outputSize: output size of index + * @return result + */ + Result GetOutputSizeByIndex(const size_t index, size_t &outputSize); + + /** + * @get model output num + * @param [in] num: output num + * @return result + */ + Result GetOutputNum(size_t &num); + + /** + * @brief create input queue + * @param [in] num: input queue num + * @return result + */ + Result CreateQueueInput(int32_t num); + + /** + * @brief destroy input queue + */ + void DestroyQueueInput(); + + /** + * @brief create output queue + * @param [in] num: output queue num + * @return result + */ + Result CreateQueueOutput(int32_t num); + + /** + * @brief destroy output queue + */ + void DestroyQueueOutput(); + + /** + * @brief enqueue data by qid + * @param [in] data: model input data + * @param [in] dataSize: model input data size + * @param [in] index: the index of input queue + * @return result + */ + Result EnqueueData(void *data, size_t dataSize, int32_t index); + + /** + * @brief dequeue data by qid + * @param [out] data: model output data + * @param [in] dataSize: model output data size + * @param [out] retDataSize: the copy size of model output data + * @param [in] index: the index of output queue + * @return result + */ + Result DequeueData(void *data, size_t dataSize, size_t *retDataSize,int32_t index); + + /** + * @brief dump model output result to file + * @param [in] resList: output result list + */ + void DumpModelOutputResult(std::vector &resList); + + /** + * @brief print model output result + * @param [in] resList: output result list + */ + void OutputModelResult(std::vector &resList); + +private: + uint32_t modelId_; + uint32_t *inputQueueList_; // input queue list + uint32_t *outputQueueList_; // output queue list + acltdtQueueAttr *attr_; + int32_t inputNum_; // input queue num + int32_t outputNum_; // output queue num + UserData userData_; + bool loadFlag_; // model load flag + aclmdlDesc *modelDesc_; + +}; + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/sample_process.h b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/sample_process.h new file mode 100644 index 000000000..66ff7c396 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/sample_process.h @@ -0,0 +1,45 @@ +/** +* @file sample_process.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include "utils.h" +#include "acl/acl.h" + +class SampleProcess { +public: + /** + * @brief Constructor + */ + SampleProcess(); + + /** + * @brief Destructor + */ + virtual ~SampleProcess(); + + /** + * @brief init reousce + * @return result + */ + Result InitResource(); + + /** + * @brief sample process + * @return result + */ + Result Process(); + +private: + void DestroyResource(); + + int32_t deviceId_; + aclrtContext context_; + aclrtStream stream_; +}; + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/utils.h b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/utils.h new file mode 100644 index 000000000..261c0f46c --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/inc/utils.h @@ -0,0 +1,52 @@ +/** +* @file utils.h +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#pragma once +#include +#include +#include "acl/acl.h" + +#define INFO_LOG(fmt, ...) fprintf(stdout, "[INFO] " fmt "\n", ##__VA_ARGS__) +#define WARN_LOG(fmt, ...) fprintf(stdout, "[WARN] " fmt "\n", ##__VA_ARGS__) +#define ERROR_LOG(fmt, ...)fprintf(stdout, "[ERROR] " fmt "\n", ##__VA_ARGS__) + +typedef enum Result { + SUCCESS = 0, + FAILED = 1 +} Result; + +class Utils { +public: + /** + * @brief create buffer of file + * @param [in] fileName: file name + * @param [out] inputBuff: input data buffer + * @param [out] fileSize: size of file + * @return result + */ + static Result ReadBinFile(const std::string &fileName, void *&inputBuff, uint32_t &fileSize); + + /** + * @brief create buffer of file + * @param [in] fileName: file name + * @param [out] picDevBuffer: input data device buffer which need to be memcpy + * @param [out] inputBuffSize: size of inputBuff + * @return result + */ + static Result MemcpyFileToDeviceBuffer(const std::string &fileName, void *&picDevBuffer, size_t inputBuffSize); + + /** + * @brief Check whether the path is a file. + * @param [in] fileName: fold to check + * @return result + */ + static Result CheckPathIsFile(const std::string &fileName); +}; + +#pragma once diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/script/transferPic.py b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/script/transferPic.py new file mode 100644 index 000000000..b8cc3cce3 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/script/transferPic.py @@ -0,0 +1,48 @@ +import numpy as np +import os +from PIL import Image + +def process(input_path): + try: + input_image = Image.open(input_path) + input_image = input_image.resize((256, 256)) + # hwc + img = np.array(input_image) + height = img.shape[0] + width = img.shape[1] + h_off = int((height-224)/2) + w_off = int((width-224)/2) + crop_img = img[h_off:height-h_off, w_off:width-w_off, :] + # rgb to bgr + img = crop_img[:, :, ::-1] + shape = img.shape + img = img.astype("float16") + img[:, :, 0] -= 104 + img[:, :, 1] -= 117 + img[:, :, 2] -= 123 + img = img.reshape([1] + list(shape)) + result = img.transpose([0, 3, 1, 2]) + output_name = input_path.split('.')[0] + ".bin" + result.tofile(output_name) + except Exception as except_err: + print(except_err) + return 1 + else: + return 0 +if __name__ == "__main__": + count_ok = 0 + count_ng = 0 + images = os.listdir(r'./') + for image_name in images: + if not image_name.endswith("jpg"): + continue + print("start to process image {}....".format(image_name)) + ret = process(image_name) + if ret == 0: + print("process image {} successfully".format(image_name)) + count_ok = count_ok + 1 + elif ret == 1: + print("failed to process image {}".format(image_name)) + count_ng = count_ng + 1 + print("{} images in total, {} images process successfully, {} images process failed" + .format(count_ok + count_ng, count_ok, count_ng)) diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/host_version.conf b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/host_version.conf new file mode 100644 index 000000000..227f5d6ec --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/host_version.conf @@ -0,0 +1,4 @@ +Atlas300 = c76 +Atlas200dk = c76 +Atlas800 = +Atlas1951 = \ No newline at end of file diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_200dk.sh b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_200dk.sh new file mode 100644 index 000000000..5004ec2f6 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_200dk.sh @@ -0,0 +1,208 @@ +caffe_model="https://obs-model-ascend.obs.cn-east-2.myhuaweicloud.com/resnet50/resnet50.caffemodel" +caffe_prototxt="https://obs-model-ascend.obs.cn-east-2.myhuaweicloud.com/resnet50/resnet50.prototxt" +data_source="https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/" +model_name="resnet50" +project_name="cplusplus_resnet50_async_imagenet_classification" + +version=$1 + +script_path="$( cd "$(dirname $BASH_SOURCE)" ; pwd -P)" +project_path=${script_path}/.. + +declare -i success=0 +declare -i inferenceError=1 +declare -i verifyResError=2 + +function downloadAndGenerateData() { + mkdir -p ${project_path}/data/ + + wget -O ${project_path}/data/"dog1_1024_683.jpg" ${data_source}"dog1_1024_683.jpg" --no-check-certificate + if [ $? -ne 0 ];then + echo "download dog1_1024_683.jpg failed, please check Network." + return 1 + fi + + wget -O ${project_path}/data/"dog2_1024_683.jpg" ${data_source}"dog2_1024_683.jpg" --no-check-certificate + if [ $? -ne 0 ];then + echo "download dog2_1024_683.jpg failed, please check Network." + return 1 + fi + + cd ${project_path}/data/ + python3 ../script/transferPic.py + if [ $? -ne 0 ];then + echo "generate data failed." + return 1 + fi + + return 0 +} + +function setAtcEnv() { + # 设置模型转换时需要的环境变量 + if [[ ${version} = "c73" ]] || [[ ${version} = "C73" ]];then + export install_path=/home/HwHiAiUser/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export PYTHONPATH=${install_path}/atc/python/site-packages/te:${install_path}/atc/python/site-packages/topi:$PYTHONPATH + export ASCEND_OPP_PATH=${install_path}/opp + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + elif [[ ${version} = "c75" ]] || [[ ${version} = "C75" ]];then + export install_path=$HOME/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + export PYTHONPATH=${install_path}/atc/python/site-packages:${install_path}/atc/python/site-packages/auto_tune.egg/auto_tune:${install_path}/atc/python/site-packages/schedule_search.egg:$PYTHONPATH + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + elif [[ ${version} = "c76" ]] || [[ ${version} = "c76" ]];then + export install_path=$HOME/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + export PYTHONPATH=${install_path}/atc/python/site-packages:${install_path}/atc/python/site-packages/auto_tune.egg/auto_tune:${install_path}/atc/python/site-packages/schedule_search.egg:$PYTHONPATH + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + fi + + return 0 +} + +function downloadOriginalModel() { + mkdir -p ${project_path}/caffe_model/ + + wget -O ${project_path}/caffe_model/${caffe_prototxt##*/} ${caffe_prototxt} --no-check-certificate + if [ $? -ne 0 ];then + echo "install caffe_prototxt failed, please check Network." + return 1 + fi + + wget -O ${project_path}/caffe_model/${caffe_model##*/} ${caffe_model} --no-check-certificate + if [ $? -ne 0 ];then + echo "install caffe_model failed, please check Network." + return 1 + fi + + return 0 +} + +function setBuildEnv() { + if [[ ${version} = "c73" ]] || [[ ${version} = "C73" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/arm64-linux_gcc7.3.0 + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + elif [[ ${version} = "c75" ]] || [[ ${version} = "C75" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + elif [[ ${version} = "c76" ]] || [[ ${version} = "c76" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/arm64-linux + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + fi + + return 0 +} + +function main() { + if [[ ${version}"x" = "x" ]];then + echo "ERROR: version is invalid" + return ${inferenceError} + fi + + # 生成模型输入数据集 + downloadAndGenerateData + if [ $? -ne 0 ];then + echo "ERROR: generate data failed" + return ${inferenceError} + fi + + mkdir -p ${HOME}/models/${project_name} + if [ $? -ne 0 ];then + echo "ERROR: mkdir models folder failed. please check your project" + return ${inferenceError} + fi + mkdir -p ${project_path}/model/ + if [ $? -ne 0 ];then + echo "ERROR: mkdir model folder failed. please check your project" + return ${inferenceError} + fi + if [[ $(find ${HOME}/models/${project_name} -name ${model_name}".om")"x" = "x" ]];then + # 下载原始模型文件 + downloadOriginalModel + if [ $? -ne 0 ];then + echo "ERROR: download original model failed" + return ${inferenceError} + fi + + # 设置模型转换的环境变量 + setAtcEnv + if [ $? -ne 0 ];then + echo "ERROR: set atc environment failed" + return ${inferenceError} + fi + + # 转模型 + atc --model=${project_path}/caffe_model/${caffe_prototxt##*/} --weight=${project_path}/caffe_model/${caffe_model##*/} --framework=0 --output=${HOME}/models/${project_name}/${model_name} --soc_version=Ascend310 --input_format=NCHW --input_fp16_nodes=data --output_type=FP32 --out_nodes=prob:0 + if [ $? -ne 0 ];then + echo "ERROR: convert model failed" + return ${inferenceError} + fi + + ln -s ${HOME}/models/${project_name}/${model_name}".om" ${project_path}/model/${model_name}".om" + if [ $? -ne 0 ];then + echo "ERROR: failed to set model soft connection" + return ${inferenceError} + fi + else + ln -s ${HOME}/models/${project_name}/${model_name}".om" ${project_path}/model/${model_name}".om" + if [ $? -ne 0 ];then + echo "ERROR: failed to set model soft connection" + return ${inferenceError} + fi + fi + + # 创建目录用于存放编译文件 + mkdir -p ${project_path}/build/intermediates/minirc + if [ $? -ne 0 ];then + echo "ERROR: mkdir build folder failed. please check your project" + return ${inferenceError} + fi + cd ${project_path}/build/intermediates/minirc + + # 设置代码编译时需要的环境变量 + setBuildEnv + if [ $? -ne 0 ];then + echo "ERROR: set build environment failed" + return ${inferenceError} + fi + + # 产生Makefile + cmake ${project_path}/src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE + if [ $? -ne 0 ];then + echo "ERROR: cmake failed. please check your project" + return ${inferenceError} + fi + + make + if [ $? -ne 0 ];then + echo "ERROR: make failed. please check your project" + return ${inferenceError} + fi + + cd ${project_path}/out + + # 重新配置程序运行所需的环境变量 + export LD_LIBRARY_PATH= + export LD_LIBRARY_PATH=/home/HwHiAiUser/Ascend/acllib/lib64:$LD_LIBRARY_PATH + + # 运行程序 + ./main > result.txt + if [ $? -ne 0 ];then + echo "ERROR: run failed. please check your project" + return ${inferenceError} + fi + + # 验证结果 + results=$(cat result.txt) + if [[ $results =~ "ERROR" || $results =~ "fail" || $results =~ "FAIL" || $results =~ "error" ]];then + echo "run failed" + return ${verifyResError} + else + echo "run success" + return ${success} + fi +} +main diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_300.sh b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_300.sh new file mode 100644 index 000000000..4d423b6f1 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/scripts/testcase_300.sh @@ -0,0 +1,208 @@ +caffe_model="https://obs-model-ascend.obs.cn-east-2.myhuaweicloud.com/resnet50/resnet50.caffemodel" +caffe_prototxt="https://obs-model-ascend.obs.cn-east-2.myhuaweicloud.com/resnet50/resnet50.prototxt" +data_source="https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/aclsample/" +model_name="resnet50" +project_name="cplusplus_resnet50_async_imagenet_classification" + +version=$1 + +script_path="$( cd "$(dirname $BASH_SOURCE)" ; pwd -P)" +project_path=${script_path}/.. + +declare -i success=0 +declare -i inferenceError=1 +declare -i verifyResError=2 + +function downloadAndGenerateData() { + mkdir -p ${project_path}/data/ + + wget -O ${project_path}/data/"dog1_1024_683.jpg" ${data_source}"dog1_1024_683.jpg" --no-check-certificate + if [ $? -ne 0 ];then + echo "download dog1_1024_683.jpg failed, please check Network." + return 1 + fi + + wget -O ${project_path}/data/"dog2_1024_683.jpg" ${data_source}"dog2_1024_683.jpg" --no-check-certificate + if [ $? -ne 0 ];then + echo "download dog2_1024_683.jpg failed, please check Network." + return 1 + fi + + cd ${project_path}/data/ + python3 ../script/transferPic.py + if [ $? -ne 0 ];then + echo "generate data failed." + return 1 + fi + + return 0 +} + +function setAtcEnv() { + # 设置模型转换时需要的环境变量 + if [[ ${version} = "c73" ]] || [[ ${version} = "C73" ]];then + export install_path=/home/HwHiAiUser/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export PYTHONPATH=${install_path}/atc/python/site-packages/te:${install_path}/atc/python/site-packages/topi:$PYTHONPATH + export ASCEND_OPP_PATH=${install_path}/opp + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + elif [[ ${version} = "c75" ]] || [[ ${version} = "C75" ]];then + export install_path=$HOME/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + export PYTHONPATH=${install_path}/atc/python/site-packages:${install_path}/atc/python/site-packages/auto_tune.egg/auto_tune:${install_path}/atc/python/site-packages/schedule_search.egg:$PYTHONPATH + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + elif [[ ${version} = "c76" ]] || [[ ${version} = "c76" ]];then + export install_path=$HOME/Ascend/ascend-toolkit/latest + export PATH=/usr/local/python3.7.5/bin:${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH + export ASCEND_OPP_PATH=${install_path}/opp + export PYTHONPATH=${install_path}/atc/python/site-packages:${install_path}/atc/python/site-packages/auto_tune.egg/auto_tune:${install_path}/atc/python/site-packages/schedule_search.egg:$PYTHONPATH + export LD_LIBRARY_PATH=${install_path}/atc/lib64:${LD_LIBRARY_PATH} + fi + + return 0 +} + +function downloadOriginalModel() { + mkdir -p ${project_path}/caffe_model/ + + wget -O ${project_path}/caffe_model/${caffe_prototxt##*/} ${caffe_prototxt} --no-check-certificate + if [ $? -ne 0 ];then + echo "install caffe_prototxt failed, please check Network." + return 1 + fi + + wget -O ${project_path}/caffe_model/${caffe_model##*/} ${caffe_model} --no-check-certificate + if [ $? -ne 0 ];then + echo "install caffe_model failed, please check Network." + return 1 + fi + + return 0 +} + +function setBuildEnv() { + if [[ ${version} = "c73" ]] || [[ ${version} = "C73" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/x86_64-linux_gcc7.3.0 + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + elif [[ ${version} = "c75" ]] || [[ ${version} = "C75" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/x86_64-linux + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + elif [[ ${version} = "76" ]] || [[ ${version} = "c76" ]];then + export DDK_PATH=/home/HwHiAiUser/Ascend/ascend-toolkit/latest/x86_64-linux + export NPU_HOST_LIB=${DDK_PATH}/acllib/lib64/stub + fi + + return 0 +} + +function main() { + if [[ ${version}"x" = "x" ]];then + echo "ERROR: version is invalid" + return ${inferenceError} + fi + + # 生成模型输入数据集 + downloadAndGenerateData + if [ $? -ne 0 ];then + echo "ERROR: generate data failed" + return ${inferenceError} + fi + + mkdir -p ${HOME}/models/${project_name} + if [ $? -ne 0 ];then + echo "ERROR: mkdir models folder failed. please check your project" + return ${inferenceError} + fi + mkdir -p ${project_path}/model/ + if [ $? -ne 0 ];then + echo "ERROR: mkdir model folder failed. please check your project" + return ${inferenceError} + fi + if [[ $(find ${HOME}/models/${project_name} -name ${model_name}".om")"x" = "x" ]];then + # 下载原始模型文件 + downloadOriginalModel + if [ $? -ne 0 ];then + echo "ERROR: download original model failed" + return ${inferenceError} + fi + + # 设置模型转换的环境变量 + setAtcEnv + if [ $? -ne 0 ];then + echo "ERROR: set atc environment failed" + return ${inferenceError} + fi + + # 转模型 + atc --model=${project_path}/caffe_model/${caffe_prototxt##*/} --weight=${project_path}/caffe_model/${caffe_model##*/} --framework=0 --output=${HOME}/models/${project_name}/${model_name} --soc_version=Ascend310 --input_format=NCHW --input_fp16_nodes=data --output_type=FP32 --out_nodes=prob:0 + if [ $? -ne 0 ];then + echo "ERROR: convert model failed" + return ${inferenceError} + fi + + ln -s ${HOME}/models/${project_name}/${model_name}".om" ${project_path}/model/${model_name}".om" + if [ $? -ne 0 ];then + echo "ERROR: failed to set model soft connection" + return ${inferenceError} + fi + else + ln -s ${HOME}/models/${project_name}/${model_name}".om" ${project_path}/model/${model_name}".om" + if [ $? -ne 0 ];then + echo "ERROR: failed to set model soft connection" + return ${inferenceError} + fi + fi + + # 创建目录用于存放编译文件 + mkdir -p ${project_path}/build/intermediates/host + if [ $? -ne 0 ];then + echo "ERROR: mkdir build folder failed. please check your project" + return ${inferenceError} + fi + cd ${project_path}/build/intermediates/host + + # 设置代码编译时需要的环境变量 + setBuildEnv + if [ $? -ne 0 ];then + echo "ERROR: set build environment failed" + return ${inferenceError} + fi + + # 产生Makefile + cmake ${project_path}/src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE + if [ $? -ne 0 ];then + echo "ERROR: cmake failed. please check your project" + return ${inferenceError} + fi + + make + if [ $? -ne 0 ];then + echo "ERROR: make failed. please check your project" + return ${inferenceError} + fi + + cd ${project_path}/out + + # 重新配置程序运行所需的环境变量 + export LD_LIBRARY_PATH= + export LD_LIBRARY_PATH=/home/HwHiAiUser/Ascend/nnrt/latest/acllib/lib64:/home/HwHiAiUser/Ascend/ascend-toolkit/latest/atc/lib64:/home/HwHiAiUser/ascend_ddk/x86/lib:${LD_LIBRARY_PATH} + + # 运行程序 + ./main > result.txt + if [ $? -ne 0 ];then + echo "ERROR: run failed. please check your project" + return ${inferenceError} + fi + + # 验证结果 + results=$(cat result.txt) + if [[ $results =~ "ERROR" || $results =~ "fail" || $results =~ "FAIL" || $results =~ "error" ]];then + echo "run failed" + return ${verifyResError} + else + echo "run success" + return ${success} + fi +} +main diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeLists.txt b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeLists.txt new file mode 100644 index 000000000..a3016f7ec --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeLists.txt @@ -0,0 +1,82 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. + +# CMake lowest version requirement +cmake_minimum_required(VERSION 3.5.1) + +# project information +project(ACL_RESNET50) + +# Compile options +add_compile_options(-std=c++11) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../../out") +set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall") +set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -Wall") + +set(INC_PATH $ENV{DDK_PATH}) +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_WIN32_THREADS_INIT 0) +set(CMAKE_USE_PTHREADS_INIT 1) +set(THREADS_PREFER_PTHREAD_FLAG ON) + +if (NOT DEFINED ENV{DDK_PATH}) + if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows") + set(INC_PATH "C:/Program Files/HuaWei/Ascend") + else () + set(INC_PATH "/usr/local/Ascend") + endif () + message(STATUS "set default INC_PATH: ${INC_PATH}") +else () + message(STATUS "env INC_PATH: ${INC_PATH}") +endif () + +set(LIB_PATH $ENV{NPU_HOST_LIB}) + +# Dynamic libraries in the stub directory can only be used for compilation +if (NOT DEFINED ENV{NPU_HOST_LIB}) + if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows") + set(LIB_PATH "C:/Program Files/HuaWei/Ascend/Acllib/lib64") + else () + set(LIB_PATH "/usr/local/Ascend/acllib/lib64/stub/") + endif () + message(STATUS "set default LIB_PATH: ${LIB_PATH}") +else () + message(STATUS "env LIB_PATH: ${LIB_PATH}") +endif () + +# Header path +include_directories( + ${INC_PATH}/include/ + ../inc/ +) + +if(target STREQUAL "Simulator_Function") + add_compile_options(-DFUNC_SIM) +endif() + +# add host lib path +link_directories( + ${LIB_PATH} +) + +add_executable(main + utils.cpp + model_process.cpp + sample_process.cpp + main.cpp) + +if (target STREQUAL "Simulator_Function") + target_link_libraries(main funcsim) +else () + if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(main + libascendcl) + else () + target_link_libraries(main + ascendcl stdc++ libacl_tdt_queue.so) + endif () +endif () + +install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/Makefile b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/Makefile new file mode 100644 index 000000000..e0a099908 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/Makefile @@ -0,0 +1,318 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.16 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/ye/aclCode/samples/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/ye/aclCode/samples/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/ye/aclCode/samples/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeFiles /home/ye/aclCode/samples/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeFiles/progress.marks + $(MAKE) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/ye/aclCode/samples/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named main + +# Build rule for target. +main: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 main +.PHONY : main + +# fast build rule for target. +main/fast: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build +.PHONY : main/fast + +main.o: main.cpp.o + +.PHONY : main.o + +# target to build an object file +main.cpp.o: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i + +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s + +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.cpp.s +.PHONY : main.cpp.s + +model_process.o: model_process.cpp.o + +.PHONY : model_process.o + +# target to build an object file +model_process.cpp.o: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/model_process.cpp.o +.PHONY : model_process.cpp.o + +model_process.i: model_process.cpp.i + +.PHONY : model_process.i + +# target to preprocess a source file +model_process.cpp.i: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/model_process.cpp.i +.PHONY : model_process.cpp.i + +model_process.s: model_process.cpp.s + +.PHONY : model_process.s + +# target to generate assembly for a file +model_process.cpp.s: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/model_process.cpp.s +.PHONY : model_process.cpp.s + +sample_process.o: sample_process.cpp.o + +.PHONY : sample_process.o + +# target to build an object file +sample_process.cpp.o: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/sample_process.cpp.o +.PHONY : sample_process.cpp.o + +sample_process.i: sample_process.cpp.i + +.PHONY : sample_process.i + +# target to preprocess a source file +sample_process.cpp.i: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/sample_process.cpp.i +.PHONY : sample_process.cpp.i + +sample_process.s: sample_process.cpp.s + +.PHONY : sample_process.s + +# target to generate assembly for a file +sample_process.cpp.s: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/sample_process.cpp.s +.PHONY : sample_process.cpp.s + +utils.o: utils.cpp.o + +.PHONY : utils.o + +# target to build an object file +utils.cpp.o: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/utils.cpp.o +.PHONY : utils.cpp.o + +utils.i: utils.cpp.i + +.PHONY : utils.i + +# target to preprocess a source file +utils.cpp.i: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/utils.cpp.i +.PHONY : utils.cpp.i + +utils.s: utils.cpp.s + +.PHONY : utils.s + +# target to generate assembly for a file +utils.cpp.s: + $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/utils.cpp.s +.PHONY : utils.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... install/strip" + @echo "... install/local" + @echo "... install" + @echo "... list_install_components" + @echo "... rebuild_cache" + @echo "... edit_cache" + @echo "... main" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" + @echo "... model_process.o" + @echo "... model_process.i" + @echo "... model_process.s" + @echo "... sample_process.o" + @echo "... sample_process.i" + @echo "... sample_process.s" + @echo "... utils.o" + @echo "... utils.i" + @echo "... utils.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/acl.json b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/acl.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/acl.json @@ -0,0 +1 @@ +{} diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/main.cpp b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/main.cpp new file mode 100644 index 000000000..7cb5ad520 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/main.cpp @@ -0,0 +1,33 @@ +/** +* @file main.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include +#include "sample_process.h" +#include "utils.h" +using namespace std; +bool g_isDevice = false; + +int main() +{ + SampleProcess sampleProcess; + Result ret = sampleProcess.InitResource(); + if (ret != SUCCESS) { + ERROR_LOG("sample init resource failed"); + return FAILED; + } + + ret = sampleProcess.Process(); + if (ret != SUCCESS) { + ERROR_LOG("sample process failed"); + return FAILED; + } + + INFO_LOG("execute sample success"); + return SUCCESS; +} \ No newline at end of file diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/model_process.cpp b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/model_process.cpp new file mode 100644 index 000000000..b177abae2 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/model_process.cpp @@ -0,0 +1,400 @@ +/** +* @file model_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "model_process.h" +#include +#include +#include +#include +#include +#include "utils.h" + +using namespace std; +extern bool g_isDevice; + +ModelProcess::ModelProcess() :modelId_(0), inputQueueList_(nullptr), outputQueueList_(nullptr), attr_(nullptr), + inputNum_(0), outputNum_(0), userData_({}), loadFlag_(false), modelDesc_(nullptr) +{ +} + +ModelProcess::~ModelProcess() +{ + +} + +Result ModelProcess::LoadModel(const char *modelPath, int32_t inputNum, int32_t outputNum) +{ + if (loadFlag_) { + ERROR_LOG("model has already been loaded"); + return FAILED; + } + + if (attr_ == nullptr) { + attr_ = acltdtCreateQueueAttr(); + } + + if (attr_ == nullptr) { + ERROR_LOG("create queue attr failed"); + return FAILED; + } + + Result ret = CreateQueueInput(inputNum); + if (ret != SUCCESS) { + return FAILED; + } + + ret = CreateQueueOutput(outputNum); + if (ret != SUCCESS) { + return FAILED; + } + + aclError re = aclmdlLoadFromFileWithQ(modelPath, &modelId_, inputQueueList_, inputNum_, + outputQueueList_, outputNum_); + if (re != ACL_SUCCESS) { + ERROR_LOG("load model from file failed, model file is %s, errorCode is %d", + modelPath, static_cast(re)); + return FAILED; + } + + loadFlag_ = true; + INFO_LOG("load model %s success", modelPath); + return SUCCESS; +} + +Result ModelProcess::CreateModelDesc() +{ + modelDesc_ = aclmdlCreateDesc(); + if (modelDesc_ == nullptr) { + ERROR_LOG("create model description failed"); + return FAILED; + } + + aclError ret = aclmdlGetDesc(modelDesc_, modelId_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("get model description failed, modelId is %u, errorCode is %d", + modelId_, static_cast(ret)); + return FAILED; + } + + INFO_LOG("create model description success"); + + return SUCCESS; +} + +void ModelProcess::DestroyModelDesc() +{ + if (modelDesc_ != nullptr) { + (void)aclmdlDestroyDesc(modelDesc_); + modelDesc_ = nullptr; + } + INFO_LOG("destroy model description success"); +} + +Result ModelProcess::GetInputSizeByIndex(const size_t index, size_t &inputSize) +{ + if (modelDesc_ == nullptr) { + ERROR_LOG("no model description, create input failed"); + return FAILED; + } + inputSize = aclmdlGetInputSizeByIndex(modelDesc_, index); + return SUCCESS; +} + +Result ModelProcess::GetOutputSizeByIndex(const size_t index, size_t &outputSize) +{ + if (modelDesc_ == nullptr) { + ERROR_LOG("no model description, create input failed"); + return FAILED; + } + outputSize = aclmdlGetOutputSizeByIndex(modelDesc_, index); + return SUCCESS; +} + +Result ModelProcess::GetOutputNum(size_t &num) +{ + if (modelDesc_ == nullptr) { + ERROR_LOG("no model description, create input failed"); + return FAILED; + } + num = aclmdlGetNumOutputs(modelDesc_); + return SUCCESS; +} + +Result ModelProcess::CreateQueueInput(int32_t num) +{ + if (attr_ == nullptr) { + ERROR_LOG("queue attr needs to be created"); + return FAILED; + } + + if (inputQueueList_ != nullptr) { + ERROR_LOG("input queue has already been created"); + return FAILED; + } + + inputQueueList_ = new (nothrow) uint32_t[num]; + if (inputQueueList_ == nullptr) { + ERROR_LOG("create input queue list failed"); + return FAILED; + } + + inputNum_ = 0; + + for (int n = 0; n < num; n++) { + uint32_t qid; + aclError ret = acltdtCreateQueue(attr_, &qid); + if (ret != ACL_SUCCESS) { + ERROR_LOG("create input queue failed, errorCode is %d", static_cast(ret)); + return FAILED; + } + + inputQueueList_[n] = qid; + } + + inputNum_ = num; + INFO_LOG("create input queue success"); + + return SUCCESS; +} + +void ModelProcess::DestroyQueueInput() +{ + if (attr_ == nullptr || inputNum_ < 1 || inputQueueList_ == nullptr) { + ERROR_LOG("no queue needs to be destroyed"); + return; + } + + for (int n = 0; n < inputNum_; n++) { + uint32_t qid = inputQueueList_[n]; + aclError ret = acltdtDestroyQueue(qid); + if (ret != ACL_SUCCESS) { + ERROR_LOG("destroy input queue failed, errorCode is %d", static_cast(ret)); + return; + } + } + + delete [] inputQueueList_; + inputQueueList_ = nullptr; + inputNum_ = 0; + INFO_LOG("destroy input queue success"); +} + +Result ModelProcess::CreateQueueOutput(int32_t num) +{ + if (attr_ == nullptr) { + ERROR_LOG("queue attr needs to be created"); + return FAILED; + } + + if (outputQueueList_ != nullptr) { + ERROR_LOG("output queue has already been created"); + return FAILED; + } + + outputQueueList_ = new (nothrow) uint32_t[num]; + if (outputQueueList_ == nullptr) { + ERROR_LOG("create output queue list failed"); + return FAILED; + } + + outputNum_ = 0; + + for (int n = 0; n < num; n++) { + uint32_t qid; + aclError ret = acltdtCreateQueue(attr_, &qid); + if (ret != ACL_SUCCESS) { + ERROR_LOG("create output queue failed, errorCode is %d", static_cast(ret)); + return FAILED; + } + + outputQueueList_[n] = qid; + } + + outputNum_ = num; + INFO_LOG("create output queue success"); + + return SUCCESS; +} + +void ModelProcess::DestroyQueueOutput() +{ + if (attr_ == nullptr || outputNum_ < 1 || outputQueueList_ == nullptr) { + ERROR_LOG("no queue needs to be destroyed"); + return; + } + + for (int n = 0; n < outputNum_; n++) { + uint32_t qid = outputQueueList_[n]; + aclError ret = acltdtDestroyQueue(qid); + if (ret != ACL_SUCCESS) { + ERROR_LOG("destroy output queue failed, errorCode is %d", static_cast(ret)); + return; + } + } + + delete [] outputQueueList_; + outputQueueList_ = nullptr; + outputNum_ = 0; + INFO_LOG("destroy output queue success"); +} + +Result ModelProcess::EnqueueData(void *data, size_t dataSize, int32_t index) +{ + if (attr_ == nullptr || inputNum_ < 1 || inputQueueList_ == nullptr) { + ERROR_LOG("no queue needs to enqueue"); + return FAILED; + } + + if (index >= inputNum_) { + ERROR_LOG("the index is out of the input queue num"); + return FAILED; + } + + int32_t timeout = -1; + uint32_t qid = inputQueueList_[index]; + aclError ret = acltdtEnqueueData(qid, data, dataSize, &userData_, sizeof(userData_), timeout, 0); + if (ret != ACL_SUCCESS) { + ERROR_LOG("enqueue failed, errorCode is %d", static_cast(ret)); + return FAILED; + } + + INFO_LOG("enqueue success"); + + return SUCCESS; +} + +Result ModelProcess::DequeueData(void *data, size_t dataSize, size_t *retDataSize,int32_t index) +{ + if (attr_ == nullptr || outputNum_ < 1 || outputQueueList_ == nullptr) { + ERROR_LOG("no queue needs to dequeue"); + return FAILED; + } + + if (index >= outputNum_) { + ERROR_LOG("the index is out of the output queue num"); + return FAILED; + } + + int32_t timeout = -1; + uint32_t qid = outputQueueList_[index]; + aclError ret = acltdtDequeueData(qid, data, dataSize, retDataSize, &userData_, sizeof(userData_), timeout); + if (ret != ACL_SUCCESS) { + ERROR_LOG("dequeue failed, errorCode is %d", static_cast(ret)); + return FAILED; + } + + INFO_LOG("dequeue success"); + + return SUCCESS; +} + +void ModelProcess::DumpModelOutputResult(std::vector &resList) +{ + size_t outputNum; + Result ret = GetOutputNum(outputNum); + if (ret != SUCCESS) { + ERROR_LOG("get output num failed"); + return; + } + + stringstream ss; + static int executeNum = 0; + for (size_t i = 0; i < outputNum; ++i) { + OutDataRes &outDataRes = resList[i]; + if (*outDataRes.res != SUCCESS) { + continue; + } + + ss << "output" << ++executeNum << "_" << i << ".bin"; + string outputFileName = ss.str(); + FILE *outputFile = fopen(outputFileName.c_str(), "wb"); + if (outputFile != nullptr) { + // get model output data + void* data = outDataRes.data; + uint32_t len = *outDataRes.retDataSize; + + // if app is running in host, write model output data into result file + fwrite(data, len, sizeof(char), outputFile); + + fclose(outputFile); + } else { + ERROR_LOG("create output file [%s] failed", outputFileName.c_str()); + return; + } + } + + INFO_LOG("dump data success"); +} + +void ModelProcess::OutputModelResult(std::vector &resList) +{ + size_t outputNum; + Result ret = GetOutputNum(outputNum); + if (ret != SUCCESS) { + ERROR_LOG("get output num failed"); + return; + } + + for (size_t i = 0; i < outputNum; ++i) { + // get model output data + OutDataRes &outDataRes = resList[i]; + if (*outDataRes.res != SUCCESS) { + continue; + } + + void* data = outDataRes.data; + uint32_t len = *outDataRes.retDataSize; + INFO_LOG("retDataSize is %zu", *outDataRes.retDataSize); + + float *outData = reinterpret_cast(data); + + map > resultMap; + for (unsigned int j = 0; j < len / sizeof(float); ++j) { + resultMap[*outData] = j; + outData++; + } + + int cnt = 0; + for (auto it = resultMap.begin(); it != resultMap.end(); ++it) { + // print top 5 + if (++cnt > 5) { + break; + } + INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first); + } + } + + INFO_LOG("output data success"); +} + +void ModelProcess::UnloadModel() +{ + if (!loadFlag_) { + WARN_LOG("no model had been loaded, unload failed"); + return; + } + + aclError ret = aclmdlUnload(modelId_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("unload model failed, modelId is %u, errorCode is %d", modelId_, static_cast(ret)); + } + + DestroyQueueInput(); + DestroyQueueOutput(); + DestroyModelDesc(); + + if (attr_ != nullptr) { + acltdtDestroyQueueAttr(attr_); + attr_ = nullptr; + } + + loadFlag_ = false; + INFO_LOG("unload model success, modelId is %u", modelId_); + modelId_ = 0; +} diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/sample_process.cpp b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/sample_process.cpp new file mode 100644 index 000000000..8958e225a --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/sample_process.cpp @@ -0,0 +1,288 @@ +/** +* @file sample_process.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "sample_process.h" +#include "model_process.h" +#include "acl/acl.h" +#include "utils.h" +#include +#include +#include + +using namespace std; +extern bool g_isDevice; + +SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) +{ +} + +SampleProcess::~SampleProcess() +{ + DestroyResource(); +} + +Result SampleProcess::InitResource() +{ + // ACL init + const char *aclConfigPath = "../src/acl.json"; + aclError ret = aclInit(aclConfigPath); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl init failed, errorCode = %d", static_cast(ret)); + return FAILED; + } + INFO_LOG("acl init success"); + + // set device + ret = aclrtSetDevice(deviceId_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl set device %d failed, errorCode = %d", deviceId_, static_cast(ret)); + return FAILED; + } + INFO_LOG("set device %d success", deviceId_); + + // create context (set current) + ret = aclrtCreateContext(&context_, deviceId_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl create context failed, deviceId = %d, errorCode = %d", + deviceId_, static_cast(ret)); + return FAILED; + } + INFO_LOG("create context success"); + + // create stream + ret = aclrtCreateStream(&stream_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl create stream failed, deviceId = %d, errorCode = %d", + deviceId_, static_cast(ret)); + return FAILED; + } + INFO_LOG("create stream success"); + + // get run mode + // runMode is ACL_HOST which represents app is running in host + // runMode is ACL_DEVICE which represents app is running in device + aclrtRunMode runMode; + ret = aclrtGetRunMode(&runMode); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl get run mode failed, errorCode = %d", static_cast(ret)); + return FAILED; + } + g_isDevice = (runMode == ACL_DEVICE); + + return SUCCESS; +} + +void EnqueueDataFunc(ModelProcess *modelProcess, int32_t deviceId, void *inBuffer, size_t bufferSize, int32_t index) +{ + if (modelProcess == nullptr) { + return; + } + aclrtContext context; + aclError ret = aclrtCreateContext(&context, deviceId); + if (ret != ACL_SUCCESS) { + ERROR_LOG("acl create context failed, deviceId = %d, errorCode = %d", + deviceId, static_cast(ret)); + return; + } + Result res = modelProcess->EnqueueData(inBuffer, bufferSize, index); + if (context != nullptr) { + ret = aclrtDestroyContext(context); + if (ret != ACL_SUCCESS) { + ERROR_LOG("destroy context failed, errorCode = %d", static_cast(ret)); + } + } +} + +void DequeueDataFunc(ModelProcess *modelProcess, int32_t deviceId, size_t outputNum, vector& resList) +{ + if (modelProcess == nullptr) { + return; + } + aclrtContext context; + aclError re = aclrtCreateContext(&context, deviceId); + if (re != ACL_SUCCESS) { + ERROR_LOG("acl create context failed, deviceId = %d, errorCode = %d", + deviceId, static_cast(re)); + return; + } + + for (int32_t i = 0; i < outputNum; i++) { + size_t dataSize; + Result ret = modelProcess->GetOutputSizeByIndex(i, dataSize); + if (ret != SUCCESS) { + return; + } + + INFO_LOG("model outputSize is %zu", dataSize); + void *data = nullptr; + if (!g_isDevice) { + data = malloc(dataSize); + if (data == NULL) { + ERROR_LOG("malloc host buffer failed, size is %zu", dataSize); + return; + } + } else { + re = aclrtMalloc(&data, dataSize, ACL_MEM_MALLOC_NORMAL_ONLY); + if (re != ACL_SUCCESS) { + ERROR_LOG("malloc device buffer failed. size is %zu, errorCode is %d", + dataSize, static_cast(re)); + return; + } + } + + OutDataRes outDataRes; + outDataRes.index = i; + outDataRes.data = data; + outDataRes.len = dataSize; + outDataRes.retDataSize = new size_t; + outDataRes.res = new Result; + resList.push_back(outDataRes); + *outDataRes.res = modelProcess->DequeueData(data, dataSize, outDataRes.retDataSize, i); + } + + if (context != nullptr) { + re = aclrtDestroyContext(context); + if (re != ACL_SUCCESS) { + ERROR_LOG("destroy context failed, errorCode = %d", static_cast(re)); + } + } +} + +Result SampleProcess::Process() +{ + string testFile[] = { + "../data/dog1_1024_683.bin", + "../data/dog2_1024_683.bin" + }; + + const char* omModelPath = "../model/resnet50.om"; + ModelProcess modelProcess; + + Result ret = modelProcess.LoadModel(omModelPath, 1, 1); + if (ret != SUCCESS) { + ERROR_LOG("execute LoadModel failed"); + return FAILED; + } + + ret = modelProcess.CreateModelDesc(); + if (ret != SUCCESS) { + ERROR_LOG("execute CreateModelDesc failed"); + return FAILED; + } + + size_t inputSize; + ret = modelProcess.GetInputSizeByIndex(0, inputSize); + if (ret != SUCCESS) { + ERROR_LOG("execute GetInputSizeByIndex failed"); + return FAILED; + } + + size_t outputNum; + ret = modelProcess.GetOutputNum(outputNum); + if (ret != SUCCESS) { + ERROR_LOG("execute GetOutputNum failed"); + return FAILED; + } + + for (size_t index = 0; index < sizeof(testFile) / sizeof(testFile[0]); ++index) { + INFO_LOG("start to process file:%s", testFile[index].c_str()); + + // copy image data to device buffer + uint32_t devBufferSize; + void *picDevBuffer = nullptr; + ret = Utils::ReadBinFile(testFile[index], picDevBuffer, devBufferSize); + if (ret != SUCCESS) { + ERROR_LOG("read bin file failed, file name is %s", testFile[index].c_str()); + return FAILED; + } + + if (inputSize != static_cast(devBufferSize)) { + ERROR_LOG("input image size[%u] is not equal to model input size[%zu]", devBufferSize, inputSize); + if (!g_isDevice) { + free(picDevBuffer); + } else { + aclrtFree(picDevBuffer); + } + return FAILED; + } + + vector threadList; + + threadList.push_back(thread(EnqueueDataFunc, &modelProcess, deviceId_, picDevBuffer, devBufferSize, 0)); + + vector resList; + + threadList.push_back(thread(DequeueDataFunc, &modelProcess, deviceId_, outputNum, std::ref(resList))); + + for (auto &x : threadList) { + x.join(); + } + + // Print the top 5 confidence values with indexes. + // Use function [DumpModelOutputResult] if you want to dump results to file in the current directory. + modelProcess.OutputModelResult(resList); + //modelProcess.DumpModelOutputResult(resList); + + for (int32_t i = 0; i < outputNum; i++) { + OutDataRes& outDataRes = resList[i]; + if (!g_isDevice) { + free(outDataRes.data); + } else { + aclrtFree(outDataRes.data); + } + + delete outDataRes.retDataSize; + delete outDataRes.res; + } + + if (!g_isDevice) { + free(picDevBuffer); + } else { + aclrtFree(picDevBuffer); + } + } + + modelProcess.UnloadModel(); + + return SUCCESS; +} + +void SampleProcess::DestroyResource() +{ + aclError ret; + if (stream_ != nullptr) { + ret = aclrtDestroyStream(stream_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("destroy stream failed, errorCode = %d", static_cast(ret)); + } + stream_ = nullptr; + } + INFO_LOG("end to destroy stream"); + + if (context_ != nullptr) { + ret = aclrtDestroyContext(context_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("destroy context failed, errorCode = %d", static_cast(ret)); + } + context_ = nullptr; + } + INFO_LOG("end to destroy context"); + + ret = aclrtResetDevice(deviceId_); + if (ret != ACL_SUCCESS) { + ERROR_LOG("reset device %d failed, errorCode = %d", deviceId_, static_cast(ret)); + } + INFO_LOG("end to reset device %d", deviceId_); + + ret = aclFinalize(); + if (ret != ACL_SUCCESS) { + ERROR_LOG("finalize acl failed, errorCode = %d", static_cast(ret)); + } + INFO_LOG("end to finalize acl"); +} diff --git a/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/utils.cpp b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/utils.cpp new file mode 100644 index 000000000..46b3c1d94 --- /dev/null +++ b/cplusplus/level2_simple_inference/1_classification/resnet50_imagenet_classificationWithQ/src/utils.cpp @@ -0,0 +1,128 @@ +/** +* @file utils.cpp +* +* Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include "utils.h" +#include +#include +#include +#if defined(_MSC_VER) +#include +#else +#include +#endif +#include "acl/acl.h" + +extern bool g_isDevice; + +Result Utils::ReadBinFile(const std::string &fileName, void *&inputBuff, uint32_t &fileSize) +{ + if (CheckPathIsFile(fileName) == FAILED) { + ERROR_LOG("%s is not a file", fileName.c_str()); + return FAILED; + } + + std::ifstream binFile(fileName, std::ifstream::binary); + if (binFile.is_open() == false) { + ERROR_LOG("open file %s failed", fileName.c_str()); + return FAILED; + } + + 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 FAILED; + } + binFile.seekg(0, binFile.beg); + + aclError ret = ACL_SUCCESS; + if (!g_isDevice) { // app is running in host + inputBuff = malloc(static_cast(binFileBufferLen)); + if (inputBuff == NULL) { + ERROR_LOG("malloc binFileBufferData failed, binFileBufferLen is %u", binFileBufferLen); + binFile.close(); + return FAILED; + } + } else { // app is running in device + ret = aclrtMalloc(&inputBuff, binFileBufferLen, ACL_MEM_MALLOC_NORMAL_ONLY); + if (ret != ACL_SUCCESS) { + ERROR_LOG("malloc device buffer failed. size is %u, errorCode is %d", + binFileBufferLen, static_cast(ret)); + binFile.close(); + return FAILED; + } + } + binFile.read(static_cast(inputBuff), binFileBufferLen); + binFile.close(); + fileSize = binFileBufferLen; + return SUCCESS; +} + +Result Utils::MemcpyFileToDeviceBuffer(const std::string &fileName, void *&picDevBuffer, size_t inputBuffSize) +{ + void *inputBuff = nullptr; + uint32_t fileSize = 0; + auto ret = Utils::ReadBinFile(fileName, inputBuff, fileSize); + if (ret != SUCCESS) { + ERROR_LOG("read bin file failed, file name is %s", fileName.c_str()); + return FAILED; + } + if (inputBuffSize != static_cast(fileSize)) { + ERROR_LOG("input image size[%u] is not equal to model input size[%zu]", fileSize, inputBuffSize); + if (!g_isDevice) { + (void)aclrtFreeHost(inputBuff); + } else { + (void)aclrtFree(inputBuff); + } + return FAILED; + } + if (!g_isDevice) { + // if app is running in host, need copy data from host to device + aclError aclRet = aclrtMemcpy(picDevBuffer, inputBuffSize, inputBuff, inputBuffSize, ACL_MEMCPY_HOST_TO_DEVICE); + if (aclRet != ACL_SUCCESS) { + ERROR_LOG("memcpy failed. buffer size is %zu, errorCode is %d", inputBuffSize, static_cast(aclRet)); + (void)aclrtFreeHost(inputBuff); + return FAILED; + } + (void)aclrtFreeHost(inputBuff); + } else { // app is running in device + aclError aclRet = aclrtMemcpy(picDevBuffer, inputBuffSize, inputBuff, inputBuffSize, ACL_MEMCPY_DEVICE_TO_DEVICE); + if (aclRet != ACL_SUCCESS) { + ERROR_LOG("memcpy d2d failed. buffer size is %zu, errorCode is %d", inputBuffSize, static_cast(aclRet)); + (void)aclrtFree(inputBuff); + return FAILED; + } + (void)aclrtFree(inputBuff); + } + return SUCCESS; +} + +Result Utils::CheckPathIsFile(const std::string &fileName) +{ +#if defined(_MSC_VER) + DWORD bRet = GetFileAttributes((LPCSTR)fileName.c_str()); + if (bRet == FILE_ATTRIBUTE_DIRECTORY) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return FAILED; + } +#else + struct stat sBuf; + int fileStatus = stat(fileName.data(), &sBuf); + if (fileStatus == -1) { + ERROR_LOG("failed to get file"); + return FAILED; + } + if (S_ISREG(sBuf.st_mode) == 0) { + ERROR_LOG("%s is not a file, please enter a file", fileName.c_str()); + return FAILED; + } +#endif + return SUCCESS; +} \ No newline at end of file -- Gitee