海思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不是并行处理多个模型,而是互斥的一个个交替处理。