资讯 社区 文档 控制台
技术能力
语音技术
文字识别
人脸与人体
图像技术
语言与知识
视频技术
AR与VR
数据智能
场景方案
部署方案
行业应用
智能教育
智能医疗
智能零售
智能工业
企业服务
智能政务
信息服务
智能园区

EasyEdge平台Linux系统SDK开发文档-C++

简介

本文档介绍EasyEdge的Linux CPP SDK的使用方法。

  • 网络类型支持:图像分类,物体检测,图像分割
  • 硬件支持:

    • NVIDIA GPU: - x86_64 Desktop/Server - aarch64 Jetson
    • CPU: - x86_64 - aarch64 armv7hf
    • ASIC: - Hisilicon NNIE1.1 on aarch64(Hi3559AV100/Hi3559CV100等) - Hisilicon NNIE1.2 on armv7l(Hi3519AV100/Hi3559V200等) - Intel Movidius MyRIAD2 / MyRIAD X on x86_64 - Intel Movidius MyRIAD2 / MyRIAD X on armv7l(树莓派3b+) - Intel Movidius MyRIAD2 / MyRIAD X on aarch64 - 比特大陆 Bitmain SE50 (BM1684)
  • 操作系统支持: * Linux

Release Notes

时间 版本 说明
2021.10.20 1.3.4 适用英特尔至强、酷睿、凌动处理器推理引擎优化升级
2021.06.29 1.3.1 视频流解析支持分辨率调整;GPU SDK支持分类模型的batch预测;预测引擎升级
2021.05.13 1.3.0 新增视频流接入支持
2021.01.27 1.1.0 新增支持Jetson系列、瑞芯微NPU、通用ARM GPU、骁龙GPU等的端计算组件的生成;
新增ONNX作为输入框架的支持;
新增对PaddlePaddle分散格式的模型的支持;
新增一系列模型的支持;
性能优化
2020.12.18 1.0.0 性能优化;接口优化升级;intel神经计算棒、CPU加速版推理引擎升级
2020.09.17 0.5.6 支持linux aarch64架构的硬件接入intel神经计算棒预测;支持比特大陆计算盒SE50 BM1684
2020.08.11 0.5.5 提升预测速度。支持百度昆仑芯片
2020.05.15 0.5.3 优化性能,支持专业版更多模型
2020.04.16 0.5.2 支持CPU加速版;CPU基础版引擎升级;GPU加速版支持多卡多线程
2020.03.12 0.5.0 x86引擎升级;更新本地http服务接口;GPU加速版提速,支持批量图片推理
2020.01.16 0.4.7 ARM引擎升级;增加推荐阈值支持
2019.12.26 0.4.6 支持海思NNIE
2019.11.02 0.4.5 移除curl依赖;支持自动编译OpenCV;支持EasyDL 专业版 Yolov3; 支持EasyDL经典版高精度物体检测模型升级
2019.10.25 0.4.4 ARM引擎升级,性能提升30%; 支持EasyDL专业版模型
2019.09.23 0.4.3 增加海思NNIE加速芯片支持
2019.08.30 0.4.2 ARM引擎升级;支持分类高性能与高精度模型
2019.07.25 0.4.1 引擎升级,性能提升
2019.07.25 0.4.0 支持Xeye, 细节完善
2019.06.11 0.3.3 paddle引擎升级;性能提升
2019.05.16 0.3.2 新增NVIDIA GPU支持;新增armv7l支持
2019.04.25 0.3.1 优化硬件支持
2019.03.29 0.3.0 ARM64 支持;效果提升
2019.02.20 0.2.1 paddle引擎支持;效果提升
2018.11.30 0.1.0 第一版!

2020-12-18: 【接口升级】 参数配置接口从1.0.0版本开始已升级为新接口,以前的方式被置为deprecated,并将在未来的版本中移除。请尽快考虑升级为新的接口方式,具体使用方式可以参考下文介绍以及demo工程示例,谢谢。

快速开始

