海思SS928V100的视频处理异常退出导致资源被占用不能销毁的问题解决

前些时间开发海思SS928V100的视频解码功能时遇到一个问题。就是当视频解码的程序由于某些原因,包括但不限于程序异常 ,手动杀进程等等 ,异常退出了。程序重新启动无法获取到视频解码器资源,只能断电并重新通电启动主板才能重新运行程序。

经过分析,应该是程序异常退出导致占用的资料无法释放了。后来,从供应商哪里获取到新的SDK库和一个配置方法后解决。但这样毕竟感觉绕了一手,感觉有点不太踏实。

这几天有些时间,深入研究芯片的开发文档,发现其中有个应对这种情况的解决方案原文 :


2.3.3 强制销毁 VB 功能
VB在占用状态时无法被销毁,插入ssxx_base.ko时加上模块参数g_vb_force_exit=1,
即使VB正在被使用也可强制销毁,因此请谨慎使用此功能,需保证业务正常运行时不
可主动销毁VB,必须待所有业务完全退出之后才能主动销毁VB。
须知
强制销毁VB功能是为了应用程序异常崩溃之后方便业务重启而设计的:用户态应用程
序异常崩溃之后,应用程序已经无法按正常的业务退出流程操作,此时重启业务前须
先进行ss_mpi_sys_exit和ss_mpi_vb_exit把上次应用程序异常崩溃之后无法销毁的VB
资源先销毁,然后再进行正常的业务重启流程。

其中在供应商提供的解决方法的配置在 /ko/load_ss928v100 的insmod ot_base.ko配置里增加 g_vb_force_exit=1 即是出自这里。

海思3403-SS928 yolov5 c++开发日记(7)

在上一个日记中记录的问题,最近进行了验证和解决。其中的问题1、aclInit(“acl.json”)  一个进程只能调用一次。这个进一步验证了。所以,只能从代码本身入手进行解决。需要在主线程一开始就调用这个初始化。并且,验证了,这个初始化是可以与子线程无关的。即,这个初始化就是这么调一下哪个函数,不用向下传递什么参数、数据或者指针什么的。另外,在结束时调用 aclFinalize() ,虽然,调用了这个并不能再重新调用  aclInit()  这个重新初始化。但本着有头有尾,以防出现什么内存泄漏问题,还是要按套路来。在程序结束时调一下这个。

第2个问题是,“调用aclInit(…) 函数的线程必须与后面调用 aclrtMalloc( …) 和 aclrtMemcpy(…) 的是同一个线程,否则会报提示不能取得硬件资源的错” 这里需要注意的是子线程中在开始时,必须调用  aclrtSetDevice()、aclrtCreateContext()、aclrtCreateStream() 这三个函数,当然也可以在每次处理时循环调用这个和 Destory() 但这样性能不好。这三个的作用是调置调用的NPU设备号,创建上下文 ,创建一个处理流。相当于告诉设备哪个线程对应的是哪块数据。如果三个函数在主线程上执行,哪子线程在处理时就会抛没有上下文 ,或者没有stream的异常错误。并且需要在每次调用NPU处理时都调用一下aclrtSetCurrentContext() 函数,让NPU处理指定上下文的数据,否则会抛异常。

最后,还是有个比较奇怪,不知是硬件设计就是这样,还是代码还是有哪里不对的问题。虽然,最后使用一些感觉好像是折衷的方法,还是就是这样的方法实现了同一个NNN核,同时多线程运行多个模型 (目前测试了同时运行4个),但就是感觉怪怪的。

1、代码中不能使用SDK提供的异步处理函数  aclrtMemcpyAsync()、aclmdlExecuteAsync() 。 调用 aclrtMemcpyAsync() 时会抛内存不足的异常提示,但我板上内存明明是足够的,数据也不是很大。只能调用 aclrtMemcpy()。使aclrtMemcpy(),然后调aclmdlExecuteAsync(),会卡死。只能调aclmdlExecute()。
2、这样分别调aclrtMemcpy(),aclmdlExecute()是不会卡死了,但在多线程时,还是会因为冲突跑着跑着就卡住不动。所以,最后,我只能人为加入线程锁,实现多线程单核处理多个模型。但这样感觉NPU不是并行处理多个模型,而是互斥的一个个交替处理。