EasySense版本t187-多线程

t187版本

1. 更改原因

  • 主要原因: 提升流分析速度

  • 分析:
    程序在主线程对获取视频的每一帧分析,设分析算法执行一次500ms
    要求程序一秒分析一帧或两帧,则程序会阻塞(1000/500 = 2)
    若希望程序一秒分析超过2帧,则一定会丢帧

2. 基本思路

  • 线程数量:每秒执行n次,创建n/2个线程
  • 线程安全:控制对buf_queue访问,使用std::condition_variable与std::mutex

3. 结果缓存队列

  • 线程将结果push到res_buf_queue
    result从res_buf_queue中取(可能为空)
    使用模板,互斥锁,条件变量实现队列;
  • 设置buf_queue最大长度为:500/40 + 1 = 13

4. 均匀取流

  • 更改get_frame和put_frame初步思路为每一个线程建立队列
    轮转分配frame到队列
  • push_frame()操作时间间隔为40s,为了保证每个时刻主线程都可以取到结果

5. 性能测试

  • 在相同时间10s内,开启不同数量线程执行次数Input_Frame()次数
  • 相同情况下测试5轮结果,取最大最小和平均值
min max average
0 thread 43 48 46.4
1 thread 44 57 50.4
2 threads 77 95 90.0
3 threads 116 126 123.2
4 threads 104 131 123.3
5 threads 105 128 188.1
  • 可以看出虽然GIL使多线程下python几乎串行,对于IO密集型的操作可能回有性能上的一定提升,但比较有限

智能指针

代码中唯一用到shared_ptr在frame_node;
frame_node和alarm_ids有相似之处,都在子线程中获取,但在主线程中使用,因此都需要放入结果队列;
但不同之处在于alarm_ids离开作用域后自动析构,不用担心内存问题
frame_node在子线程中拷贝到结果队列后引用加一,随后while进入下次循环同时析构,引用减一,此时引用为1,并且暂存在队列。
在主线程中使用时,调用take()取一个pakage(take会释放pakage),因此赋值给主线程frame_node后引用计数=1
由于frame_node声明在while内,主线程while进入下一次循环后,frame_node被释放
因此暂时不存在垃圾内存问题

9.1遗留问题(已解决)

① alg_thread.h 36行,阻塞(注释掉这一函数后,buf_queue一直被push,导致长度无限增长)
② 主线程取buf_queue失败

思考: 设置buf_queue的长度不能超过N(已解决)
取buf_queue失败,是因为锁的问题(已解决)
解决途径:使用标准库conditional_variable;为RunPython()添加GIL锁

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。