SDK在以下环境中测试通过

  • x86_64, Ubuntu 16.04, gcc 5.4
  • x86_64, Ubuntu 18.04, gcc 7.4
  • Tesla P4, Ubuntu 16.04, cuda 9.0, cudnn 7.5
  • x86_64, Ubuntu 16.04, gcc 5.4, XTCL 1.0.0.187
  • aarch64(arm64), Ubuntu 16.04, gcc 5.3 (RK3399)
  • Hi3559AV100, aarch64, Ubuntu 16.04, gcc 5.3
  • Hi3519AV100, armv7l , HiLinux 4.9.37, (Hi3519AV100R001C02SPC020)
  • armv7hf, Raspbian, (Raspberry 3b)
  • aarch64, Raspbian, (Raspberry 4b)
  • armv7l, Raspbian, (Raspberry 3b+)
  • Bitmain se50 BM1684, Debian 9

依赖包括

  • cmake 3+
  • gcc 5.4 (需包含 GLIBCXX_3.4.22)
  • opencv3.4 (可选)
  • cuda9.0_cudnn7 (使用NVIDIA-GPU时必须)

说明1:

海思开发板需要根据海思SDK文档配置开运行环境和编译环境,SDK和opencv都需要在该编译环境中编译。 NNIE1.2用arm-himix200-linux交叉编译好的opencv下载链接:https://pan.baidu.com/s/13QW0ReeWx4ZwgYg4lretyw 密码:yq0s。下载后修改SDK CMakesList.txt

说明2:

树莓派Raspberry默认为armv7hf系统(可通过uname -a查看),使用SDK包中名称中包含armv7hf_ARM_的tar包。如果是aarch64系统,使用SDK包中名称中包含aarch64_ARM_的tar包。

1. 安装依赖

以下步骤均可选,请开发者根据实际运行环境选择安装。

(可选) 安装cuda&cudnn

在NVIDIA GPU上运行必须(包括GPU基础版,GPU加速版)

默认依赖的版本为cuda9.0, cudnn7。

对于GPU基础版,若开发者需求不同的依赖版本,请在PaddlePaddle官网 下载对应版本的libpaddle_fluid.so或参考其文档进行编译,覆盖lib文件夹下的相关库文件。

(可选)安装BMNNSDK

对于硬件使用为比特大陆SE计算盒的,需要安装BMNNSDK2.2,并在CMakeList.txt中指定SDK安装地址:

# 这里修改并填入所使用的bmnnsdk路径
set(EDGE_BMSDK_ROOT "{这里填写sdk路径}")

2. 使用序列号激活

在控制台获取的序列号请通过参数配置结构体EdgePredictorConfig的成员函数set_config(easyedge::params::PREDICTOR_KEY_SERIAL_NUM, "this-is-serial-num")设置。

具体请参考SDK自带的Demo.cpp文件的使用方法。

3. 测试Demo

模型资源文件默认已经打包在开发者下载的SDK包中。Demo工程直接编译即可运行。

请先将tar包整体拷贝到具体运行的设备中,再解压缩编译 对于硬件使用为: -Intel Movidius MyRIAD2 / MyRIAD X on Linux x86_64 / armv7hf / aarch64英特尔至强、酷睿、凌动处理器的,在编译或运行demo程序前执行以下命令: source ${cpp_kit位置路径}/thirdparty/openvino/bin/setupvars.sh

请在官网获取序列号,填写在demo.cpp

编译运行:

cd src
mkdir build && cd build
cmake .. && make
./easyedge_image_inference {模型RES文件夹}  {测试图片路径}
# 如果是NNIE引擎,使用sudo运行
sudo ./easyedge_image_inference {模型RES文件夹}  {测试图片路径}

如果希望SDK自动编译安装所需要的OpenCV库,修改cmake的optionEDGE_BUILD_OPENCVON即可。 SDK会自动从网络下载opencv源码,并编译需要的module、链接。注意,此功能必须需联网。

cmake -DEDGE_BUILD_OPENCV=ON

若需自定义library search path或者gcc路径,修改CMakeList.txt即可。

对于硬件使用为Intel Movidius MyRIAD2 / MyRIAD X on Linux aarch64的,如果要使用Intel Movidius MyRIAD X(比如英特尔2代神经计算棒),openvino预测引擎要找到设备需要执行以下命令:

cp ${CPP_SDK_DIR}/openvino/97-myriad-usbboot.rules  /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo ldconfig

demo运行效果:

 > ./easyedge_image_inference ../../../../RES 2.jpeg
