欢迎光临
我们一直在努力

SS928V100(Hi3403V100)----ATC模型转换工具----SVP_NNN 和 NNN 踩坑记录(LINUX版)

        由于官方SDK比较冗余且经常跨文档讲解且SDK整理的乱七八糟,对于新手来说全部看完上手成本较高,本文旨在以简短的方式介绍 CAFFE / ONNX 模型转 om 模型,并进行推理的全流程。希望能够帮助到第一次接触华为海思框架的道友们。大佬们就没必要看这种基础文章啦!

        注:本文所有操作均在 WSL (Windows 虚拟子系统)上操作的,默认 root 环境,默认开发板系统为LINUX,所有环境变量均写入 bashrc ,非虚拟机用户谨慎写入。所有用到的工具以及示例代码,均在文末。


1. 简介

        ATC 是海思芯片的模型转换工具,用于将开源框架网络模型(caffe,onnx,tensorflow)转化为 .om 格式并使用 AscendCL进行推理(因为笔者比较熟悉瑞芯微系列,分别类似于类似瑞芯微系列的RKNNToolkit工具, .rknn 模型,RKNNToolkitLite板端推理工具)。

        首先在进行下面这篇文章之前,先来了解一下 SS928V100(Hi3403V100) 这款芯片,该芯片有两颗 NPU,分别是 NNN 和SVP_NNN,其中 NNN 支持4.8Tops算力,支持 INT4/INT8/FP16;SVP_NNN 支持5.6Tops算力,支持 INT8/INT16。

