专栏算法工具链FAQ HobotCV

FAQ HobotCV

DR_KAN2023-09-26
64
0

应用程序开发部分

Hobotcv提供的接口为什么不能在w全局对象的构造函数中使用?

hobotcv框架中的接口都需要从CVFramework::Instance()直接或者间接获得。在CVFramework::Instance()第一次被调用时,将进行框架的初始化,调用各个模块的初始化函数。

而各个模块的初始化函数是通过Dummy的全局对象的构造函数注册到初始化框架中。

所以,如果在应用程序的全局对象构造函数中CVFramework::Instance()被调用,则不能保证所有模块的初始化函数已经注册到初始化框架,从而存在风险。


为什么要定义IContext 和 ISession,他们之间是什么关系

IContext 用来表示系统环境,最重要的是包含的设备列表,应用程序还可以在IContext里面设置传给设备的各种参数。

ISession则表示了一个OP的执行环境,创建ISession时保留了IContext指针,所以,IContext的生命周期需要大于ISession。一个ISession的Run()接口可以被多次调用,也可以被不同线程同时调用。

ISession创建之后,在IContext删减设备,不会影响ISession的可用设备列表。

ISession创建之后,修改和增删IContext里的参数是否会生效,取决于具体的 OP实现和设备实现。


为什么屏蔽接口类的析构方法?如果需要实现智能指针封装,自动释放该怎么做?

强化基于接口的编程模式 以及Create/Destroy的资源使用范式,让用户对于资源的生命周期有清晰的掌握。

如果确实需要用智能指针来包裹获取的接口类对象,可以用如下方法:


输入buffer是从相机拿到的vio_buffer_t, 该怎么传给gdc设备? 如果需要同时支持CPU设备呢?

IImage支持设置自定义属性,可以通过设置自定义属性的方式传给设备。属性名和方式需要和设备的实现保持一致。 一个可能的例子:

如果支持该OP的设备同时包含gdc和CPU,应用程序代码可以同时设置好两种数据传递方式。


图像内存从设备分配,如何拿到设备分配内存的私有控制头?

应用程序调用 ISession->AllocDevMem()从设备分配内存以后,可以通过image->GetPlaneVirtAddr()/

image->GetPlanePhysAddr() 拿到设备分配内存的地址。如果想要拿到设备内存的私有控制头,比如vio_buffer_t,需要设备在image中设置相应的属性,应用程序调用 image->GetParamXXX()来获取。


应用程序调用设备分配内存函数来分配输出图像的内存。为什么在分配成功后,可能获取到无效的虚拟地址和物理地址?

有些设备类型,其输出内存事先注入在一个队列中。每执行一次操作,从队列中取出一个buffer并返回给调用者。

这种场景和Hobotcv的使用范式有区别: Hobotcv要求在运行OP前,输出内存必须设置,要么是应用程序已有的内存,或者应用程序调用设备分配内存。

在这类设备上,调用AllocDevMem()去分配输出内存时,设备层会分配无效的虚拟地址和物理地址来告知这种情况,同时,AllocDevMem()返回成功。

后续,设备在Run()函数中,拿到真正的Buffer后,会更新输出图像相应的信息。


如何指定OP运行的设备

有两种方式:

创建IContext时仅添加一个设备。或者

创建ISession后,调用ISession->SetBindDevice()来设置指定的设备


如何在运行OP时,传递临时参数给设备

可以通过ISession 的 Run()和ASyn()的最后一个参数进行传递。


异步执行时,回调函数如何保存应用程序需要保存的私有数据

回调函数实际上是一个仿函数,应用程序可以派生以后,添加自己想要保存的数据。


同步执行时,如何设置回调函数

同步执行,不支持每次OP运行时设置回调,因为作用不大。在 ISession级别可以设置一个正确执行和错误执行的回调函数,该回调函数同样也是仿函数实现。

传给operator()的参数task在函数结束后,不保证可用。


如何获取错误码和错误信息

除了Asyn()接口外,其他函数都可以通过GetLastErrorNo()和GetLastErrorMsg()获取。

GetLastErrorNo()返回的值是添加了Bole和模块编号的,可以调用ParseErrorNo()获取真正的error number。

在Asyn()和回调函数中,可以从task相应的接口,获取该task错误信息。


设备开发部分

如何在运行时给设备传递非初始化参数

有几种方式:

如果是和特定OP相关的,可以在IContext中设置,在设备层读取。

如果是和OP的某次执行相关的,可以在Run()/Async()的最后一个参数传递

如果和特定OP无关的,可以直接通过设备的IParam 接口设置设备参数

设备需要输出文档,详细描述各种方式可以接受的参数名字,含义,类型和用途。


设备初始化时,需要使用的配置参数该如何获取

Hobotcv在框架初始化时,会调用设备的Start()函数来初始化设备。如果设备初始化时,需要动态获取配置参数,则无法通过前面问题中说的方式给设备传递参数,可选的方案有:

  • 通过环境变量来获取

  • 通过搜索预定义好的目录和文件来获取

  • 设备对外暴露私有接口,由应用程序去设置

  • 通过框架提供的全局配置对象获取设备配置参数 (TBD)

其中,第一种和第二种方式,可以实现对应用程序透明(可以不需要添加设置配置代码),对应用程序开发友好。

第三种和第四种,则需要应用程序添加额外的配置代码,并保证在hobotcv框架初始化前完成。

从通用性和灵活性来说第四种最好。

无论采用哪种模式,都需要设备实现提供详细文档,说明配置参数的含义和如何设置。


如何让应用程序调用设备的函数

设备可以重载Get/SetParamXXX的接口来实现调用函数。应用程序可以通过调用Get/SetParamXXX接口来调用,类似于读取/设置设备寄存器。

示意代码如下


如何实现新的设备调度策略

从DeviceScheduler类派生,并实现SelectDevice()方法。

构造函数中传进的两个Vector分别包含了设备列表和设备优先级。

实现后,需要调用DeviceSchedulerRegistry::Instance()->RegisterInterface()来注册。

使用时,可以在IContext中设置“device_scheduler”来使其生效。


如何设置设备状态

框架本身会负责设备状态的设置。一般情况下,设备仅需要在出错时,设置状态为kDevStatusError。


创建设备时,设备构造函数中run_max,pend_max,urgent_reserved时什么含义?

这三个参数分别表示,一个设备同时可以支持的并行任务数(run_max),可以pending的等待任务数(pend_max)。当新任务下发给设备时,当前pend的任务已经达到pend_max, 则会立即失败返回。

urgent_reserved时设备预留给urgent任务的数量。当urgent任务到达时,在执行的urgent任务大于或者等于urgent_reserved, 则该任务会进入pending队列。

一个设备可以同时并行执行的最大任务数为run_max+urgent_reserved


设备的kDevStatusOverload 和kDevStatusFullload 是如何判定和设置

框架会根据设备调度参数和当前负载情况,自动判断这两个状态,逻辑如下代码:


设备在实现IDevSession::ExecAsyncTask()时,为什么在调用task->app_callback(task)之后,不能再访问task

因为task->app_callback()会唤醒应用程序的调用者,应用程序很可能会接着调用释放task的函数。由于操作系统调度问题,不能保证这个task->app_callback()之后使用task的代码,一定会在释放task之前完成,从而存在风险。

算法工具链
官方教程
评论0
0/1000