2019-02-13 16:46:12,659 INFO [EasyEdge] [easyedge.cpp:34] 140606189016192 Baidu EasyEdge Linux Development Kit 0.2.1(20190213)
2019-02-13 16:46:14,083 INFO [EasyEdge] [paddlev2_edge_predictor.cpp:60] 140606189016192 Allocate graph success.
2019-02-13 16:46:14,326 DEBUG [EasyEdge] [paddlev2_edge_predictor.cpp:143] 140606189016192 Inference costs 168 ms
1, 1:txt_frame, p:0.994905 loc: 0.168161, 0.153654, 0.920856, 0.779621
Done

4. 测试Demo HTTP 服务

编译demo完成之后,会同时生成一个http服务 运行

# ./easyedge_serving {res_dir} {serial_key} {host, default 0.0.0.0} {port, default 24401}
 ./easyedge_serving ../../../RES "1111-1111-1111-1111" 0.0.0.0  24401

后,日志中会显示

HTTP is now serving at 0.0.0.0:24401

字样,此时,开发者可以打开浏览器,http://{设备ip}:24401,选择图片来进行测试。

同时,可以调用HTTP接口来访问服务,具体参考下文接口说明。

使用说明

使用该方式,将运行库嵌入到开发者的程序当中。

使用流程

请优先参考Demo的使用流程。遇到错误,请优先参考文件中的注释解释,以及日志说明。

    // step 1: 配置模型资源目录
    EdgePredictorConfig config;
    config.model_dir = {模型文件目录};

    // step 2: 创建并初始化Predictor;这这里选择合适的引擎
    auto predictor = global_controller()->CreateEdgePredictor(config);

    // step 3: 预测图像
    auto img = cv::imread({图片路径});
    std::vector<EdgeResultData> results;
    predictor->infer(img, results);

	// step 3-2: 预测视频
	std::vector<EdgeResultData> results;
	FrameTensor frame_tensor;
    VideoConfig video_config;
    video_config.source_type = static_cast<SourceType>(video_type);  // source_type 定义参考头文件 easyedge_video.h
    video_config.source_value = video_src;
    /*
    ... more video_configs, 根据需要配置video_config的各选项
    */
    auto video_decoding = CreateVideoDecoding(video_config);
    while (video_decoding->next(frame_tensor) == EDGE_OK) {
        results.clear();
        if (frame_tensor.is_needed) {
            predictor->infer(frame_tensor.frame, results);
            render(frame_tensor.frame, results, predictor->model_info().kind);
        }
        //video_decoding->display(frame_tensor); // 显示当前frame,需在video_config中开启配置
        //video_decoding->save(frame_tensor); // 存储当前frame到视频,需在video_config中开启配置
    }

运行参数配置

运行参数的配置通过结构体EdgePredictorConfig完成。

struct EdgePredictorConfig {
    /**
     * @brief 模型资源文件夹路径
     */
    std::string model_dir;

    std::map<std::string, std::string> conf;

    EdgePredictorConfig();

    template<typename T>
    T get_config(const std::string &key, const T &default_value);

    template<typename T = std::string>
    T get_config(const std::string &key);

    template<typename T>
    const T *get_config(const std::string &key, const T *default_value);

    template<typename T>
    void set_config(const std::string &key, const T &value);

    template<typename T>
    void set_config(const std::string &key, const T *value);

    static EdgePredictorConfig default_config();
};

运行参数选项的配置以keyvalue的方式存储在类型为std::mapconf中,并且键值对的设置和获取可以通过EdgePredictorConfigset_configget_config函数完成。同时部分参数也支持以环境变量的方式设置键值对。 EdgePredictorConfig的具体使用方法可以参考开发工具包中的demo工程。

初始化

  • 接口
auto predictor = global_controller()->CreateEdgePredictor(config);
predictor->init();

若返回非0,请查看输出日志排查错误原因。

预测图像

  • 接口
 /**
  * @brief
  * 通用接口
  * @param image: must be BGR , HWC format (opencv default)
  * @param result
  * @return
  */
 virtual int infer(
         cv::Mat& image, std::vector<EdgeResultData>& result
 ) = 0;

 /**
  * @brief
  * GPU加速版批量图片推理接口
  * @param image: must be BGR , HWC format (opencv default)
  * @param result
  * @return
  */
 virtual int infer(
         std::vector<cv::Mat>& image, std::vector<std::vector<EdgeResultData>>& result
 ) = 0;

