rknn优化教程(二)
文章目录
- 1. 前述
- 2. 三方库的封装
- 2.1 `xrepo`中的库
- 2.2 `xrepo`之外的库
- 2.2.1 `opencv`
- 2.2.2 `rknnrt`
- 2.2.3 `spdlog`
- 3. `rknn_engine`库
1. 前述
OK,开始写第二篇的内容了。这篇博客主要能写一下:
- 如何给一些三方库按照
xmake
方式进行封装,供调用 - 如何按照
xmake
构建rknn_engine
2. 三方库的封装
这个三方库的封装,主要分为如下两类:
- 类似
opencv
这种在xmake
的xrepo
中已经包含的库 - 类似
rknnrt
这种纯粹的三方库,完全需要我们进行处理的库
2.1 xrepo
中的库
比如Eigen
和opencv
库,我们可以直接使用xrepo
中的库,比如直接:
add_requires("opencv", "eigen3")
在使用xmake
的时候,可以直接通过网络下载依赖库,然后进行处理。但是,一般我们在rk3588上都会通过apt
安装了libopencv-dev
这些,所以我还是建议直接使用系统库,避免库的版本问题,所以就是如之前博客说的:
add_requires("cmake::OpenCV", {alias = "opencv", system = true})
add_requires("cmake::Eigen3", {alias = "eigen3", system = true})
但是,还有一个问题,如果我们不是在rk3588上进行编译,而是通过交叉编译呢?使用交叉编译的时候,xmake
能够自动调用交叉编译器进行opencv
的编译,然后得到一个可被调用的库,但是!opencv
这种库很有可能编译失败,依赖的ffmpeg
等等库太多了,那么有没有优雅的解决方法呢?
其实有现成的
aarch64
的opencv
库,我们可以把这个库直接拿下来,看做是rknnrt
一样处理!
2.2 xrepo
之外的库
使用rk3588,调用其npu,必然要用rk官方的rknnrt
和librga
库,然而xrepo
中并不收纳这些库,所以我们就需要自己构建。当我们拿到头文件和库文件之后,我们就可以按照如下的目录结构进行处理:
./xmake_repo
└── packages├── e│ └── eigen3│ ├── include│ │ └── Eigen│ │ ├── Eigen的各种头文件│ └── xmake.lua├── l│ └── librga│ ├── cross│ ├── linux│ │ └── arm64│ │ ├── include│ │ └── lib│ └── xmake.lua├── o│ └── opencv│ ├── cross│ ├── linux│ │ └── arm64│ │ ├── bin│ │ ├── include│ │ ├── lib│ │ └── share│ └── xmake.lua├── r│ └── rknnrt│ ├── cross│ ├── linux│ │ └── arm64│ │ ├── include│ │ └── lib│ └── xmake.lua└── s└── spdlog├── include│ └── spdlog│ ├── sdplog的各种头文件└── xmake.lua
当然细心的我们发现了,我并不是每个库的目录结构都一样,而且有的目录下面还有一个cross
,这个其实是一个软链接,都是对应链接同目录的linux
目录。但是有一个非常相同,每个目录下都有一个xmake.lua
,这将是保证xmake
能够找到库的核心文件。
这里我就以三个比较代表性的说明一下。
2.2.1 opencv
这个opencv
主要就是在交叉编译的时候使用的,如果在rk3588平台上直接编译,则不使用我们自己处理的这个,所以这里的cross
是我们最终使用的文件(虽然最终还是软链接到了linux
)……
那么xmake.lua
可以这样写:
package("opencv")set_description("The opencv package")add_configs("shared", {description = "Build shared library.", default = true, type = "boolean", readonly = true})on_load(function (package)package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch()))end)on_fetch(function (package)local result = {}local libfiledir = (package:config("shared") and package:is_plat("windows", "mingw")) and "bin" or "lib"result.links = {"opencv_core", "opencv_video", "opencv_videoio"}result.linkdirs = package:installdir("lib")result.includedirs = package:installdir("include/opencv4")result.libfiles = {path.join(package:installdir(libfiledir), "libopencv_core.so"),path.join(package:installdir(libfiledir), "libopencv_video.so"),path.join(package:installdir(libfiledir), "libopencv_videoio.so")}return resultend)
package
描述了包名,务必和文件夹同名
on_load()
函数的具体含义和使用参考xmake
的官方文档,我们这里只是定义了包的安装目录
on_fetch()
函数的具体含义和使用参考xmake
的官方文档,但是里面定义了头文件目录、库文件目录,和将要链接的库。注意的是这里我只写了链接
libopencv_core.so
、libopencv_video.so
和libopencv_videoio.so
,是因为只用到了这些,如果你要用到更多,那就在对应添加一下即可。
2.2.2 rknnrt
因为这是使用rk平台必须使用的库,所以不管是本机编译还是交叉编译,都要使用到,所以cross
和linux
都是将要使用到的。所以对应的xmake.lua
:
package("rknnrt")set_description("The rknnrt package")add_configs("shared", {description = "Build shared library.", default = true, type = "boolean", readonly = true})on_load(function (package)-- 官方提供的库,也只有一个版本,就不区分 release 还是 debug 了-- package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch(), package:mode()))package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch()))end)on_fetch(function (package)local result = {}local libfiledir = (package:config("shared") and package:is_plat("windows", "mingw")) and "bin" or "lib"result.links = "rknnrt"result.linkdirs = package:installdir("lib")result.includedirs = package:installdir("include")result.libfiles = path.join(package:installdir(libfiledir), "librknnrt.so")return resultend)
2.2.3 spdlog
spdlog
和Eigen
都是纯头文件库,所以不管是aarch64
还是x86
,都是使用同样一套文件。为了简单,我还是同意都放在本地的repo
之中。这里给一下spdlog
的xmake.lua
示例:
package("spdlog")set_description("Fast C++ logging library.")add_configs("library", {headeronly = true})on_load(function (package)package:set("installdir", os.scriptdir())end)on_fetch(function (package)local result = {}result.includedirs = package:installdir("include")return resultend)
OK,特别的地方相信聪明的我们肯定注意到了。我就不指出来了!
3. rknn_engine
库
三方库我们都已经通过自己写的xmake.lua
加入到xmake
的repo
中了,rknn_engine
的目录结构:
./rknn_engine/
├── demo
├── include
├── README.md
├── src
├── xmake.lua
└── xmake_repo
那就直接给出xmake.lua
的内容:
set_project("rknn_engine")
set_version("1.0.1", {soname = true})
set_xmakever("2.3.1")
set_languages("cxx17", "c17")
set_warnings("all")option("local_repo")set_default("./xmake_repo")set_showmenu(true)set_description("local_repo for xmake")
option_end()add_repositories("local-repo $(local_repo)")
add_requires("spdlog", "rknnrt", "librga")if is_plat("cross") then add_requires("opencv", "eigen3")
else add_requires("cmake::OpenCV", {alias = "opencv", system = true})add_requires("cmake::Eigen3", {alias = "eigen3", system = true})
endtarget("rknn_engine")-- set_kind("$(kind)")set_kind("shared")-- set_basename("rknn_engine")-- 添加公共依赖add_includedirs("include", {public = true})add_headerfiles("include/(**.h)")add_files("src/**.cpp")add_packages("spdlog", "rknnrt", "librga", "opencv", "eigen3")add_rules("utils.install.pkgconfig_importfiles")add_rules("utils.install.cmake_importfiles")-- 交叉编译命令
-- xmake f -p cross --cross=aarch64-linux-gnu-
-- 或者
-- xmake f -p cross --sdk=/path/to/cross/compiler
注意到这里的几个地方:
option(“local_repo”)
这个是加一个编译选项,可以配置本地
repo
的地址add_repositories(“local-repo $(local_repo)”)
添加一个本地
repo
的地址if is_plat(“cross”) then
这个则是按照编译的平台进行处理,可以对应
xmake f -p cross
中的这个-p
选项,具体有哪些取值也还是参考xmake
的官方文档add_rules(“utils.install.pkgconfig_importfiles”)
add_rules(“utils.install.cmake_importfiles”)
这个是增加最终安装的规则,可以增加
pkgconfig
和cmake
的东西
OK,这篇博客就写这些了。
相关文章:
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...