一、簡介
1.華為昇騰AI全棧簡介
- Atlas系列產品:提供AI訓練、推理卡及訓練服務器.
- CANN(異構計算架構):芯片算子庫和自動化算法開發工具。
- ModelBox:適用于端邊云場景的AI推理應用開發框架,提供標準SDK API接口。
- MindSpore(AI框架):支持“端-邊-云”獨立和協同的統一訓練和推理框架。
-
MindX SDK(昇騰SDK):行業SDK和應用解決方案。
- mxIndex:對于大規模特征檢索/聚類的應用場景需求,基于開源Faiss框架,提供極簡易用、高性能API。
- mxManufacture:提供制造業視覺質檢相關API。
- mxVision:提供智能視頻分析相關API。
- ModelArts(AI開發平臺):華為云AI開發平臺。
- MindStudio(全流程開發工具鏈):AI全流程開發IDE。
2.CANN簡介
CANN(Compute Architecture for Neural Networks)是華為公司針對AI場景推出的異構計算架構,通過提供多層次的編程接口,支持用戶快速構建基于昇騰平臺的AI應用和業務。
- 統一編程接口AscendCL適配全系列硬件。
- 通過自動流水、算子深度融合、智能計算調優、自適應梯度切分等核心技術,軟硬件協同優化,釋放硬件算力。
1)CANN開發及運行環境
-
開發環境:主要用于代碼開發、編譯、調測等開發活動。
- (場景一)在非昇騰AI設備上安裝開發環境,僅能用于代碼開發、編譯等不依賴于昇騰設備的開發活動(例如ATC模型轉換、算子和推理應用程序的純代碼開發)。
- (場景二)在昇騰AI設備上安裝開發環境,支持代碼開發和編譯,同時可以運行應用程序或進行訓練腳本的遷移、開發&調試。
運行環境:在昇騰AI設備上運行用戶開發的應用程序或進行訓練腳本的遷移、開發&調試。
推理方式
- 離線推理:是基于原有AI框架模型轉換OM模型,不依賴于AI框架執行推理的場景。
- 在線推理:是將原有AI框架做推理的應用快速遷移至昇騰AI處理器上,依賴于AI框架執行推理的場景。
2)CANN 開發輔助工具
-
精度對比工具
- 推理場景中,ATC在模型轉換過程中對模型進行了優化,包括算子消除、算子融合、算子拆分,可能會造成算子精度問題。
- 訓練場景中,華為支持遷移用戶原始網絡,在昇騰910 AI處理器上訓練,網絡遷移可能會造成算子精度問題。
Auto Tune調優工具
可以自動對算子進行性能優化,提升算子的運行效率。
-
Profiling工具
- 用于分析在訓練階段或運行在昇騰AI處理器上的APP工程各個運行階段的關鍵性能瓶頸。
AI Core Error Analyzer工具
可以自動快速準確地收集定位AI Core Error問題所需的關鍵信息。
-
腳本轉換工具
- 可以將腳本轉換為支持在NPU上運行的腳本,解決基于GPU的訓練和在線推理腳本不能直接在NPU上運行的問題。
-
算子及模型速查工具
- 查詢當前版本CANN支持的模型和算子功能
-
推理Benchmark工具
- 針對指定的推理模型運行推理程序,并能夠測試推理模型的性能(包括吞吐率、時延)和精度指標。
-
專家系統(MindStudio Advisor)
- 用于聚焦模型和算子的性能調優TOP問題,識別性能瓶頸Pattern,重點構建瓶頸分析、優化推薦模型,支撐開發效率提升的工具。
-
昇騰模型壓縮工具
- 對原始網絡模型進行量化(對模型的權重(weight)和數據(activation)進行低比特處理),節省網絡模型存儲空間、降低傳輸時延、提高計算效率。
- 無需在安裝昇騰AI處理器的服務器上運行
- Caffe昇騰模型壓縮工具
- TensorFlow昇騰模型壓縮工具
- PyTorch昇騰模型壓縮工具
- ONNX昇騰模型壓縮工具:源模型轉量化模型
- 須在安裝昇騰AI處理器的服務器上運行
- MindSpore昇騰模型壓縮工具
- ACL昇騰模型壓縮工具:將量化模型轉換成昇騰AI處理器的離線模型。
- TensorFlow,Ascend昇騰模型壓縮工具
昇騰模型壓縮工具目前支持在Ubuntu 18.04.5和麒麟 V10操作系統安裝。
3.MindSpore
MindSpore具有編程簡單、端云協同、調試輕松、性能卓越、開源開放等特點,降低了AI開發門檻。
MindSpore Extend(擴展層):MindSpore的擴展包,社區開發者可參與開發。
MindExpression(表達層):基于Python的前端表達;向用戶提供了3個不同層次的API,支撐用戶進行網絡構建、整圖執行、子圖執行以及單算子執行。
High-Level Python API:提供了訓練推理的管理、混合精度訓練、調試調優等高級接口。
Medium-Level Python API:提供網絡層、優化器、損失函數等模塊,可靈活構建神經網絡和控制執行流程,實現模型算法邏輯。
Low-Level Python API:提供張量定義、基礎算子、自動微分等模塊,可實現張量定義和求導計算。
-
MindCompiler(編譯優化層):圖層的核心編譯器,主要基于端云統一的MindIR實現三大功能:
- 包括硬件無關的優化(類型推導、自動微分、表達式化簡等)
- 硬件相關優化(自動并行、內存優化、圖算融合、流水線執行等)
- 部署推理相關的優化(量化、剪枝等)
MindRT(全場景運行時):含云側、端側以及更小的IoT。
二、快速部署
快速部署(22.0.RC2版本-對應CANN 5.1.RC2 )
- 根據官方提供容器鏡像的最高版本來選擇。
基于Atlas 500 Pro 智能邊緣服務器(3000)的KylinV10SP1或 OpenEuler 20.03進行部署。
1.不同產品形態的部署架構
昇騰AI設備可分為EP和RC兩種模式。
1)Ascend EP模式
昇騰 AI 處理器的PCIe工作在從模式,則稱為EP模式。
支持EP模式的產品:
昇騰310 AI處理器:Atlas 200 AI加速模塊、Atlas 300I 推理卡、Atlas 500 智能小站、Atlas 500 Pro 智能邊緣服務器、Atlas 800 推理服務器。
昇騰710 AI處理器:Atlas 300I Pro 推理卡。
昇騰910 AI處理器:Atlas 800 訓練服務器、Atlas 300T 訓練卡。
2)Ascend RC模式
昇騰 AI 處理器的PCIe工作在主模式,可以擴展外設,則稱為RC模式。
支持RC模式的產品有:Atlas 200 AI加速模塊、Atlas 200 DK 開發者套件。
2.安裝前準備
1)CANN社區版支持的OS清單
產品型號 | 支持的操作系統 |
---|---|
A500 Pro-3000+A300I-3000 | Ubuntu 18.04.1、Ubuntu 16.04.5、EulerOS 2.8、EulerOS2.9、OpenEuler 20.03、CentOS 7.6、CentOS 8.2、Linx 6.0、KylinV10SP1、UOS20 SP1 |
- KylinV10SP1就是Kylin V10Tercel
2)需要準備的軟件包
軟件類型 | 軟件介紹 |
---|---|
npu-firmware | 固件包含昇騰AI處理器自帶的OS 、電源器件和功耗管理器件控制軟件,分別用于后續加載到AI處理器的模型計算、芯片啟動控制和功耗控制。 |
npu-driver | 部署在昇騰服務器,功能類似英偉達驅動,管理查詢昇騰AI處理器,同時為上層CANN軟件提供芯片控制、資源分配等接口。 |
CANN | 部署在昇騰服務器,功能類似英偉達CUDA,包含Runtime、算子庫、圖引擎、媒體數據處理等組件,通過AscendCL(Ascend Computing Language,昇騰計算語言)對外提供Device管理、Context管理、Stream管理、內存管理、模型加載與執行、算子加載與執行、媒體數據處理等API,幫助開發者實現在昇騰軟硬件平臺上開發和運行AI業務。CANN軟件按照功能主要分為Toolkit(開發套件)、NNAE(深度學習引擎)、NNRT(離線推理引擎)、TFPlugin(TensorFlow框架插件)幾種軟件包,各軟件包支持功能范圍如下:Toolkit:支持訓練和推理業務、模型轉換、算子/應用/模型開發和編譯。NNAE:支持訓練和推理業務、模型轉換。NNRT:僅支持推理業務。TFPlugin:用于運行訓練業務時和TensorFlow框架進行對接,幫助TensorFlow框架調用底層CANN接口運行訓練業務。 |
ToolBox | ToolBox包含運維檢查工具(Acsend DMI工具)和容器引擎插件(Ascend Docker),運維檢查工具能夠檢測設備狀態(如帶寬、設備實時狀態等);容器引擎插件本質上是基于OCI標準實現的Docker Runtime,不修改Docker引擎,對Docker以插件方式提供Ascend NPU適配功能,使用戶AI作業能夠以Docker容器的方式平滑運行在昇騰設備上。 |
- npu-firmware:在運行環境中安裝,依賴昇騰AI處理器。
- npu-driver:在運行環境中安裝,依賴昇騰AI處理器。
- toolkit:在開發環境中安裝,不依賴昇騰AI處理器。
- nnrt:離線推理引擎包,用于應用程序的模型推理。僅支持離線推理,依賴昇騰AI處理器。
- nnae:深度學習引擎,支持在線訓練、在線推理、離線推理。
- toolbox:在運行環境中安裝,依賴昇騰AI處理器。
3)下載軟件
-
主板相關固件及驅動【可選】:
選擇CANN 5.1.RC2.alpha008版本
- KylinV10SP1 驅動包:A500-Pro-3000-iDriver_V106_KylinV10SP1.zip
- 其他按需安裝
-
選擇CANN 5.1.RC2.alpha008版本
- Atlas 300I 推理卡(型號:3000)驅動:A300-3000-npu-driver_5.1.rc2_linux-aarch64.run
- Atlas 300I 推理卡(型號:3000)固件:A300-3000-npu-firmware_5.1.rc2.run
-
選擇5.1.RC2.alpha008版本
- Toolkit(開發套件包):Ascend-cann-toolkit_5.1.RC2_linux-aarch64.run
- NNAE(深度學習引擎):Ascend-cann-nnae_5.1.RC2_linux-aarch64.run
- NNRT(推理引擎):Ascend-cann-nnrt_5.1.RC2_linux-aarch64.run
- AMCT(模型壓縮工具):Ascend-cann-amct_5.1.RC2_linux-aarch64.tar.gz
- Device-SDK(包含昇騰310/310P驅動包、acl、ctrlcpu庫):Ascend-cann-device-sdk_5.1.RC2_linux-aarch64.zip
-
- Toolbox(包含容器引擎插件Ascend-docker runtime、Ascend-DMI工具等):Ascend-mindx-toolbox_3.0.RC3_linux-aarch64.run
3.安裝固件、驅動及軟件包
首次安裝按照“驅動 > 固件”的順序;覆蓋安裝或升級按照“固件 > 驅動”順序。
1)確認基礎信息
$ tree Ascned_22.0.RC2/
.
├── Atlas300I_3000_Firmware_Driver
│ ├── A300-3000-npu-driver_5.1.rc2_linux-aarch64.run
│ └── A300-3000-npu-firmware_5.1.rc2.run
├── CANN5.1.RC2
│ ├── Ascend-cann-amct_5.1.RC2_linux-aarch64.tar.gz
│ ├── Ascend-cann-device-sdk_5.1.RC2_linux-aarch64.zip
│ ├── Ascend-cann-nnae_5.1.RC2_linux-aarch64.deb
│ ├── Ascend-cann-nnae_5.1.RC2_linux-aarch64.run
│ ├── Ascend-cann-nnrt_5.1.RC2_linux-aarch64.deb
│ ├── Ascend-cann-nnrt_5.1.RC2_linux-aarch64.run
│ ├── Ascend-cann-toolkit_5.1.RC2_linux-aarch64.deb
│ └── Ascend-cann-toolkit_5.1.RC2_linux-aarch64.run
└── ToolBox
└── Ascend-mindx-toolbox_3.0.RC3_linux-aarch64.run
# 檢測Atlas 300I 推理卡(型號:3000)是否正常在位
$ lspci | grep d100
06:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d100 (rev 20)
07:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d100 (rev 20)
08:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d100 (rev 20)
09:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d100 (rev 20)
# 確認操作系統和內核版本
$ uname -m && cat /etc/*release
aarch64
Kylin Linux Advanced Server release V10 (Tercel)
DISTRIB_ID=Kylin
DISTRIB_RELEASE=V10
DISTRIB_CODENAME=juniper
DISTRIB_DESCRIPTION="Kylin V10"
DISTRIB_KYLIN_RELEASE=V10
DISTRIB_VERSION_TYPE=enterprise
DISTRIB_VERSION_MODE=normal
NAME="Kylin Linux Advanced Server"
VERSION="V10 (Tercel)"
ID="kylin"
VERSION_ID="V10"
PRETTY_NAME="Kylin Linux Advanced Server V10 (Tercel)"
ANSI_COLOR="0;31"
$ uname -r
4.19.90-23.8.v2101.ky10.aarch64
2)創建運行用戶HwHiAiUser
# 安裝驅動前需要創建驅動運行用戶(運行驅動進程的用戶)
groupadd HwHiAiUser
useradd -g HwHiAiUser -d /home/HwHiAiUser -m HwHiAiUser -s /bin/bash
# 設置HwHiAiUser用戶密碼
passwd HwHiAiUser
3)安裝驅動及固件
$ cd Atlas300I_3000_Firmware_Driver
$ chmod +x *.run
# 安裝驅動
$ ./A300-3000-npu-driver_5.1.rc2_linux-aarch64.run --full --install-for-all
# 查看驅動加載是否成功
$ npu-smi info
+------------------------------------------------------------------------------------------------+
| npu-smi 22.0.2 Version: 22.0.2 |
+-----------------------+-----------------+------------------------------------------------------+
| NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) |
| Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) |
+=======================+=================+======================================================+
| 2 310 | OK | 12.8 49 0 / 970 |
| 0 0 | 0000:06:00.0 | 0 633 / 7764 |
+-----------------------+-----------------+------------------------------------------------------+
| 2 310 | OK | 12.8 49 0 / 970 |
| 1 1 | 0000:07:00.0 | 0 634 / 7764 |
+-----------------------+-----------------+------------------------------------------------------+
| 2 310 | OK | 12.8 52 0 / 970 |
| 2 2 | 0000:08:00.0 | 0 634 / 7764 |
+-----------------------+-----------------+------------------------------------------------------+
| 2 310 | OK | 12.8 48 0 / 970 |
| 3 3 | 0000:09:00.0 | 0 634 / 7764 |
+=======================+=================+======================================================+
$ /usr/local/Ascend/driver/tools/upgrade-tool --device_index -1 --component -1 --version
{
Get component version(1.82.22.2.220) succeed for deviceId(0), componentType(0).
{"device_id":0, "component":nve, "version":1.82.22.2.220}
...
}
$ ./A300-3000-npu-firmware_5.1.rc2.run --full
# 查看芯片信息
$ ascend-dmi -i -dt
================================Product Details===============================
ascend-dmi : 3.0.RC3
Card Quantity : 1
Type : Atlas 300I-3000
Card Manufacturer : Huawei
Card Serial Number : 033EFS10M8001498
...
$ reboot
4.安裝軟件包
基于Kylin V10 SP1
1)物理機部署
# 1.檢查root用戶的umask值是否為0022
umask
# 否則 umask 0022
# 2.安裝依賴
yum install -y gcc gcc-c++ make cmake unzip zlib-devel libffi-devel openssl-devel pciutils net-tools sqlite-devel lapack-devel openblas-devel gcc-gfortran
# 檢測是否已安裝python 3.7.x
python3 --version
yum install -y python3-pip
pip3 install attrs cython numpy decorator sympy cffi pyyaml pathlib2 psutil protobuf scipy requests absl-py
# 安裝Toolkit
cd CRNN_Package
chmod +x *.run
./Ascend-cann-toolkit_6.0.0.alpha002_linux-aarch64.run --install
# 配置環境變量
vi ~/.bashrc
# 在文件最后一行后面添加
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source ~/.bashrc
2)容器部署【推薦】
# 安裝Docker
$ yum install docker
$ docker --version
Docker version 18.09.0, build 62eb848
# 安裝toolbox
$ cd ToolBox
$ chmod +x *.run
$ ./Ascend-mindx-toolbox_3.0.RC3_linux-aarch64.run --install
# 配置環境變量
$ vi ~/.bashrc
# 在文件最后一行后面添加
source /usr/local/Ascend/toolbox/set_env.sh
$ source ~/.bashrc
從AscendHub拉取容器鏡像
- infer-modelzoo【推理】
- ModelZoo 推理基礎鏡像,包含模型轉換、模型推理功能,鏡像中安裝了toolkit和sdk及其依賴的軟件,其中sdk默認安裝的為mxmanufacture,另一個版本安裝的是mxvision。
- ascend-infer【推理】
- Ascend-infer基礎鏡像,基于centos7.6,ubuntu18.04制作,內部集成推理通用的第三方庫(系統包、pip)和NNRT推理引擎。
- pytorch-modelzoo【訓練+推理】
- ModelZoo PyTorch框架基礎鏡像,基于PyTorch 1.5.0或 1.8.1版本制作的基礎鏡像,鏡像中安裝了nnae,包含訓練、轉換和推理功能。
docker login -u xxx -p xxx ascendhub.huawei.com
# infer-modelzoo
docker pull ascendhub.huawei.com/public-ascendhub/infer-modelzoo:22.0.RC2
# ascend-infer
docker pull ascendhub.huawei.com/public-ascendhub/ascend-infer:22.0.RC2-centos7.6
# pytorch-modelzoo
docker pull ascendhub.huawei.com/public-ascendhub/pytorch-modelzoo:22.0.RC2 # pytorch1.5.0+ascend.post6
docker pull ascendhub.huawei.com/public-ascendhub/pytorch-modelzoo:22.0.RC2-1.8.1 # pytorch1.8.1
啟動離線推理容器
#/bin/bash
export MY_CONTAINER="infer-modelzoo"
num=`sudo docker ps -a|grep -w "$MY_CONTAINER"|wc -l`
echo $num
echo $MY_CONTAINER
if [ 0 -eq $num ];then
docker run -it -u root \
--device=/dev/davinci0 \ # 默認掛載加速卡0到容器中
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
-itd \
--name $MY_CONTAINER \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v $PWD:/home/share \
ascendhub.huawei.com/public-ascendhub/infer-modelzoo:22.0.RC2 \
/bin/bash
else
#docker start $MY_CONTAINER
docker exec -ti $MY_CONTAINER /bin/bash
fi
啟動訓練+在線推理容器
#/bin/bash
export MY_CONTAINER="pytorch-modelzoo"
num=`sudo docker ps -a|grep -w "$MY_CONTAINER"|wc -l`
echo $num
echo $MY_CONTAINER
if [ 0 -eq $num ];then
docker run -it -u root \
--device=/dev/davinci0 \ # 默認掛載加速卡0到容器中
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
-itd \
--name $MY_CONTAINER \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-v /var/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
-v /var/log/npu/slog/:/var/log/npu/slog \
-v /var/log/npu/profiling/:/var/log/npu/profiling \
-v /var/log/npu/dump/:/var/log/npu/dump \
-v /var/log/npu/:/usr/slog \
-v $PWD:/home/share \
ascendhub.huawei.com/public-ascendhub/pytorch-modelzoo:22.0.RC2-1.8.1 \
/bin/bash
else
#docker start $MY_CONTAINER
docker exec -ti $MY_CONTAINER /bin/bash
fi
-
該容器還需要更新torchvision版本
#PyTorch 1.8.1需安裝0.9.1版本,PyTorch 1.11.0需安裝0.12.0版本,PyTorch 1.5.0需安裝0.6.0版本 pip3 install torchvision==0.9.1
-
想要在pytorch-modelzoo容器中進行離線模型推理,還需要安裝cann-toolkit。
dpkg -i Ascend-cann-toolkit_5.1.RC2_linux-aarch64.deb source /usr/local/Ascend/ascend-toolkit/set_env.sh
注意:只能同時運行一個容器,后啟動的容器無法使用設備資源。
5.模型推理測試
infer-modelzoo容器環境中測試
1)Ascend CANN Samples
CANN樣例倉庫以CANN AscendCL接口進行開發,制作的一系列給開發者進行參考學習的樣例。
git clone https://gitee.com/ascend/samples.git
# 測試圖像分類樣例
cd samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification
# 準備源模型
mkdir model && cd model
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/AE/ATC%20Model/resnet50/resnet50.caffemodel
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/AE/ATC%20Model/resnet50/resnet50.prototxt
# 準備測試圖片
cd ../data
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg
# 源模型轉om模型
cd ../
atc --model=model/resnet50.prototxt --weight=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
# 模型推理
$ python3 src/acl_net.py
Using device id:0
model path:/home/share/samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/../model/resnet50.om
images path:/home/share/samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/../data
init resource stage:
model_id:1
init resource success
images:/home/share/samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/../data/dog2_1024_683.jpg
data interaction from host to device
data interaction from host to device success
execute stage:
execute stage success
data interaction from device to host
data interaction from device to host success
======== top5 inference results: =============
[267]: 0.935547
[266]: 0.041107
[265]: 0.018967
[219]: 0.002865
[160]: 0.000311
images:/home/share/samples/python/level2_simple_inference/1_classification/resnet50_imagenet_classification/src/../data/dog1_1024_683.jpg
data interaction from host to device
data interaction from host to device success
execute stage:
execute stage success
data interaction from device to host
data interaction from device to host success
======== top5 inference results: =============
[161]: 0.763672
[162]: 0.157593
[167]: 0.039215
[163]: 0.021835
[166]: 0.011871
*****run finish******
Releasing resources stage:
Resources released successfully.
2)MindX SDK
包含如下sample:
- mxManufacture:制造業視覺質檢
- mxVision:智能視頻/圖像分析,主要功能如下:
- 快速構建推理業務:通過修改流程編排配置文件,可快速構建推理業務,通過API調用,向構建完成的推理業務發送請求,得到推理結果Json字符串或者原始數據結構。
- 自定義功能插件:通過SDK提供的插件開發工具和業務邏輯開發基礎庫,用戶可自行開發新插件。
- mxIndex:特征類聚與檢索
基于 infer-modelzoo容器測試mxManufacture:
# infer-modelzoo容器中
cd /home/hwMindX/sdk_home/mxManufacture && ls
bin config filelist.txt include lib opensource operators python samples set_env.sh toolkit version.info
# 使MindX SDK mxManufacture環境變量生效
bash set_env.sh
使用mxManufacture開發一個簡單的圖片分類的Demo
- 參考快速入門
6.Ascend實用工具
1)Ascend Tools
-
msame【模型推理工具】
輸入.om模型和模型所需要的輸入bin文件,輸出模型的輸出數據文件。
-
img2bin【bin文件生成工具】
生成模型推理所需的輸入數據,以.bin格式保存。
-
makesd【制卡工具】
制卡工具包,提供ubuntu下制卡功能。
-
configure_usb_ethernet【USB虛擬網卡連接腳本】
配置USB網卡對應的IP地址。
-
pt2pb【pytorch模型轉tensorflow pb模型工具】
輸入pytorch權重參數模型,轉為onnx,再轉為pb模型
-
dnmetis【NPU推理精度和性能測試工具】
使用Python封裝ACL的C++接口,輸入om模型和原始數據集圖片、標簽,即可執行模型推理,輸出精度數據和性能數據。
-
msquickcmp【一鍵式全流程精度比對工具】
該工具適用于tensorflow和onnx模型,輸入原始模型和對應的離線om模型,輸出精度比對結果。
-
precision_tool【精度問題分析工具】
該工具包提供了精度比對常用的功能,當前該工具主要適配Tensorflow訓練場景,同時提供Dump數據/圖信息的交互式查詢和操作入口。
-
cann-benchmark_infer_scripts【cann-benchmark推理軟件對應的模型前后處理腳本】
該工具包含cann-benchmark推理工具模型處理腳本, 包括:結果解析腳本和前后處理腳本等。這些腳本需根據cann-benchmark指導手冊說明使用。
-
tfdbg_ascend【Tensorflow2.x dump工具】
該工具提供CPU/GPU平臺上Tensorflow2.x運行時數據Dump能力。
-
ais-bench_workload【ais-bench_workload】
該目錄包含基于Ais-Bench軟件的訓練和推理負載程序,用于測試驗證。Ais-Bench是基于AI標準針對AI服務器進行性能測試的工具軟件。
-
intelligent_edge_tools【intelligent_edge_tools】
該目錄包含智能邊緣工具集。
-
auto-optimizer【auto-optimizer】
提供基于ONNX的改圖、自動優化及端到端推理流程。
-
saved_model2om【TensorFlow1.15 saved_model模型轉om模型工具】
輸入TensorFlow存儲的saved_model模型,轉換為pb模型,再轉換為om模型
2) Ascend CANN Parser
Ascend CANN Parser(簡稱parser)配合TF_Adapter、 ATC工具、IR構圖等使用,開發者通過以上工具,借助parser能方便地將第三方框架的算法表示轉換成Ascend IR。
3)Ascend ModelZoo
模型庫包含pytorch與tensorflow的一系列模型及腳本。
也可以通過官網搜索模型。
三、Ascend PyTorch 在線推理
在線推理是在AI框架內執行推理的場景,相比于離線推理場景,使用在線推理可以方便將原來基于PyTorch框架做推理的應用快速遷移到昇騰AI處理器,適用于數據中心推理場景。
1.環境準備
-
支持在線推理的芯片型號
- Ascend310
- Ascend310P*
- Ascend910*
Ascend Pytorch版本對應關系
-
安裝依賴
# CentOS yum install -y patch libjpeg-turbo-devel dos2unix git yum install -y gcc==7.3.0 cmake==3.12.0 # Ubuntu apt-get update apt-get install -y patch build-essential libbz2-dev libreadline-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev m4 dos2unix git apt-get install -y gcc==7.3.0 cmake==3.12.0 #3.12.0版本及以上 # 安裝PyTorch環境依賴 pip3 install pyyaml pip3 install wheel
2.運行Ascend Pytorch在線推理樣例
1)環境準備
基于pytorch-modelzoo容器運行
- 鏡像:ascendhub.huawei.com/public-ascendhub/pytorch-modelzoo:22.0.RC2-1.8.1
# 初始化nnae環境變量
source /usr/local/Ascend/nnae/set_env.sh
# 可選配置
# 指定芯片的邏輯ID
export ASCEND_DEVICE_ID=0
# 輸出日志信息,可根據實際修改
export ASCEND_SLOG_PRINT_TO_STDOUT=1
# Task多線程下發
export ASCEND_GLOBAL_LOG_LEVEL=0
2)樣例準備
以ResNet50模型為例,執行在線推理樣例。
-
下載預訓練模型。
打開ModelZoo中ResNet50詳情頁,單擊該頁面的“下載模型“下載已訓練好的模型文件。
-
編輯推理腳本。
創建“resnet50_infer_for_pytorch.py“模型腳本文件,并參考樣例代碼寫入相關代碼。
-
執行推理
$ tree nnae_sample/ -L 2 nnae_sample/ ├── data │ └── val │ ├── val │ ├── dog1_1024_683.jpg │ ├── dog2_1024_683.jpg ├── ResNet50_for_Pytorch_1.4_model │ ├── resnet50_pytorch_1.4.om │ ├── resnet50_pytorch_1.4.onnx │ └── resnet50_pytorch_1.4.pth.tar └── resnet50_infer_for_pytorch.py $ python3 resnet50_infer_for_pytorch.py \ --data ./data \ --npu 0 \ --epochs 90 \ --resume ResNet50_for_Pytorch_1.4_model/resnet50_pytorch_1.4.pth.tar use npu:0 => creating model 'resnet50' Selected optimization level O2: FP16 training with FP32 batchnorm and FP32 master weights. Defaults for this optimization level are: enabled : True opt_level : O2 cast_model_type : torch.float16 patch_torch_functions : False keep_batchnorm_fp32 : True master_weights : True loss_scale : dynamic combine_grad : None combine_ddp : None ddp_replica_count : 4 check_combined_tensors : None user_cast_preferred : None Processing user overrides (additional kwargs that are not None)... After processing overrides, optimization options are: enabled : True opt_level : O2 cast_model_type : torch.float16 patch_torch_functions : False keep_batchnorm_fp32 : True master_weights : True loss_scale : 1024.0 combine_grad : None combine_ddp : None ddp_replica_count : 4 check_combined_tensors : None user_cast_preferred : None => loading checkpoint 'ResNet50_for_Pytorch_1.4_model/resnet50_pytorch_1.4.pth.tar' => loaded checkpoint 'ResNet50_for_Pytorch_1.4_model/resnet50_pytorch_1.4.pth.tar' (epoch 90) Test: [0/1] Time 3.165 ( 0.000) Acc@1 0.00 ( 0.00) Acc@5 0.00 ( 0.00) * Acc@1 0.000 Acc@5 0.000 THPModule_npu_shutdown success.
四、PyTorch模型遷移與轉換
1.模型遷移
1)模型算子評估
-
將原始模型及訓練腳本遷移到昇騰AI處理器上之前,可以將原始模型及訓練腳本在CPU上進行訓練,使用PyTorch profiler功能獲取當前模型算子列表并在《AI框架算子支持清單》中查找該算子查看是否支持
- 支持PyTorch1.5.0、PyTorch1.8.1、PyTorch1.11.0版本算子
當有不支持算子時,可修改模型腳本用等價支持的算子替換不支持算子或者參考《自定義算子開發指南》中“算子開發過程>算子適配>適配插件開發(PyTorch框架)”進行算子適配。
2)遷移方式
將基于PyTorch的訓練腳本遷移到昇騰AI處理器上進行訓練,目前有以下3種方式:
-
自動遷移【推薦】:訓練時,在訓練腳本中導入腳本轉換庫,導入后執行訓練。訓練腳本在運行的同時,會自動將腳本中的CUDA接口替換為昇騰AI處理器支持的NPU接口。整體過程為:邊訓練邊轉換。
- 僅PyTorch 1.8.1版本及以上使用,自動遷移方式較簡單,且修改內容最少,只需在訓練腳本中添加引入庫代碼。
import torch import torch_npu ..... from torch_npu.contrib import transfer_to_npu
工具遷移:訓練前,通過腳本遷移工具,自動將訓練腳本中的CUDA接口替換為昇騰AI處理器支持的NPU接口,并生成遷移報告(腳本轉換日志、不支持算子的列表、腳本修改記錄)。訓練時,運行轉換后的腳本。整體過程為:先轉換腳本,再進行訓練。
手工遷移:算法工程師通過對模型的分析、GPU與NPU代碼的對比進而對訓練腳本進行修改,以支持再昇騰AI處理器上執行訓練。
2.AMCT模型壓縮【可選】
昇騰模型壓縮工具(Ascend Model Compression Toolkit,簡稱AMCT)是通過模型壓縮技術(如融合,量化,張量分解等)將模型進行壓縮的工具包,壓縮后模型體積變小,部署到昇騰 AI 處理器件上后可使能低比特運算,提高計算效率。
3.導出ONNX模型
模型訓練完成后,保存的.pth或.pt文件可以通過PyTorch構建模型再加載權重的方法恢復,然后導出ONNX模型。
import torch
import torch_npu
import torch.onnx
import torchvision.models as models
# 設置使用CPU導出模型
device = torch.device("cpu")
def convert():
# 模型定義來自于torchvision,樣例生成的模型文件是基于resnet50模型
model = models.resnet50(pretrained = False)
resnet50_model = torch.load('resnet50.pth', map_location='cpu')
model.load_state_dict(resnet50_model)
batch_size = 1 #批處理大小
input_shape = (3, 224, 224) #輸入數據,改成自己的輸入shape
# 模型設置為推理模式
model.eval()
dummy_input = torch.randn(batch_size, *input_shape) # 定義輸入shape
torch.onnx.export(model,
dummy_input,
"resnet50_official.onnx",
input_names = ["input"], # 構造輸入名
output_names = ["output"], # 構造輸出名
opset_version=11, # ATC工具目前支持opset_version=9,10,11,12,13
dynamic_axes={"input":{0:"batch_size"}, "output":{0:"batch_size"}}) #支持輸出動態軸
)
if __name__ == "__main__":
convert()
4.離線模型轉換
昇騰張量編譯器(Ascend Tensor Compiler,簡稱ATC)是異構計算架構CANN體系下的模型轉換工具, 它可以將開源框架的網絡模型或Ascend IR定義的單算子描述文件(json格式)轉換為昇騰AI處理器支持的.om格式離線模型。
- 開源框架網絡模型經過Parser解析后,轉換為中間態IR Graph(CANN模型格式)。
- 中間態IR經過圖準備,圖拆分,圖優化,圖編譯等一系列操作后,轉成適配昇騰AI處理器的離線模型。
- 轉換后的離線模型上傳到板端環境,通過AscendCL接口加載模型文件實現推理過程。
- 可以將開源框架網絡模型轉換后的離線模型轉成json文件,或者直接將開源框架網絡模型通過ATC工具轉成json文件,方便文件查看。
1)不同網絡模型的轉換示例
-
Caffe網絡模型
atc --model=$HOME/module/resnet50.prototxt --weight=$HOME/module/resnet50.caffemodel --framework=0 --output=$HOME/module/out/caffe_resnet50 --soc_version=Ascend310
-
TensorFlow網絡模型
atc --model=$HOME/module/resnet50_tensorflow*.pb --framework=3 --output=$HOME/module/out/tf_resnet50 --soc_version=Ascend310
-
ONNX網絡模型
atc --model=$HOME/module/resnet50.onnx --framework=5 --output=$HOME/module/out/onnx_resnet50 --soc_version=Ascend310 # yolov5 源模型轉離線模型示例 # yolov5 源模型 轉 onnx模型 python export.py --weights yolov5l.pt --include onnx --imgsz 640 --batch-size 1 --opset 11 --simplify # onnx模型轉om模型 atc --model=yolov5l.onnx \ --framework=5 \ --output=yolov5l_b1 \ --input_format=NCHW \ --input_shape="images:1,3,640,640" \ --input_fp16_nodes="images" \ --soc_version=Ascend310 \ --output_type=FP16 \ --log=error
-
MindSpore網絡模型
atc --model=$HOME/module/ResNet50.air --framework=1 --output=$HOME/module/out/ResNet50_mindspore --soc_version=Ascend310
2)基礎功能參數配置
-
模型文件轉json文件
json文件可以查看基礎版本號
# 原始模型文件轉json文件 atc --mode=1 --om=$HOME/module/resnet50_tensorflow*.pb --json=$HOME/module/out/tf_resnet50.json --framework=3 # 離線模型轉json文件 atc --mode=1 --om=$HOME/module/out/tf_resnet50.om --json=$HOME/module/out/tf_resnet50.json
-
離線模型支持動態BatchSize/動態分辨率
# 動態BatchSize atc --model=$HOME/module/resnet50_tensorflow*.pb --framework=3 --output=$HOME/module/out/tf_resnet50 --soc_version=<soc_version> --input_shape="Placeholder:-1,224,224,3" --dynamic_batch_size="1,2,4,8" # 動態分辨率 atc --model=$HOME/module/resnet50_tensorflow*.pb --framework=3 --output=$HOME/module/out/tf_resnet50 --soc_version=<soc_version> --input_shape="Placeholder:1,-1,-1,3" --dynamic_image_size="224,224;448,448"
-
離線模型支持動態維度
atc --model=$HOME/module/resnet50_tensorflow*.pb --framework=3 --output=$HOME/module/out/tf_resnet50 --soc_version=<soc_version> --input_shape="Placeholder:-1,-1,-1,3" --dynamic_dims="1,224,224;8,448,448" --input_format=ND
-
自定義離線模型的輸入輸出數據類型
atc --model=$HOME/module/resnet50_tensorflow_1.7.pb --framework=3 --output=$HOME/module/out/tf_resnet50 --soc_version=<soc_version> --input_fp16_nodes="Placeholder" --out_nodes="fp32_vars/MaxPoolWithArgmax:0" --output_type="fp32_vars/MaxPoolWithArgmax:0:FP16"
3)AIPP功能配置
# 通過--insert_op_conf參數,插入aipp預處理算子
atc --model=$HOME/module/resnet50.prototxt --weight=$HOME/module/resnet50.caffemodel --framework=0 --insert_op_conf=$HOME/module/insert_op.cfg --output=$HOME/module/out/caffe_resnet50 --soc_version=<soc_version>
insert_op.cfg:aipp配置文件使用說明
aipp_op {
aipp_mode : static #AIPP配置模式
related_input_rank : 0 # 標識對第1個輸入進行AIPP處理【可選】
related_input_name : "data" # 標識對輸入名稱為data的節點進行AIPP處理【可選】
input_format : YUV420SP_U8 #輸入給AIPP的原始圖片格式
src_image_size_w : 250 #輸入給AIPP的原始圖片寬高
src_image_size_h : 250
crop: true #摳圖開關,用于改變圖片尺寸
load_start_pos_h: 0 #摳圖起始位置水平、垂直方向坐標
load_start_pos_w: 0
csc_switch : true #色域轉換開關【可選】
rbuv_swap_switch : false # RGB與BGR互轉
matrix_r0c0 : 256 #matrix:色域轉換系數,用戶無需修改
matrix_r0c1 : 0
matrix_r0c2 : 359
matrix_r1c0 : 256
matrix_r1c1 : -88
matrix_r1c2 : -183
matrix_r2c0 : 256
matrix_r2c1 : 454
matrix_r2c2 : 0
input_bias_0 : 0
input_bias_1 : 128
input_bias_2 : 128
mean_chn_0 : 0 # 每個通道的均值【可選】
mean_chn_1 : 0
mean_chn_2 : 0
var_reci_chn_0 : 0.0039216 # 每個通道方差的倒數【可選】,如:1/255
var_reci_chn_1 : 0.0039216
var_reci_chn_2 : 0.0039216
}
aipp_op {
...
}
-
# YUV420SP_U8轉RGB,輸入數據為JPEG圖像 aipp_op { aipp_mode: static input_format : YUV420SP_U8 csc_switch : true rbuv_swap_switch : false matrix_r0c0 : 256 matrix_r0c1 : 0 matrix_r0c2 : 359 matrix_r1c0 : 256 matrix_r1c1 : -88 matrix_r1c2 : -183 matrix_r2c0 : 256 matrix_r2c1 : 454 matrix_r2c2 : 0 input_bias_0 : 0 input_bias_1 : 128 input_bias_2 : 128 } # YUV420SP_U8轉BGR,輸入數據為JPEG圖像 aipp_op { aipp_mode: static input_format : YUV420SP_U8 csc_switch : true rbuv_swap_switch : false matrix_r0c0 : 256 matrix_r0c1 : 454 matrix_r0c2 : 0 matrix_r1c0 : 256 matrix_r1c1 : -88 matrix_r1c2 : -183 matrix_r2c0 : 256 matrix_r2c1 : 0 matrix_r2c2 : 359 input_bias_0 : 0 input_bias_1 : 128 input_bias_2 : 128 } # YUV420SP_U8轉BGR,輸入數據為JPEG圖像 aipp_op { aipp_mode: static input_format : YUV420SP_U8 csc_switch : true rbuv_swap_switch : true matrix_r0c0 : 256 matrix_r0c1 : 0 matrix_r0c2 : 359 matrix_r1c0 : 256 matrix_r1c1 : -88 matrix_r1c2 : -183 matrix_r2c0 : 256 matrix_r2c1 : 454 matrix_r2c2 : 0 input_bias_0 : 0 input_bias_1 : 128 input_bias_2 : 128 } # RGB888_U8轉RGB aipp_op { aipp_mode: static input_format : RGB888_U8 csc_switch : false rbuv_swap_switch : false } # RGB888_U8轉BGR aipp_op { aipp_mode : static input_format : RGB888_U8 csc_switch : false rbuv_swap_switch : true }
-
歸一化配置
mean_chn_i # 每個通道的均值 min_chn_i # 每個通道的最小值 var_reci_chn # 每個通道方差的倒數 pixel_out_chx(i)=[pixel_in_chx(i)-mean_chn_i-min_chn_i]*var_reci_chn
-
Crop/Padding配置
aipp_op { aipp_mode: static input_format: YUV420SP_U8 src_image_size_w: 320 src_image_size_h: 240 crop: true load_start_pos_w: 10 # 左上點坐標 load_start_pos_h: 20 crop_size_w: 50 # 裁剪后的圖像大小 crop_size_h: 60 padding: true left_padding_size: 20 # 在裁剪后的圖像四周padding的尺寸 right_padding_size: 15 top_padding_size: 20 bottom_padding_size: 15 padding_value: 0 # padding像素值 }
-
輸入圖像大小校驗
# YUV400_U8 N * src_image_size_w * src_image_size_h * 1 # YUV420SP_U8 N * src_image_size_w * src_image_size_h * 1.5 # XRGB8888_U8 N * src_image_size_w * src_image_size_h * 4 # RGB888_U8 N * src_image_size_w * src_image_size_h * 3
-
AIPP輸入數據格式說明
- 數據儲存格式
- AIPP輸入默認為NHWC排布,如果不是,將強制轉換為NHWC。
- 經過AIPP處理后的圖片,統一采用NC1HWC0的五維數據格式進行存儲。
- 圖像輸入格式
- AIPP支持的圖像輸入格式:YUV420SP_U8(NV12)、RGB888_U8、XRGB8888_U8、YUV400_U8。(輸入數據類型為UINT8)
- 數據儲存格式
4)ATC工具關鍵參數說明
ATC工具安裝在Ascend-cann-toolkit安裝目錄/ascend-toolkit/latest/bin下。
$ atc -h
===== Basic Functionality =====
[General] # 基礎功能
--mode Run mode.
0(default): generate offline model;
1: convert model to JSON format;
3: only pre-check;
5: convert ge dump txt file to JSON format;
6: display model info
[Input]
--model 原始網絡模型文件路徑
--weight 原始網絡模型權重文件路徑與文件名,僅當原始網絡模型是Caffe時需要指定。
--om 需要轉換為json格式的離線模型或原始模型
--framework Framework type.
0:Caffe;
1:MindSpore;
3:Tensorflow;
5:Onnx
--input_format 輸入數據存儲格式。
當原始框架為Caffe時,支持NCHW(默認)、ND(動態維度)
當原始框架為ONNX時,支持NCHW(默認)、NCDHW、ND
當原始框架是TensorFlow時,支持NCHW、NHWC(默認)、ND(模型轉換時根據data_format屬性的算子,推導出具體的format)、NCDHW、NDHWC
--input_shape 指定模型輸入數據的shape
E.g.: "input_name1:n1,c1,h1,w1;input_name2:n2,c2,h2,w2"
--input_shape_range 指定模型輸入數據的shape范圍,暫不支持
E.g.: "input_name1:[n1~n2,c1,h1,w1];input_name2:[n2,c2~c3,h2,w2]"
--dynamic_batch_size 設置動態BatchSize參數,適用于執行推理時,每次處理圖片數量不固定的場景。
E.g.: "1,2,4,8"
--dynamic_image_size 設置輸入圖片的動態分辨率參數。適用于執行推理時,每次處理圖片寬和高不固定的場景。需要與--input_shape配合使用,
E.g.: --input_shape="data:8,3,-1,-1;img_info:8,4,-1,-1" --dynamic_image_size="416,416;832,832"
--dynamic_dims 設置ND格式下動態維度的檔位。適用于執行推理時,每次處理任意維度的場景。N<=4。
E.g.: "dims1_n1,dims1_n2;dims2_n1,dims2_n2"
--singleop 單算子定義文件,將單個算子Json文件轉換成適配昇騰AI處理器的離線模型。以便進行后續的單算子功能驗證。
[Output]
--output Output file path
--output_type 指定某個輸出節點的輸出類型,需要與--out_nodes參數配合使用。
FP32:推薦分類網絡、檢測網絡使用。
UINT8:推薦圖像超分辨率網絡使用。
FP16:推薦分類網絡、檢測網絡使用。通常用于一個網絡輸出作為另一個網絡輸入場景。
E.g.: --output_type="conv1:0:FP16" --out_nodes="conv1:0".
--check_report 預檢結果保存文件路徑
--json 離線模型或原始模型文件轉換的json格式文件
[Target]
--soc_version The soc version.
Ascend310
Ascend910
--virtual_type 是否支持離線模型在算力分組生成的虛擬設備上運行。
0 (default) : Disable virtualization; 1 : Enable virtualization.
--core_type 設置網絡模型使用的Core類型
VectorCore: use vector core.
AiCore: Default
--aicore_num 設置模型編譯時使用的aicore數量
===== Advanced Functionality =====
[Feature] # 功能配置選項
--out_nodes 指定某層輸出節點(算子)作為網絡模型的輸出,如果不指定,則模型的輸出默認為最后一層的算子信息。適合算子調試。
E.g.: "node_name1:0;node_name1:1;node_name2:0"
--input_fp16_nodes 指定輸入數據類型為FP16的輸入節點名稱。 配置了該參數,則不能對同一個輸入節點同時使用--insert_op_conf參數。
E.g.: "node_name1;node_name2"
--insert_op_conf 插入新算子的配置文件,例如aipp預處理算子。使用該參數后,則輸入數據類型為UINT8。
--op_name_map 擴展算子(非標準算子)映射配置文件
--is_input_adjust_hw_layout 與--input_fp16_nodes配合使用。若該參數設置為true,對應--input_fp16_nodes節點的輸入數據類型為float16,輸入數據格式為NC1HWC0。
--is_output_adjust_hw_layout 與--out_nodes配合使用。若該參數設置為true,對應--out_nodes中輸出節點的輸出數據類型為float16,數據格式為NC1HWC0。
[Model Tuning] # 模型調優選項
--disable_reuse_memory 內存復用開關
--fusion_switch_file 融合規則(包括圖融合和UB融合)開關配置文件
--enable_scope_fusion_passes 指定編譯時需要生效的融合規則列表
--enable_single_stream 是否使能一個模型推理時只能使用一條Stream。
true: enable;
false(default): disable
--enable_small_channel 是否使能small channel的優化,使能后在channel<=4的卷積層會有性能收益。建議與--insert_op_conf參數(AIPP功能)配合使用
0(default): disable;
1: enable
--enable_compress_weight Enable compress weight. true: enable; false(default): disable
--compress_weight_conf 壓縮權重的配置文件
--compression_optimize_conf 壓縮優化功能配置文件,暫不支持。
--sparsity Optional; enable structured sparse. 0(default): disable; 1: enable
--buffer_optimize 數據緩存優化開關
"l2_optimize" (default),
"l1_optimize",
"off_optimize"
--mdl_bank_path 加載子圖調優后自定義知識庫的路徑
[Operator Tuning] # 算子調優選項
--op_precision_mode 設置具體某個算子的精度模式,通過 (.ini)配置文件設置。
--precision_mode 設置網絡模型的精度模式。支持如下:
force_fp16(default),
force_fp32, allow_mix_precision,
allow_fp32_to_fp16, must_keep_origin_dtype.
--modify_mixlist 混合精度場景下,修改算子使用混合精度名單。
--keep_dtype 保持原始模型編譯時個別算子的計算精度不變。
--customize_dtypes 模型編譯時自定義算子的計算精度。
--auto_tune_mode 設置算子的自動調優模式。
E.g.: "GA,RL", support configure multiple, spit by ,
--op_bank_path 加載Auto Tune調優后自定義知識庫的路徑。
--op_select_implmode 選擇算子是高精度實現還是高性能實現。支持如下:
high_precision,
high_performance, default
high_precision_for_all,
high_performance_for_all.
--optypelist_for_implmode 列舉算子optype的列表,該列表中的算子使用--op_select_implmode參數指定的模式。 E.g.: "node_name1,node_name2"
--op_debug_level TBE算子編譯debug功能開關。
0 (default): Disable debug;
1: Enable TBE pipe_all, and generate the operator CCE file and Python-CCE mapping file (.json);
2: Enable TBE pipe_all, generate the operator CCE file and Python-CCE mapping file (.json), and enable the CCE compiler -O0-g.
3: Disable debug, and keep generating kernel file (.o and .json)
4: Disable debug, keep generation kernel file (.o and .json) and generate the opera
五、離線推理應用開發
1.AscendCL
AscendCL(Ascend Computing Language)是一套用于在昇騰平臺上開發深度神經網絡推理應用的C語言API庫,提供Device管理、Context管理、Stream管理、內存管理、模型加載與執行、算子加載與執行、媒體數據處理等C語言API庫。
在運行應用時,AscendCL調用GE執行器提供的接口實現模型和算子的加載與執行、調用運行管理器的接口實現Device管理、Context管理、Stream管理、內存管理等。
計算資源層是昇騰AI處理器的硬件算力基礎,主要完成神經網絡的矩陣相關計算、完成控制算子/標量/向量等通用計算和執行控制功能、完成圖像和視頻數據的預處理,為深度神經網絡計算提供了執行上的保障。
pyACL(Python Ascend Computing Language)就是在AscendCL的基礎上使用CPython封裝得到的Python API庫。
- 邏輯架構圖:
1)接口調用流程
-
AscendCL初始化。
調用acl.init接口實現初始化pyACL。
-
運行管理資源申請。
依次申請運行管理資源:Device、Context、Stream。
-
算子調用
- 加載算子om文件,運行算子時使用。
- 執行算子,輸出算子的運行結果。
-
模型推理。
- 模型加載
- (可選)數據預處理:可實現JPEG圖片解碼、視頻解碼、摳圖/圖片縮放/格式轉換、JPEG圖片編碼、視頻編碼等功能。參見AIPP與DVPP。
- 模型推理
- (可選)數據后處理:處理模型推理的結果。
- 模型卸載:調用acl.mdl.unload接口卸載模型。
-
運行管理資源釋放。
所有數據處理都結束后,需要依次釋放運行管理資源:Stream、Context、Device。
-
pyACL去初始化。
調用acl.finalize接口實現pyACL去初始化。
2.預處理模塊AIPP與DVPP
1)AIPP
AIPP(Artificial Intelligence Pre-Processing)在AI Core上完成數據預處理,主要功能包括改變圖像尺寸
(Crop/Padding配置)、色域轉換
(轉換圖像格式)、歸一化配置
(減均值/乘系數)等。可通過ATC工具配置模型的AIPP功能。
AIPP使能模式:
- 靜態AIPP:模型生成后,AIPP參數值被保存在離線模型中,每次模型推理過程采用固定的AIPP預處理參數進行處理,而且在之后的推理過程中無法通過業務代碼進行直接的修改。
- 動態AIPP:每次模型推理前,根據需求,在執行模型前設置動態AIPP參數值,然后在模型執行時可使用不同的AIPP參數。動態AIPP參數值會根據需求在不同的業務場景下選用合適的參數(如不同攝像頭采用不同的歸一化參數,輸入圖片格式需要兼容YUV420和RGB等)。
AIPP支持的圖像輸入格式:
- YUV420SP_U8、RGB888_U8、XRGB8888_U8、YUV400_U8。
2)DVPP
DVPP(Digital Vision Pre-Processor)是昇騰AI處理器內置的圖像處理單元,通過pyACL媒體數據處理接口提供強大的媒體處理硬加速能力,主要功能包括縮放、摳圖、格式轉換、圖片編解碼、視頻編解碼等。
-
pyACL提供了基于DVPP硬件的媒體數據處理接口
功能 說明 VPC(Vision Preprocessing Core) 處理YUV、RGB等格式的圖片,包括縮放、摳圖、圖像金字塔、色域轉換等。 JPEGD(JPEG Decoder) JPEG壓縮格式-->YUV格式的圖片解碼。 JPEGE(JPEG Encoder) YUV格式-->JPEG壓縮格式的圖片編碼。 VDEC(Video Decoder) H264/H265格式-->YUV/RGB格式的視頻碼流解碼。 VENC(Video Encoder) YUV420SP格式-->H264/H265格式的視頻碼流編碼。 PNGD(PNG decoder) PNG格式-->RGB格式的圖片解碼。 -
昇騰AI處理器對媒體數據處理V1版本各功能的支持度
昇騰AI處理器 VPC JPEGD JPEGE PNGD VDEC VENC 昇騰310 AI處理器 √ √ √ √ √ √ 昇騰910 AI處理器 √ √ √ √ √ x 昇騰310P AI處理器 √ √ √ √ √ √
3)AIPP與DVPP區別
- DVPP對輸入、輸出有特殊的限制(基于處理速度和處理占有量的考慮),對輸出圖片的寬高有對齊要求,且其輸出格式通常為YUV420SP等格式。
- AIPP能力是對DVPP能力的有效補充,AIPP主要用于在AI Core上完成數據預處理,AIPP提供色域轉換功能、Crop(摳圖)和Padding(補邊)功能,可以輸出色域轉換和固定大小的圖片。
- 處理順序:原圖/視頻流 -> DVPP -> AIPP -> 模型推理。
3.Python推理
基于現有模型,使用pyACL提供的Python語言API庫開發深度神經網絡應用,用于實現目標識別、圖像分類等功能。
1)推理過程
# 導入acl模塊
import acl
# 1.pyACL初始化
ret = acl.init()
# 2.運行管理資源申請(Device、Context及Stream)
self.device_id = 0
# 指定運算的Device。
ret = acl.rt.set_device(self.device_id)
# 顯式創建一個Context,用于管理Stream對象。
self.context, ret = acl.rt.create_context(self.device_id)
# 3.加載模型,并獲取模型描述信息
# 初始化變量。
self.model_path = './model/resnet50.om'
# 加載離線模型文件,返回標識模型的ID。
self.model_id, ret = acl.mdl.load_from_file(self.model_path)
# 根據加載成功的模型的ID,獲取該模型的描述信息。
self.model_desc = acl.mdl.create_desc()
ret = acl.mdl.get_desc(self.model_desc, self.model_id)
# 4.準備模型推理的輸入、輸出數據結構
# 初始化變量。
ACL_MEM_MALLOC_HUGE_FIRST = 0
# 創建aclmdlDataset類型的數據,描述模型推理的輸入。
self.load_input_dataset = acl.mdl.create_dataset()
# 獲取模型輸入的數量。
input_size = acl.mdl.get_num_inputs(self.model_desc)
self.input_data = []
# 循環為每個輸入申請內存,并將每個輸入添加到aclmdlDataset類型的數據中。
for i in range(input_size):
buffer_size = acl.mdl.get_input_size_by_index(self.model_desc, i)
# 獲取模型輸入維度
dims, ret = acl.mdl.get_input_dims(self.model_desc, i)
# 申請輸入內存。
buffer, ret = acl.rt.malloc(buffer_size, ACL_MEM_MALLOC_HUGE_FIRST)
data = acl.create_data_buffer(buffer, buffer_size)
_, ret = acl.mdl.add_dataset_buffer(self.load_input_dataset, data)
self.input_data.append({"buffer": buffer, "size": buffer_size})
# 準備模型推理的輸出數據集。
# 創建aclmdlDataset類型的數據,描述模型推理的輸出。
self.load_output_dataset = acl.mdl.create_dataset()
# 獲取模型輸出的數量。
output_size = acl.mdl.get_num_outputs(self.model_desc)
self.output_data = []
# 循環為每個輸出申請內存,并將每個輸出添加到aclmdlDataset類型的數據中。
for i in range(output_size):
buffer_size = acl.mdl.get_output_size_by_index(self.model_desc, i)
# 申請輸出內存。
buffer, ret = acl.rt.malloc(buffer_size, ACL_MEM_MALLOC_HUGE_FIRST)
data = acl.create_data_buffer(buffer, buffer_size)
_, ret = acl.mdl.add_dataset_buffer(self.load_output_dataset, data)
self.output_data.append({"buffer": buffer, "size": buffer_size})
# 5.準備模型推理的輸入數據
img = cv2,imread("test.jpg")
# img前處理
bytes_data = img.tobytes()
np_ptr = acl.util.bytes_to_ptr(bytes_data)
# 將圖片數據從Host傳輸到Device。同步內存復制
ret = acl.rt.memcpy(self.input_data[0]["buffer"], self.input_data[0]["size"], np_ptr,
self.input_data[0]["size"], ACL_MEMCPY_HOST_TO_DEVICE)
# 6.執行模型推理。
# self.model_id表示模型ID,在模型加載成功后,會返回標識模型的ID。
ret = acl.mdl.execute(self.model_id, self.load_input_dataset, self.load_output_dataset)
# 7.處理模型推理的輸出數據。
inference_result = []
for i, item in enumerate(self.output_data):
buffer_host, ret = acl.rt.malloc_host(self.output_data[i]["size"])
# 將推理輸出數據從Device傳輸到Host。同步內存復制
ret = acl.rt.memcpy(buffer_host, self.output_data[i]["size"], self.output_data[i]["buffer"],
self.output_data[i]["size"], ACL_MEMCPY_DEVICE_TO_HOST)
# 將指針轉換bytes對象
bytes_out = acl.util.ptr_to_bytes(buffer_host, self.output_data[i]["size"])
# bytes轉numpy
data = np.frombuffer(bytes_out, dtype=np.byte)
inference_result.append(data)
tuple_st = struct.unpack("1000f", bytearray(inference_result[0]))
vals = np.array(tuple_st).flatten()
# 8.釋放模型推理的輸入、輸出資源。
# 釋放輸入資源,包括數據結構和內存。
while self.input_data:
item = self.input_data.pop()
ret = acl.rt.free(item["buffer"])
input_number = acl.mdl.get_dataset_num_buffers(self.load_input_dataset)
for i in range(input_number):
data_buf = acl.mdl.get_dataset_buffer(self.load_input_dataset, i)
if data_buf:
ret = acl.destroy_data_buffer(data_buf)
ret = acl.mdl.destroy_dataset(self.load_input_dataset)
# 釋放輸出資源,包括數據結構和內存。
while self.output_data:
item = self.output_data.pop()
ret = acl.rt.free(item["buffer"])
output_number = acl.mdl.get_dataset_num_buffers(self.load_output_dataset)
for i in range(output_number):
data_buf = acl.mdl.get_dataset_buffer(self.load_output_dataset, i)
if data_buf:
ret = acl.destroy_data_buffer(data_buf)
ret = acl.mdl.destroy_dataset(self.load_output_dataset)
# 9.卸載模型,釋放模型描述信息、管理資源和pyACL去初始化。
# 卸載模型。
ret = acl.mdl.unload(self.model_id)
# 釋放模型描述信息。
if self.model_desc:
ret = acl.mdl.destroy_desc(self.model_desc)
self.model_desc = None
# 釋放Context。
if self.context:
ret = acl.rt.destroy_context(self.context)
self.context = None
# 釋放Device。
ret = acl.rt.reset_device(self.device_id)
# pyACL去初始化
ret = acl.finalize()
-
同步內存復制
# 1.申請內存。 size = 1 * 1024 * 1024 host_ptr_a, ret = acl.rt.malloc_host(size) dev_ptr_b, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY) # 2.申請內存后,可向內存中讀入數據,該自定義函數fead_file由用戶實現。 fead_file(fileName, host_ptr_a, size) # 3.同步內存復制。 #host_ptr_a表示Host上源內存地址指針,dev_ptr_b表示Device上目的內存地址指針,size表示內存大小。 # ACL_MEMCPY_HOST_TO_DEVICE = 1 ret = acl.rt.memcpy(dev_ptr_b, size, host_ptr_a, size, ACL_MEMCPY_HOST_TO_DEVICE) # 4.使用完內存中的數據后,需及時釋放資源。 ret = acl.rt.free_host(host_ptr_a) ret = acl.rt.free(dev_ptr_b)
-
異步內存復制
# 1.申請內存。 size = 1 * 1024 * 1024 # 異步內存復制要求,內存首地址64字節對齊,使用acl.rt.malloc_host 需多申請64字節。 host_ptr_a, ret = acl.rt.malloc_host(size + 64) # host申請的內存需要用戶自己64對齊處理。 host_align = host_ptr_a + 64 - host_ptr_a % 64 # acl.rt.malloc 申請的Device 側內存系統保證已經符合64對齊。 dev_ptr_b, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY) # 2.申請內存后,可向內存中讀入數據,該自定義函數fead_file由用戶實現。 fead_file(fileName, host_align, size) # 3.異步內存復制。 # host_align 表示Host上源內存地址指針,dev_ptr_b表示Device上目的內存地址指針,size表示內存大小。 # ACL_MEMCPY_HOST_TO_DEVICE = 1。 ret = acl.rt.memcpy_async(dev_ptr_b, size , host_align, size, ACL_MEMCPY_HOST_TO_DEVICE, stream) ret = acl.rt.synchronize_stream(stream) # 4.使用完內存中的數據后,需及時釋放資源。 ret = acl.rt.destroy_stream(stream) ret = acl.rt.free_host(host_ptr_a) ret = acl.rt.free(dev_ptr_b)
- 多模型推理注意:一個進程內只能調用一次acl.init和acl.finalize接口。
2)官方參考樣例
ascendcl-samples: 以CANN AscendCL接口進行開發的樣例庫。
-
ModelZoo-PyTorch/ACL_Pytorch:基于昇騰芯片的推理模型參考。
-
modelzoo-GPL/ACL_Pytorch/Yolov5_for_Pytorch:對ACL_Pytorch的YoloV3/V5/V7的補充。
-
由于slice+concat算子在Ascend AI框架下耗時比較高,所以YoloV5模型想要加速需要把slice+concat算子功能放到CPU實現。
源模型網絡:
<img src="https://upload-images.jianshu.io/upload_images/15877540-48decc4a975db971.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" style="zoom: 67%;" />
修改后網絡:
<img src="https://upload-images.jianshu.io/upload_images/15877540-dea8ed4fb091718b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" style="zoom:67%;" />
-
-
4.C&C++ 推理
1)頭文件和庫文件說明
AscendCL頭文件在“CANN軟件安裝后文件存儲路徑/include/”目錄下,AscendCL庫文件在“CANN軟件安裝后文件存儲路徑/lib64/”目錄下。
定義接口的頭文件 | 用途 | 對應的庫文件 |
---|---|---|
acl/acl_base.h | 用于定義基本的數據類型(例如aclDataBuffer、aclTensorDesc等)及其操作接口、枚舉值(例如aclFormat)、日志管理接口等。 | libascendcl.so |
acl/acl.h | 該頭文件中已包含acl/acl_mdl.h、acl/acl_rt.h、acl/acl_op.h。可以引用初始化/去初始化、Device管理、算力Group查詢與設置、Context管理、Stream管理、同步等待、內存管理、模型加載與執行、算子編譯(不包括aclopCompile接口)、算子加載與執行(不包括aclopCompileAndExecute接口)等接口。 | libascendcl.so |
acl/acl_prof.h | 用于定義Profiling配置的接口。 | libmsprofiler.so |
acl/ops/acl_cblas.h | 用于定義CBLAS接口。 | libacl_cblas.so |
acl/ops/acl_dvpp.h | 用于定義媒體數據處理V1版本的接口。 | libacl_dvpp.so |
acl/ops/acl_fv.h | 用于定義特征向量檢索的接口。昇騰310 AI處理器,當前不支持引用該頭文件中的接口。昇騰910 AI處理器,當前不支持引用該頭文件中的接口。 | libacl_retr.so |
acl/acl_op_compiler.h | 用于定義aclopCompile、aclopCompileAndExecute、aclSetCompileopt等算子在線編譯相關的接口、數據類型、枚舉值等。 | libacl_op_compiler.so |
acl/acl_tdt.h | 用于定義Tensor數據傳輸接口。昇騰310 AI處理器,當前不支持引用該頭文件中的接口。 | libacl_tdt_channel.so |
acl/acl_tdt_queue.h | 用于定義共享隊列管理、共享Buffer管理接口。預留功能,當前暫不支持引用該頭文件中的接口。 | libacl_tdt_queue.so |
acl/dvpp/hi_dvpp.h | 用于定義媒體數據處理V2版本的接口。 | libacl_dvpp_mpi.so |
2)推理過程
#include "acl/acl.h"
#include <iostream>
#include <fstream>
#include <cstring>
#include <map>
using namespace std;
size_t pictureDataSize = 0;
void *pictureHostData;
void *pictureDeviceData;
//申請內存,使用C/C++標準庫的函數將測試圖片讀入內存
void ReadPictureTotHost(const char *picturePath)
{
string fileName = picturePath;
ifstream binFile(fileName, ifstream::binary);
binFile.seekg(0, binFile.end);
pictureDataSize = binFile.tellg();
binFile.seekg(0, binFile.beg);
aclError ret = aclrtMallocHost(&pictureHostData, pictureDataSize);
binFile.read((char*)pictureHostData, pictureDataSize);
binFile.close();
}
//申請Device側的內存,再以內存復制的方式將內存中的圖片數據傳輸到Device
void CopyDataFromHostToDevice()
{
aclError ret = aclrtMalloc(&pictureDeviceData, pictureDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
ret = aclrtMemcpy(pictureDeviceData, pictureDataSize, pictureHostData, pictureDataSize, ACL_MEMCPY_HOST_TO_DEVICE);
}
int main()
{
int32_t deviceId = 0;
uint32_t modelId;
aclmdlDataset *inputDataSet;
aclDataBuffer *inputDataBuffer;
aclmdlDataset *outputDataSet;
aclDataBuffer *outputDataBuffer;
aclmdlDesc *modelDesc;
size_t outputDataSize = 0;
void *outputDeviceData;
void *outputHostData;
// 1.AscendCL初始化、運行管理資源申請(指定計算設備)
aclError ret;
ret = aclInit(nullptr);
ret = aclrtSetDevice(deviceId);
// 2.加載模型
const char *modelPath = "../model/resnet50.om";
ret = aclmdlLoadFromFile(modelPath, &modelId);
// 創建模型描述信息
modelDesc = aclmdlCreateDesc();
ret = aclmdlGetDesc(modelDesc, modelId);
// 3.將測試圖片數據讀入內存,并傳輸到Device側,用于后續推理使用
const char *picturePath = "../data/dog1_1024_683.bin";
ReadPictureTotHost(picturePath);
CopyDataFromHostToDevice();
//4.準備模型推理的輸入輸出數據結構
// 創建aclmdlDataset類型的數據,描述模型推理的輸入
inputDataSet = aclmdlCreateDataset();
inputDataBuffer = aclCreateDataBuffer(pictureDeviceData, pictureDataSize);
ret = aclmdlAddDatasetBuffer(inputDataSet, inputDataBuffer);
// 創建aclmdlDataset類型的數據,描述模型推理的輸出
outputDataSet = aclmdlCreateDataset();
// 獲取模型輸出數據需占用的內存大小,單位為Byte
outputDataSize = aclmdlGetOutputSizeByIndex(modelDesc, 0);
// 申請輸出內存
ret = aclrtMalloc(&outputDeviceData, outputDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
outputDataBuffer = aclCreateDataBuffer(outputDeviceData, outputDataSize);
ret = aclmdlAddDatasetBuffer(outputDataSet, outputDataBuffer);
// 5.執行推理
ret = aclmdlExecute(modelId, inputDataSet, outputDataSet);
// 6.獲取推理結果數據
ret = aclrtMallocHost(&outputHostData, outputDataSize);
ret = aclrtMemcpy(outputHostData, outputDataSize, outputDeviceData, outputDataSize, ACL_MEMCPY_DEVICE_TO_HOST);
// 將內存中的數據轉換為float類型
float* outFloatData = reinterpret_cast<float *>(outputHostData);
// 7.釋放模型描述信息,卸載模型
aclmdlDestroyDesc(modelDesc);
aclmdlUnload(modelId);
// 8.釋放內存、銷毀推理相關的數據類型
ret = aclrtFreeHost(pictureHostData);
pictureHostData = nullptr;
ret = aclrtFree(pictureDeviceData);
pictureDeviceData = nullptr;
aclDestroyDataBuffer(inputDataBuffer);
inputDataBuffer = nullptr;
aclmdlDestroyDataset(inputDataSet);
inputDataSet = nullptr;
ret = aclrtFreeHost(outputHostData);
outputHostData = nullptr;
ret = aclrtFree(outputDeviceData);
outputDeviceData = nullptr;
aclDestroyDataBuffer(outputDataBuffer);
outputDataBuffer = nullptr;
aclmdlDestroyDataset(outputDataSet);
outputDataSet = nullptr;
// 9.計算設備釋放,AscendCL去初始化
aclError ret = aclrtResetDevice(deviceId);
aclFinalize();
}