图片的格式务必为opencv默认的BGR, HWC格式。

  • 返回格式

EdgeResultData中可以获取对应的分类信息、位置信息。

struct EdgeResultData {
    int index;  // 分类结果的index
    std::string label;  // 分类结果的label
    float prob;  // 置信度

    // 物体检测活图像分割时才有
    float x1, y1, x2, y2;  // (x1, y1): 左上角, (x2, y2): 右下角; 均为0~1的长宽比例值。

    // 图像分割时才有
    cv::Mat mask;  // 0, 1 的mask
    std::string mask_rle;  // Run Length Encoding,游程编码的mask
};

关于矩形坐标

x1 * 图片宽度 = 检测框的左上角的横坐标

y1 * 图片高度 = 检测框的左上角的纵坐标

x2 * 图片宽度 = 检测框的右下角的横坐标

y2 * 图片高度 = 检测框的右下角的纵坐标

关于图像分割mask

cv::Mat mask为图像掩码的二维数组
{
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
  {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
}
其中1代表为目标区域,0代表非目标区域

关于图像分割mask_rle

该字段返回了mask的游程编码,解析方式可参考 http demo

以上字段可以参考demo文件中使用opencv绘制的逻辑进行解析

预测视频

SDK 提供了支持摄像头读取、视频文件和网络视频流的解析工具类VideoDecoding,此类提供了获取视频帧数据的便利函数。通过VideoConfig结构体可以控制视频/摄像头的解析策略、抽帧策略、分辨率调整、结果视频存储等功能。对于抽取到的视频帧可以直接作为SDK infer 接口的参数进行预测。

  • 接口

classVideoDecoding

    /**
     * @brief 获取输入源的下一帧
     * @param frame_tensor
     * @return
     */
    virtual int next(FrameTensor &frame_tensor) = 0;

    /**
     * @brief 显示当前frame_tensor中的视频帧
     * @param frame_tensor
     * @return
     */
    virtual int display(const FrameTensor &frame_tensor) = 0;

    /**
     * @brief 将当前frame_tensor中的视频帧写为本地视频文件
     * @param frame_tensor
     * @return
     */
    virtual int save(FrameTensor &frame_tensor) = 0;

    /**
     * @brief 获取视频的fps属性
     * @return
     */
    virtual int get_fps() = 0;
     /**
      * @brief 获取视频的width属性
      * @return
      */
    virtual int get_width() = 0;

    /**
     * @brief 获取视频的height属性
     * @return
     */
    virtual int get_height() = 0;

struct VideoConfig

/**
 * @brief 视频源、抽帧策略、存储策略的设置选项
 */
struct VideoConfig {
    SourceType source_type;            // 输入源类型
    std::string source_value;          // 输入源地址,如视频文件路径、摄像头index、网络流地址
    int skip_frames{0};                // 设置跳帧,每隔skip_frames帧抽取一帧,并把该抽取帧的is_needed置为true
    int retrieve_all{false};           // 是否抽取所有frame以便于作为显示和存储,对于不满足skip_frames策略的frame,把所抽取帧的is_needed置为false
    int input_fps{0};                  // 在采取抽帧之前设置视频的fps
    Resolution resolution{Resolution::kAuto}; // 采样分辨率,只对camera有效

    bool enable_display{false};
    std::string window_name{"EasyEdge"};
    bool display_all{false};           // 是否显示所有frame,若为false,仅显示根据skip_frames抽取的frame

    bool enable_save{false};
    std::string save_path;             // frame存储为视频文件的路径
    bool save_all{false};              // 是否存储所有frame,若为false,仅存储根据skip_frames抽取的frame

    std::map::string, std::string> conf;
};

source_type:输入源类型,支持视频文件、摄像头、网络视频流三种,值分别为1、2、3。 source_value: 若source_type为视频文件,该值为指向视频文件的完整路径;若source_type为摄像头,该值为摄像头的index,如对于/dev/video0的摄像头,则index为0;若source_type为网络视频流,则为该视频流的完整地址。 skip_frames:设置跳帧,每隔skip_frames帧抽取一帧,并把该抽取帧的is_needed置为true,标记为is_needed的帧是用来做预测的帧。反之,直接跳过该帧,不经过预测。 retrieve_all:若置该项为true,则无论是否设置跳帧,所有的帧都会被抽取返回,以作为显示或存储用。 input_fps:用于抽帧前设置fps。 resolution:设置摄像头采样的分辨率,其值请参考easyedge_video.h中的定义,注意该分辨率调整仅对输入源为摄像头时有效。 conf:高级选项。部分配置会通过该map来设置。

注意:

  1. 如果使用VideoConfigdisplay功能,需要自行编译带有GTK选项的opencv,默认打包的opencv不包含此项。
  2. 使用摄像头抽帧时,如果通过resolution设置了分辨率调整,但是不起作用,请添加如下选项:
video_config.conf["backend"] = "2";

3.部分设备上的CSI摄像头尚未兼容,如遇到问题,可以通过工单、QQ交流群或微信交流群反馈。

具体接口调用流程,可以参考SDK中的demo_video_inference

设置序列号

请在网页控制台中申请序列号,并在init初始化前设置。 LinuxSDK 首次使用需联网授权。

EdgePredictorConfig config;
config.set_config(easyedge::params::PREDICTOR_KEY_SERIAL_NUM, "this-is-serial-num");

日志配置

设置 EdgeLogConfig 的相关参数。具体含义参考文件中的注释说明。

EdgeLogConfig log_config;
log_config.enable_debug = true;
global_controller()->set_log_config(log_config);

http服务

1. 开启http服务

http服务的启动可以参考demo_serving.cpp文件。

 /**
     * @brief 开启一个简单的demo http服务。
     * 该方法会block直到收到sigint/sigterm。
     * http服务里,图片的解码运行在cpu之上,可能会降低推理速度。
     * @tparam ConfigT
     * @param config
     * @param host
     * @param port
     * @param service_id service_id  user parameter, uri '/get/service_id' will respond this value with 'text/plain'
     * @param instance_num 实例数量,根据内存/显存/时延要求调整
     * @return
     */
    template<typename ConfigT>
    int start_http_server(
            const ConfigT &config,
            const std::string &host,
            int port,
            const std::string &service_id,
            int instance_num = 1);

2. 请求http服务

开发者可以打开浏览器,http://{设备ip}:24401,选择图片来进行测试。

URL中的get参数:

参数 说明 默认值
threshold 阈值过滤, 0~1 如不提供,则会使用模型的推荐阈值

HTTP POST Body即为图片的二进制内容(无需base64, 无需json)

Python请求示例

import requests

with open('./1.jpg', 'rb') as f:
    img = f.read()
    result = requests.post(
	    'http://127.0.0.1:24401/',
	    params={'threshold': 0.1},
	    data=img).json()

Java请求示例

http 返回数据

字段 类型说明 其他
error_code Number 0为成功,非0参考message获得具体错误信息
results Array 内容为具体的识别结果。其中字段的具体含义请参考预测图像-返回格式一节
cost_ms Number 预测耗时ms,不含网络交互时间

返回示例

{
    "cost_ms": 52,
    "error_code": 0,
    "results": [
        {
            "confidence": 0.94482421875,
            "index": 1,
            "label": "IronMan",
            "x1": 0.059185408055782318,
            "x2": 0.18795496225357056,
            "y1": 0.14762254059314728,
            "y2": 0.52510076761245728
        },
        {
            "confidence": 0.94091796875,
            "index": 1,
            "label": "IronMan",
            "x1": 0.79151463508605957,
            "x2": 0.92310667037963867,
            "y1": 0.045728668570518494,
            "y2": 0.42920106649398804
        }
      ]
}

其他配置

1. 日志名称、HTTP 网页标题设置

通过global_controller的set_config方法设置:

global_controller()->set_config(easyedge::params::KEY_LOG_BRAND, "MY_BRAND");

效果如下: 图片

2. CPU线程数设置

CPU加速版通过 EdgePredictorConfig::set_config配置

EdgePredictorConfig config;
config.set_config(easyedge::params::KEY_CPU_THREADS_NUM, 4);

CPU 普通版通过PaddleFluidConfig::thread_num配置

GPU 加速版

预测接口

GPU 加速版 SDK 除了支持上面介绍的通用接口外,还支持图片的批量预测,预测接口如下:

 /**
  * @brief
  * GPU加速版批量图片推理接口
  * @param image: must be BGR , HWC format (opencv default)
  * @param result
  * @return
  */
 virtual int infer(
         std::vector<cv::Mat>& image,
         std::vector<std::vector<EdgeResultData>>& result
 ) = 0;

/**
  * @brief
  * GPU加速版批量图片推理接口,带阈值
  * @related infer(cv::Mat & image, EdgeColorFormat origin_color_format, std::vector<EdgeResultData> &result, float threshold)
  */
virtual int infer(
            std::vector<cv::Mat> &images,
            EdgeColorFormat origin_color_format,
            std::vector<std::vector<EdgeResultData>> &results,
            float threshold
) = 0;

批量图片的预测接口的使用要求在调用 init 接口的时候设置一个有效的 max_batch_size,其含义见下方参数配置接口的介绍。

运行参数选项

在上面的内容中我们介绍了如何使用EdgePredictorConfig进行运行参数的配置。针对GPU加速版开发工具包,目前EdgePredictorConfig的运行参数所支持的Key包括如下项:

/**
 * @brief 当有同类型的多个设备的时候,使用哪一个设备,如:
 * GPU: 使用哪张GPU卡
 * EdgeBoard(VMX),Movidius NCS :使用哪一张加速卡
 * 值类型:int
 * 默认值:0
 */
static constexpr auto PREDICTOR_KEY_DEVICE_ID = "PREDICTOR_KEY_DEVICE_ID";

/**
 * @brief 生成最大 batch_size 为 max_batch_size 的优化模型,单次预测图片数量可以小于或等于此值
 * 值类型: int
 * 默认值:4
 */
static constexpr auto PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE = "PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE";

/**
 * @brief 设置device对应的GPU卡可以支持的最大并发量
 * 实际预测的时候对应GPU卡的最大并发量不超过这里设置的范围,否则预测请求会排队等待预测执行
 * 值类型: int
 * 默认值:1
 */
static constexpr auto PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY = "PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY";

/**
 * @brief 是否开启fp16模式预测,开启后预测速度会更快,但精度会略有降低。并且需要硬件支持fp16
 * 值类型: bool
 * 默认值:false
 */
static constexpr auto PREDICTOR_KEY_GTURBO_FP16 = "PREDICTOR_KEY_GTURBO_FP16";

/**
 * @brief 模型编译等级
 * 1:如果当前max_batch_size与历史编译产出的max_batch_size不相等时,则重新编译模型(推荐)
 * 2:无论历史编译产出的max_batch_size为多少,均根据当前max_batch_size重新编译模型
 * 值类型: int
 * 默认值:1
 */
static constexpr auto PREDICTOR_KEY_GTURBO_COMPILE_LEVEL = "PREDICTOR_KEY_GTURBO_COMPILE_LEVEL";

/**
 * @brief GPU工作空间大小设置
 * workspace_size = workspace_prefix * (1 << workspace_offset)
 * workspace_offset: 10 = KB, 20 = MB, 30 = GB
 * 值类型: int
 * 默认值:WORKSPACE_PREFIX: 100, WORKSPACE_OFFSET: 20,即100MB
 */
static constexpr auto PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIX = "PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIX";
static constexpr auto PREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET = "PREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET";

/**
 * @brief 需要使用的dla core
 * 值类型: int
 * 默认值:-1(不使用)
 */
static constexpr auto PREDICTOR_KEY_GTURBO_DLA_CORE = "PREDICTOR_KEY_GTURBO_DLA_CORE";

/**
 * @brief 自定义缓存文件命名,默认即可
 * 值类型: string
 * 默认值: 根据配置自动生成
 */
static constexpr auto PREDICTOR_KEY_GTURBO_CACHE_NAME = "PREDICTOR_KEY_GTURBO_CACHE_NAME";

/**
 * @brief 序列号设置;序列号不设置留空时,SDK将会自动尝试使用本地已经激活成功的有效期内的序列号
 * 值类型:string
 * 默认值:空
 */
static constexpr auto PREDICTOR_KEY_SERIAL_NUM = "PREDICTOR_KEY_SERIAL_NUM";

PREDICTOR_KEY_GTURBO_CACHE_NAME:首次加载模型会先对模型进行编译优化,通过此值可以设置优化后的产出文件名,这在多进程加载同一个模型的时候是有用的。

PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIXPREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET:设置运行时可以被用来使用的最大临时显存。

PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE:此值用来控制批量图片预测可以支持的最大图片数,实际预测的时候单次预测图片数不可大于此值,但可以是不大于此值的任意图片数。

PREDICTOR_KEY_DEVICE_ID:设置需要使用的 GPU 卡号。

PREDICTOR_KEY_GTURBO_COMPILE_LEVEL:模型编译等级。通常模型的编译会比较慢,但编译产出是可以复用的。可以在第一次加载模型的时候设置合理的 max_batch_size 并在之后加载模型的时候直接使用历史编译产出。是否使用历史编译产出可以通过此值 compile_level 来控制。当此值为 0 时,表示忽略当前设置的 max_batch_size 而仅使用历史产出(无历史产出时则编译模型);当此值为 1 时,会比较历史产出和当前设置的 max_batch_size 是否相等,如不等,则重新编译;当此值为 2 时,无论如何都会重新编译模型。

PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY:通过此值设置单张 GPU 卡上可以支持的最大 infer 并发量,其上限取决于硬件限制。init 接口会根据此值预分配 GPU 资源,建议结合实际使用控制此值,使用多少则设置多少。注意:此值的增加会降低单次 infer 的速度,建议优先考虑 batch inference 和 multi predictor。

PREDICTOR_KEY_GTURBO_FP16:默认是 fp32 模式,置 true 可以开启 fp16 模式预测,预测速度会有所提升,但精度也会略微下降,权衡使用。注意:不是所有模型都支持 fp16 模式。目前已知不支持fp16的模型包括:图像分类高精度模型。

多线程预测

GPU 加速版 SDK 的多线程分为单卡多线程和多卡多线程两种。 单卡多线程:创建一个 predictor,并通过 PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY 控制单卡所支持的最大并发量,只需要 init 一次,多线程调用 infer 接口。 多卡多线程:多卡的支持是通过创建多个 predictor,每个 predictor 对应一张 GPU 卡,predictor 的创建和 init 的调用放在主线程,通过多线程的方式调用 infer 接口。

已知问题

1. 多线程时图片按线程分配不均 或 不同batch size的图片交叉调用infer接口时,部分结果错误 A:EasyDL图像分类高精度模型在有些显卡上可能存在此问题,可以考虑填充假图片数据到图片比较少的线程或batch以使得infer间的图片绝对平均。

2. 显存持续增长或遇到 terminate called after throwing an instance of 'std::runtime_error' what(): Failed to create object A:部分显卡存在此问题,如果遇到此问题,请确认没有频繁调用 init 接口,通常调用 infer 接口即可满足需求。

3. 开启 fp16 后,预测结果错误 A:不是所有模型都支持 fp16 模式。目前已知的不支持fp16的模型包括:EasyDL经典版图像分类高精度模型。目前不支持的将会在后面的版本陆续支持。

昆仑服务器

昆仑服务器SDK支持将EasyDL的模型部署到昆仑服务器上。SDK提供的接口风格一致,简单易用,轻松实现快速部署。Demo的测试可参考上文中的测试Demo部分。

参数配置接口

在上面的内容中我们介绍了如何使用EdgePredictorConfig进行运行参数的配置。针对昆仑服务器开发工具包,目前EdgePredictorConfig的运行参数所支持的Key包括如下项:

/**
 * @brief 序列号设置;序列号不设置留空时,SDK将会自动尝试使用本地已经激活成功的有效期内的序列号
 * 值类型:string
 * 默认值:空
 */
static constexpr auto PREDICTOR_KEY_SERIAL_NUM = "PREDICTOR_KEY_SERIAL_NUM";

/**
 * @brief 当有同类型的多个设备的时候,使用哪一个设备,如:
 * 使用哪张加速卡
 * 值类型:int
 * 默认值:0
 */
static constexpr auto PREDICTOR_KEY_DEVICE_ID = "PREDICTOR_KEY_DEVICE_ID";

/**
 * @brief 设置需要同时预测的图片数量
 * 值类型: int
 * 默认值:1
 */
static constexpr auto PREDICTOR_KEY_KUNLUN_BATCH_SIZE = "PREDICTOR_KEY_KUNLUN_BATCH_SIZE";

PREDICTOR_KEY_DEVICE_ID:设置需要使用的加速卡的卡号。

PREDICTOR_KEY_KUNLUN_BATCH_SIZE:设置单次预测可以支持的图片数量。

使用方法:

int batch_size = 1;
config.set_config(easyedge::params::PREDICTOR_KEY_KUNLUN_BATCH_SIZE, batch_size);

模型调优

通过设置如下环境变量,可以在初始化阶段对模型调优,从而让预测的速度更快。

export XPU_CONV_AUTOTUNE=5

FAQ

1. 如何处理error while loading shared libraries?

如:./easyedge_demo: error while loading shared libraries: libeasyedge.so.1: cannot open shared object file: No such file or directory 这是因为二进制运行时ld无法找到依赖的库。如果是正确cmake && make 的程序,会自动处理好链接,一般不会出现此类问题。

遇到该问题时,请找到具体的库的位置,设置LD_LIBRARY_PATH。

示例一:libverify.so.1: cannot open shared object file: No such file or directory 链接找不到libveirfy.so文件,一般可通过 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../../lib 解决(实际冒号后面添加的路径以libverify.so文件所在的路径为准)

示例二:libopencv_videoio.so.4.5: cannot open shared object file: No such file or directory 链接找不到libopencv_videoio.so文件,一般可通过 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../../thirdparty/opencv/lib 解决(实际冒号后面添加的路径以libopencv_videoio.so所在路径为准)

2. 如何处理一些 undefined reference?

如:undefined reference to `curl_easy_setopt@CURL_OPENSSL_3'

方案1:通过安装libcurl3 libcurl-openssl1.0-dev来解决。 方案2:如果开发者想不想使用低版本的openssl(如Ubuntu 18.04), 可以link静态库easyedge_static.a,自己指定需要的Library的版本:

示例:修改CMakeList.txt

find_package(CURL REQUIRED)
target_link_libraries(easyedge_demo  ${OpenCV_LIBS} easyedge_static pthread ${CURL_LIBRARIES} verify_static ${其他需要的库})

其中, 其他需要的库视具体sdk中包含的库而定。

3. EasyDL SDK与云服务效果不一致,如何处理?

后续我们会消除这部分差异,如果开发者发现差异较大,可联系我们协助处理。

4. NVIDIA GPU预测时,报错显存不足

如以下错误字样:

paddle.fluid.core.EnforceNotMet: Enforce failed. Expected allocating <= available, but received allocating:20998686233 > available:19587333888.
Insufficient GPU memory to allocation. at [/paddle/paddle/fluid/platform/gpu_info.cc:170]

请根据显存大小和模型配置。调整合适的初始 fraction_of_gpu_memory。 参数的含义参考这里

5. 如何将我的模型运行为一个http服务?

目前cpp sdk暂未集成http运行方式; 0.4.7版本之后,可以通过start_http_server方法开启http服务。

6. 运行NNIE引擎报permission denied

日志显示:

open sys: Permission denied
open err
: Permission denied
open err
: Permission denied

请使用sudo在root下运行。

7. 运行SDK报错 Authorization failed

情况一:日志显示 Http perform failed: null respond

在新的硬件上首次运行,必须联网激活。

SDK 能够接受HTTP_PROXY 的环境变量通过代理处理自己的网络请求。如

export HTTP_PROXY="http://192.168.1.100:8888"
./easyedge_demo ...

情况二:日志显示failed to get/check device id(xxx)或者Device fingerprint mismatch(xxx)

此类情况一般是设备指纹发生了变更,包括(但不局限于)以下可能的情况:

  • mac 地址变化
  • 磁盘变更
  • bios重刷

以及系统相关信息。

遇到这类情况,请确保硬件无变更,如果想更换序列号,请先删除 ~/.baidu/easyedge 目录,再重新激活。

8. 使用libcurl请求http服务时,速度明显变慢

这是因为libcurl请求continue导致server等待数据的问题,添加空的header即可

headers = curl_slist_append(headers, "Expect:");

9. 运行二进制时,提示 libverify.so cannot open shared object file

可能cmake没有正确设置rpath, 可以设置LD_LIBRARY_PATH为sdk的lib文件夹后,再运行:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib ./easyedge_demo

10. 编译时报错:file format not recognized

可能是因为在复制SDK时文件信息丢失。请将整个压缩包复制到目标设备中,再解压缩、编译

上一篇
Windows
下一篇
Linux-Python