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锁