简单说明:

  • NNN和SVP_NNN 进行模型转换时,用到的 ATC 工具链以及环境变量不一样
  • NNN和SVP_NNN 进行推理时,推理接口以及依赖的环境变量也不一样
  • NNN和SVP_NNN是能够并行使用的,但是测试过程中发现,如果并行使用,两颗NPU的平均算力利用率会下降10%-15%
  • 因此本文的安装内容也会分成两部分,分别是 NNN 和 SVP_NNN

    1.1 通用交叉编译工具链安装

    chmod +x Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run

    # 校验安装包是否完整, 校验成功会显示 Verifying archive integrity… 100%
    ./Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run –check

    # 安装,安装过程中有协议确认,按 Y 即可,安装成功会显示 <…> install success
    # 安装路径:root用户:“/usr/local/Ascend”,非root用户:“${HOME}/Ascend”
    ./Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run –install

    # 配置环境变量,以 root 用户为例(WSL默认sudo权限)
    source /usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/x86_64-linux/bin/setenv.bash
    vi ~/.bahsrc
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/x86_64-linux/devlib/:$LD_LIBRARY_PATH
    source ~/.bashrc

    1.2 安装openssh(有的话可跳过,没有也可以通过 NFS 共享目录解决文件传输问题)

            说实话,挺烦这种精简 linux 系统的,要啥没啥,不知道精减的意义是啥,每次都要重复这种安装编译环境的过程。

            参考,注意本文使用的交叉编译工具链的名字和文中的不一样:【MindStudio】【OpenSSH】海思SOC环境准备(linux + android)-云社区-华为云

            真是令人抓狂,海思SS928这款开发板,连adb都莫得,交叉编译好的文件甚至都没办法传到开发板上,太恶心啦!!!

            NFS 共享目录方法如下:

    # 1. 以 root 用户登录 Linux 服务器(Ubuntu 操作系统),安装 NFS 服务并配置共享目录。
    apt-get install nfs-kernel-server

    # 2. 在“/etc/exports”文件中配置共享目录
    vi /etc/exports
    # 在末尾添加 <服务器共享目录绝对路径> *(rw,sync,root_squash), 如
    /userdata/share *(rw,sync,root_squash)

    # 3. 重启 nfs 服务
    /etc/init.d/nfs-kernel-server restart

    # 4. 开发板板端挂载,mount -t nfs -o nolock,tcp NFS <服务器IP地址:服务器绝对路径path>,如

    mount -t nfs -o nolock,tcp NFS 192.168.1.2:/userdata/share

    2. NNN 引擎下的模型转换与推理

    2.1 安装CANN ToolKit(以python3.9为例)

    • 编译python3.9

            坑:各 python 必须严格按照下述版本,否则执行模型转换时会报错 :Python3.7.x(3.7.5~3.7.11)、Python3.8.x(3.8.0~3.8.11)、Python3.9.x(3.9.0~3.9.2)推荐使用Python3.9.2

    # 安装python3.9
    sudo apt update
    sudo apt install -y build-essential libssl-dev zlib1g-dev \\
    libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \\
    libncurses5-dev libncursesw5-dev xz-utils tk-dev \\
    libffi-dev libxslt1-dev liblzma-dev python3-openssl cmake Pillow git

    wget https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz
    tar -zxvf Python-3.9.2.tgz
    cd Python-3.9.2
    ./configure –prefix=/usr/local/python3.9.2 –with-ssl-default-suites=openssl –enable-shared CFLAGS=-fPIC
    make -j8
    make install
    vi ~/.bashrc
    export LD_LIBRARY_PATH=/usr/local/python3.9.2/lib:$LD_LIBRARY_PATH
    export PATH=/usr/local/python3.9.2/bin:$PATH
    source ~/.bashrc

    # 安装 cann 所需 python 环境
    # 注意,WSL默认sudo权限,此处如果用sudo,后续执行 ./Ascend-cann-toolkit_8.1.RC1_linux-x86_64.run –install 也要加sudo
    pip3 install attrs cython numpy==1.24.0 decorator sympy cffi pyyaml pathlib2 psutil protobuf==3.20 scipy requests absl-py -i https://pypi.tuna.tsinghua.edu.cn/simple

    • 在昇腾官网下载 cann 安装包, 并传到WSL中:社区版资源下载-资源下载中心-昇腾社区

            注:我用的是SDK中提供的
    Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run

    • 执行如下命令安装 chmod +x Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run

      # 校验安装包是否完整, 校验成功会显示 Verifying archive integrity… 100%
      ./Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run –check

      # 安装,安装过程中有协议确认,按 Y 即可,安装成功会显示 <…> install success
      # 安装路径:root用户:“/usr/local/Ascend”,非root用户:“${HOME}/Ascend”
      ./Ascend-cann-toolkit_5.20.t6.2.b060_linux-x86_64.run –install

      # 配置环境变量,以 root 用户为例(WSL默认sudo权限)
      source /usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/x86_64-linux/bin/setenv.bash
      vi ~/.bahsrc
      export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/x86_64-linux/devlib/:$LD_LIBRARY_PATH
      source ~/.bashrc

      安装完成后,模型转换工具 atc 在 " ${HOME}Ascend/ascend-toolkit/latest/bin " 目录下。

     2.2 caffe/onnx 转 om(以resnet50为例)

    • 转换示例:

    # 模型转换(类似RKNNToolKit),注意每次重启后都需要再次 source /usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/x86_64-linux/bin/setenv.bash
    # caffe 转 om
    atc –model=./caffe_model/resnet50.prototxt –weight=./caffe_model/resnet50.caffemodel –framework=0 –output=./model/caffe_resnet50 –soc_version=OPTG –input_fp16_nodes="data" –enable_single_stream=true
    # onnx 转 om
    atc –model=./caffe_model/resnet50_official.onnx –framework=5 –output=./model/resnet50_bs64 –input_format=NCHW –soc_version=OPTG –input_fp16_nodes="data" –enable_single_stream=true

    # sample 编译
    vi ~/.bashrc
    export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-lmixlinux200
    export NPU_HOST_LIB=/usr/local/Ascend/ascend-toolkit/latest/arm64-lmixlinux200/aarch64-linux/devlib
    source ~/.bashrc

    mkdir -p build/intermediates/soc
    cd build/intermediates/soc
    cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-mix210-linux-g++ -DCMAKE_SKIP_RPATH=TRUE
    make

    • 参数讲解:
    参数 说明

    –weight

    仅caffe模型需要,指定 .caffemodel 路径

    –framewowrk

    0:Caffe,1:MindSpore,2:TensorFlow ,5:ONNX (opset v11)
    –model

    模型文件

    –input_format

    输入数据格式 (Caffe、ONNX 默认为 NCHW;TensorFlow 默认为 NHWC)

    –enable_single_stream

    是否使能一个模型推理时只能使用一条 Stream (由于 SoC 的 Stream 资源有限,在 SoC 场景下需要用户打开此开关,SOC 广义上讲其实就是我们常用的开发板啦)

    –input_fp16_nodes 模型输入类型:

    FP32、FP16通过指定该参数设置,UINT8 需要结合 AIPP 预处理文件设置

    2.3 om 模型推理流程(类似RKNNToolKitLite)

    • 基本概念:

            Device 表示板端环境上的 NNN(Neural-Network Processing Unit),提供 NN 计算能力。

            Context 作为一个容器,管理了所有对象(包括 Stream、Event、设备内存等)的生命周期。

            Stream 用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在 Device 上执行。

    坑1:

            如果开发板没有相关的 NPU 驱动 "dev/xiaoyaozi0", 切换到 " /smp/a55_linux/mpp/out/ko " 目录下执行 " ./load_ss928v100 -a "。等等,先不要惊讶,这个 NNN 的 NPU 驱动就叫 xiaoyaozi0,哈哈哈哈,看得出来,编这个驱动的程序猿很逍遥……

    坑2:

            板端执行需设置环境变量 , {PATH} 替换成实际目录地址:

    export LD_LIBRARY_PATH={PATH}/smp/a55_linux/mpp/out/lib/npu:$LD_LIBRARY_PATH

    坑3:

            执行 NNN 相关代码时,必须手动拷贝 libcpu_kernels.so 和 libaicpu_kernels.so 到指定目录,否则将无法运行,软链接无效!!!

            mkdir -p /usr/lib64/aicpu_kernels

            mkdir -p /usr/lib64/aicpu_kernels/0/aicpu_kernels_device/

            cp /usr/lib64/npu/libcpu_kernels.so /usr/lib64/aicpu_kernels

            cp /usr/lib64/npu/libcpu_kernels.so /usr/lib64/aicpu_kernels/libaicpu_kernels.so.

            cp /usr/lib64/npu/libaicpu_kernels.so /usr/lib64/aicpu_kernels/0/aicpu_kernels_device/

            cp /usr/lib64/npu/libaicpu_kernels.so /usr/lib64/aicpu_kernels/0/aicpu_kernels_device/libaicpu_kernels.so.

            你可能会有这样一个疑问:为啥要这么样做?好麻烦的说。

            答:别问,问就是工业LJ!

    坑4(不一定每家开发板都有):

            板端环境要注意,/usr/lib64/npu/libascend_protobuf有两个

            /usr/lib64/npu/libascend_protobuf.so

            /usr/lib64/npu/libascend_protobuf.so.3.13.0.0

            其中 /usr/lib64/npu/libascend_protobuf.so.3.13.0.0 用的是新版 C++ ABI,包含符号 cxx11,运行可执行程序时会出错,因为开发板自带的libstdc++ 不包含 cxx11

    •  板端推理代码示例:

    #include "acl/acl.h"
    #include <iostream>
    #include <fstream>
    #include <cstring>
    #include <map>
    #include <math.h>

    using namespace std;
    int32_t deviceId = 0;
    uint32_t modelId;
    size_t pictureDataSize = 0;
    void *pictureHostData;
    void *pictureDeviceData;
    aclmdlDataset *inputDataSet;
    aclDataBuffer *inputDataBuffer;
    aclmdlDataset *outputDataSet;
    aclDataBuffer *outputDataBuffer;
    aclmdlDesc *modelDesc;
    size_t outputDataSize = 0;
    void *outputDeviceData;
    void *outputHostData;

    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();
    }

    int main()
    {
    printf("==== 这是测试代码123 ==== \\n");
    // ===== step1 : 初始化 acl =====
    aclError ret = aclInit(nullptr);
    if (ret != ACL_SUCCESS) cerr << "aclInit failed with ret: " << ret << "\\n" << endl;

    ret = aclrtSetDevice(deviceId); // 默认创建了 context 和 stream
    if (ret != ACL_SUCCESS) cerr << "aclrtSetDevice failed with ret: " << ret << "\\n" << endl;

    // ===== step2 : 加载模型 =====
    const char *modelPath = "../model/resnet50.om";
    ret = aclmdlLoadFromFile(modelPath, &modelId);
    if (ret != ACL_SUCCESS) cerr << "aclmdlLoadFromFile failed with ret: " << ret << "\\n" << endl;

    // ===== setp3 : 加载 bin 类型的图片 =====
    const char *picturePath = "../data/dog1_1024_683.bin";
    ReadPictureTotHost(picturePath);
    ret = aclrtMalloc(&pictureDeviceData, pictureDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
    if (ret != ACL_SUCCESS) cerr << "aclrtMalloc failed with ret: " << ret << "\\n" << endl;

    ret = aclrtMemcpy(pictureDeviceData, pictureDataSize, pictureHostData, pictureDataSize, ACL_MEMCPY_HOST_TO_DEVICE);
    if (ret != ACL_SUCCESS) cerr << "aclrtInputMemcpy failed with ret: " << ret << "\\n" << endl;

    // ===== step4 :执行推理 =====
    // === step4.1 : 创建aclmdlDataset类型的数据,描述模型推理的输入 ===
    inputDataSet = aclmdlCreateDataset();
    inputDataBuffer = aclCreateDataBuffer(pictureDeviceData, pictureDataSize);
    ret = aclmdlAddDatasetBuffer(inputDataSet, inputDataBuffer);
    if (ret != ACL_SUCCESS) cerr << "aclmdlAddDatasetBuffer failed with ret: " << ret << "\\n" << endl;

    // === step4.2 : 创建aclmdlDataset类型的数据,描述模型推理的输出 ===
    // 创建模型描述信息
    modelDesc = aclmdlCreateDesc();
    ret = aclmdlGetDesc(modelDesc, modelId);
    if (ret != ACL_SUCCESS) cerr << "aclmdlGetDesc failed with ret: " << ret << "\\n" << endl;

    outputDataSet = aclmdlCreateDataset();
    outputDataSize = aclmdlGetOutputSizeByIndex(modelDesc, 0);
    // 申请输出内存
    ret = aclrtMalloc(&outputDeviceData, outputDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
    if (ret != ACL_SUCCESS) cerr << "aclrtMalloc failed with ret: " << ret << "\\n" << endl;

    outputDataBuffer = aclCreateDataBuffer(outputDeviceData, outputDataSize);
    ret = aclmdlAddDatasetBuffer(outputDataSet, outputDataBuffer);
    if (ret != ACL_SUCCESS) cerr << "aclmdlAddDatasetBuffer failed with ret: " << ret << "\\n" << endl;

    // === step 4.3 : 推理 ===
    ret = aclmdlExecute(modelId, inputDataSet, outputDataSet);
    if (ret != ACL_SUCCESS) cerr << "aclmdlExecute failed with ret: " << ret << "\\n" << endl;

    // ===== step5:获取推理结果数据 =====
    // === step5.1 : copy 推理结果到 outputHostData
    ret = aclrtMallocHost(&outputHostData, outputDataSize);
    if (ret != ACL_SUCCESS) cerr << "aclrtMallocHost failed with ret: " << ret << "\\n" << endl;

    ret = aclrtMemcpy(outputHostData, outputDataSize, outputDeviceData, outputDataSize, ACL_MEMCPY_DEVICE_TO_HOST);
    if (ret != ACL_SUCCESS) cerr << "aclrtOutputMemcpy failed with ret: " << ret << "\\n" << endl;

    // === step5.2 :后处理部分
    float* outFloatData = reinterpret_cast<float *>(outputHostData);
    // 屏显测试图片的top5置信度的类别编号
    map<float, unsigned int, greater<float>> resultMap;
    for (unsigned int j = 0; j < outputDataSize / sizeof(float); ++j)
    {
    resultMap[*outFloatData] = j;
    outFloatData++;
    }
    double totalValue=0.0;
    for (auto it = resultMap.begin(); it != resultMap.end(); ++it)
    {
    totalValue += exp(it->first);
    }
    int cnt = 0;
    for (auto it = resultMap.begin();it != resultMap.end();++it)
    {
    if(++cnt > 5) break;
    printf("top %d: index[%d] value[%lf] \\n", cnt, it->second, it->first);
    }

    // ===== step6 : 释放资源 =====
    // === 6.1 释放模型描述信息并卸载模型 ===
    aclmdlDestroyDesc(modelDesc);
    aclmdlUnload(modelId);

    // === 6.2 释放加载的测试图片 ===
    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;

    // === 6.3 释放计算资源 ===
    ret = aclrtResetDevice(deviceId);
    aclFinalize();
    }

    3. SVP_NNN 引擎下的模型转换与推理

    3.1 安装 CANN ToolKit(以python3.9为例)

            注意,此处用的SDK是"Ascend-cann-toolkit_6.10.t01spc030b270_linux.x86_64.run",写到这里,不得不吐槽一下,我不知道是我拿到手的SDK有问题,还是整理这个SDK的人有问题,喵的,整个SDK没有一篇文档有说过 SVP_NNN 和 NNN 用的ATC工具不是同一个。也没有一篇文档讲了 SVP_NNN 的 ATC 工具进行转换时参数应该怎么写……

            不过好在,安装过程和 NNN 的 ATC 工具差别不大,只需要注意环境变量即可

    chmod +x Ascend-cann-toolkit_6.10.t01spc030b270_linux.x86_64.run
    ./Ascend-cann-toolkit_6.10.t01spc030b270_linux.x86_64.run –install

    # install 成功后,终端会打印如下 export 环境变量信息
    vi ~/.bashrc
    export DDK_PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/x86_64-linux
    export NPU_HOST_LIB=/usr/local/Ascend/ascend-toolkit/svp_latest/x86_64-linux/acllib/lib64/stub
    export PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/toolkit/bin:$PATH
    export PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/atc/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/toolkit/tools/sim/lib:$LD_LIBRARY_PATH
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/atc/lib64:$LD_LIBRARY_PATH
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/svp_latest/atc/third_party_lib:$LD_LIBRARY_PATH
    source ~/.bashrc

    3.2 caffe 转 om

            我个人觉得 SVP_NNN 的 ATC 比较好用,可能因为 SVP_NNN 只支持 INT8/INT16 ,所以就量化而言,要比 NNN 下使用 AMCT 工具来的轻松友好的多,转换示例:

    atc \\
    –weight="./caffe_model/resnet50.caffemodel" \\
    –model="./caffe_model/resnet50.prototxt" \\
    –framework=0 \\
    –log_level=0 \\
    –dump_data=0 \\
    –online_model_type=0 \\
    –batch_num=256 \\
    –input_shape="data:1,3,224,224" \\
    –input_type="data:UINT8" \\
    –input_format=NCHW \\
    –output="./model/resnet50" \\
    –soc_version=SS928V100 \\
    –insert_op_conf=./insert_op.cfg \\
    –compile_mode=0 \\
    –save_original_model=false \\
    –image_list="data:./data/image_ref_list.txt"

            具体参数信息,安装完 ATC 环境后,可通过 atc –hlep 查看,以下仅对常用基础参数进行说明:

    参数 说明

    –batch_num

    批处理层的批次数,[0, 256],默认值为 256

    –compile_mode

    量化数据类型,0:低精度(8位量化),1:高精度(16位量化)

    –framework

    输入模型的框架,0:caffe,5:onnx,默认 0

    –image_list

    量化校准使用的图像列表文件

    –input_shape

    输入数据的形状

    –input_format

    输入数据的格式,{NCHW},默认:NCHW

    –input_type

    支持的输入数据类型:{FP16, FP32, INT16, INT8, S16, S8, U16, U8, UINT16, UINT8},默认 FP32

    –insert_op_conf

    AIPP 配置文件路径

    –model

    输入模型文件路径

    –weight

    权重文件路径

    –output

    输出 om 路径及文件名

    –output_type

    支持的输出数据类型:{FP16, FP32, INT16, INT8, S16, S8, U16, U8, UINT16, UINT8},默认 FP32

    –soc_version

    SoC 版本,{SS626V100, SS928V100},默认 SS626V100(注意,次数和 NNN 下的 ATC 有一定区别,不支持 OPTG)

    –save_original_model

    是否保存原始模型,默认 false

    3.3 om 推理流程

    坑1:

            如果开发板没有相关的 NPU 驱动 "dev/svp_npu",切换到 " /smp/a55_linux/mpp/out/ko " 目录下,修改 " ./load_ss928v100" 这个可执行程序,搜索加载 " pqp.ko "的代码,然后将其注释掉,然后关闭注释或添加如下内容:"insmod svp_npu/ot_svp_npu.ko svp_npu_save_power=1 svp_npu_max_task_node_num=512", 因为 "ot_svp_npu.ko" 和 "pqp.ko" 不能同时加载

    坑2:

            板端执行需设置环境变量,{PATH} 替换成实际目录地址 :

    export LD_LIBRARY_PATH={PATH}/smp/a55_linux/mpp/out/lib/svp_npu:$LD_LIBRARY_PATH

            SVP_NNN 下的推理流程和 NNN 类似,区别在于引用的头文件名称以及接口都添加了 svp 的前缀,且接口风格由驼峰变成了下划线分割,下列代码仅贴出和 NNN 不同的代码段以供理解,完整代码见文末: 

    #include "acl/svp_acl.h"

    # 1. 初始化 svp_acl
    svp_acl_error ret = svp_acl_init(aclConfigPath);
    svp_acl_error ret = svp_acl_rt_set_device(deviceId_);
    # 2. 加载模型
    svp_acl_error ret = svp_acl_mdl_load_from_mem(static_cast<uint8_t* >(modelMemPtr_), modelMemSize_, &modelId_);
    # 3. 创建模型描述信息
    modelDesc_ = svp_acl_mdl_create_desc();
    svp_acl_error ret = svp_acl_mdl_get_desc(modelDesc_, modelId_);

    # 4. 创建输入
    Result ret = GetInputStrideParam(0, devSize, stride, inputDims);
    size_t dataSize = GetInputDataSize(0);
    void *picDevBuffer = Utils::GetDeviceBufferOfFile(filePath, inputDims, stride, dataSize);
    Result ret = InitInput();
    Result ret = CreateInput(picDevBuffer, devSize, stride);

    # 4. 创建输出
    output_ = svp_acl_mdl_create_dataset();
    size_t outputSize = svp_acl_mdl_get_num_outputs(modelDesc_);

    # 5. 执行推理
    svp_acl_error ret = svp_acl_mdl_execute(modelId_, input_, output_);

    4. 其他

    4.1 om 模型信息查看

            通过 netron 可以直接查看NNN ATC 工具转换的模型信息(SVP_NNN ATC 工具转换的 om 模型无法直接使用 netron 查看),或者执行如下命令,将 .om 模型转化为 json 文件查看模型信息:

    atc –mode=1 –om={oem_model_path.oem} –json={oem_json_path.json}

    4.2 查看 NPU 利用率

            看整体的NPU资源占用,分两个核看

    # SVP_NNN, 执行命令后查看 hw_utilization
    watch -n 1 cat /proc/umap/svp_npu

    # NNN, 执行命令后查看 utilizaiton rate
    watch -n 1 cat /proc/umap/tsfw的utilizaiton rate

    4.3 源码传送门

    SS928V100_NNN&SVP_NNN_TOOLS 提取码: 2jdc

    赞(0)
    未经允许不得转载:171主机测评 » SS928V100(Hi3403V100)----ATC模型转换工具----SVP_NNN 和 NNN 踩坑记录(LINUX版)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址