type
status
date
slug
summary
tags
category
icon
password
async_frame 有两个版本,自瞄仓库中的是跨平台版本,可以运行在主机、nuc和nx上
简介
项目共分为两个,threadPool更底层,主体是一个线程池,含有了任务窃取和FIFO机制,保证输入输出的一致性和时序,使用较为复杂但是更加灵活。AsyncInfer是基于threadPool的神经网络推理框架,适合处理单次的神经网络推理,使用简单,但是不够灵活。
ThreadPool
流程
用户首先创建一个task,这个任务将会被推入线程池,当任务结束之后,线程池会自动从任务的返回值中获取运算结果,然后自动调用回调函数。用户也可以创建一个tag,随任务一起送入线程池,程序运行结束后取答案时,可以同时得到运算结果和tag。
模版参数
模版参数有两个,分别是_Result和_Tag,前者是任务的答案,后者是tag,在程序运行过程中只能有一个tag与一个task绑定,并且在程序运行过程中tag不会发生改变。
需要注意的是,tag并不是必须的,后面将不再重复说明。
使用方法
创建任务
创建任务的方法有三种,常用的是push()和force_push(),他们的区别在于,当线程池满时,前者会阻塞,后者会通过扩充线程池的方式强制推入任务,也就是不阻塞。需要根据实际情况使用这两中push方法。
还有一种是free_push(),他会快速推入任务而不进行任何检查,注意他不是线程安全的。
你要使用一个std::function<_Result(int,int)>来创建任务,这个函数指针的两个参数是Pool_id,thread_id,这两个是线程池和线程的唯一标识符。
你可以使用这三个函数结合一个函数指针和一个Tag创建一个task。
取出任务
有两种方式可以去除任务,get()和fast_get(),他们的唯一区别在于,get()会将答案拷贝出来,而fast_get()会传答案的引用。在最新版本中这两个函数完全一致,不存在区别,但是不排除在更新版本的更新中区分。
get()函数有一个bool型的返回值,当成功取到答案时会返回true,当队列是空的或者某些原因没有取到答案时返回false。
静态内存
如果你需要使用异步实现大量同样操作,你可以使用静态内存存储那些不会发生变化的数据。线程池设置类静态内存管理器,用来管理静态内存的自动析构。
使用ThreadPool<_Result,_Tag>::try_to_malloc_static<_Infer>()来根据你的数据拷贝到静态内存,需要注意的是,这个函数会调用_Infer的拷贝构造,安全的方式是使用check_inlaw来判断是否满足要求,如果失败返回false
使用ThreadPool<_Result,_Tag>::try_to_alloc_static()可以从外部申请一块静态内存,然后将指针存入管理器,这种方式比较自由,推荐实用这种方式,分配内存,失败则返回false
使用ThreadPool<_Result,_Tag>::get_staticMem_ptr()可以获取已经申请的静态内存的数据,如果没有分配,返回false
AsyncInfer
#include <AsyncInferFrame.hpp>来使用异步推理框架。
总的来说,神经网络推理大体可以分为三步,预处理、推理、后处理。
TensorRT环境配置
在cross_platform 的cmake/FindTensorRT.cmake中添加你的TensorRT路径即可。
异步推理器的创建
使用AsyncInfer<Infer,Result,Tag>来创建异步推理器,其中Infer是推理器类型,可以使用TrtInfer/VinoInfer来强制选择推理器,但是更推荐使用AUTO_INFER来根据当前情况选择最优的推理器。模版的后两个类型是选择填写的,分别是输出和标识符,和上面ThreadPool类似。AsyncInfer的构造函数可以接受三个参数,分别是model_path,is_warmup,device_name,分别是模型路径,是否预热模型,处理设备CPU/GPU
也可以调用默认构造函数,然后使用setInfer来设置推理器
推理流程
pushInput()接受一个函数指针和一个Tag(可选),这个函数指针的返回值是void*,仅有一个参数是std::vector<det::Binding>&这个参数是网络的输入层形状,在这个函数中一般需要完成你的模型的预处理操作,将输入信息转变成张量,或者说一个数组。当然,你也可以使用std::bind偏函数的形式,使你的函数可以接受更多参数,这在使用处理图像的网络中更为常用。特别注意对于cv::Mat类型的数据,需要使用std::move( )转交对象控制权,以防止意外析构,导致程序运行错误。
registerPostprocess()函数用来注册后处理函数,当你的推理任务完成后将会自动调用后处理函数,以将输出原始数据转化成Result类型的数据。这个函数接受三个参数,依次是std::vector<void*>,std::vector<det::Binding>,Tag,分别是输出原始数据,网络输出形状,Tag。函数的返回值是Result,是你网络的最终输出结果。
registerCallback()函数用来注册回调函数,当你的推理任务完成时会自动调用这个函数。这个函数接受Result和Tag,不必返回任何参数。
cross_platform
这是一个ROS2跨平台检测包,可以读取当前的处理器架构和神经网络推理的环境情况,使用该包提供的检测服务,可以满足自瞄的跨平台需