python的任务调度问题
首先描述一下现象
Win10系统,python编程,进行双摄像头采集识别,用到了opencv,由于opencv不支持多进程编程,故而用多线程方式。
程序刚启动时速度很快,但随着时间的推移,几分钟后程序变得很慢,,其间没有其他操作,也没有其他软件干扰。
下图发现,CPU的使用率从最开始的60%,一直降到20%,为初始的1/3,而帧率从10+掉到1帧以下,运行效率为1/10,不是应该降到3.3帧才对的么?
尝试解决方法
1 在Win10设置中,将电脑设为高性能,无效
2 打开Windows资源监视器发现,CPU使用率从最开始的60%降低到最后的不到20%,下降明显。但连续监控发现CPU温度并没有超标,最高只有68度左右。所以肯定不是过热导致的CPU降频。
3 重装了了电脑,依然如此。
4 运用了CPU锁频软件ThrottleStop,可以锁住CPU的频率为最高的睿频,但依然无法解决CPU占用率往下掉
5 BIOS中一通操作,无效。
思考问题
初步判断是Win10的任务调度出了问题,导致如此结果。
OpenCV本身是支持多进程的,这一点很容易证明,运行程序,观察CPU占用率,如下图
如果它不支持多进程的话,对于我的6核CPU来说,即使单核满负载,总的CPU使用率最多只能占用到16.67%,而现在CPU占用率超过50%,说明所有核心均有一半的负载,或者有一半的核心已经满负载,而这肯定是多进程才能做到的。
既然opencv本身支持多进程,那么我再开多线程就是多此一举,而且效率肯定会更低。因为Python本身是不支持多进程的。
最终解决
出问题的代码是这样的,在主程序中调用函数,在函数中进行无限循环
方案1,用线程方式实现
if __name__ == '__main__':
th0 = threading.Thread(target=camera_detect, args=(0, True, True, True, 280, False))
th0.start
方案2,用函数方式实现循环
改为下面这样,不用线程的方式,问题依然如故:
if __name__ == '__main__':
camera_detect(0, True, True, True, 280, False)) # 函数内部有一个while循环
方案3,在主程序段实现循环
最终,将无限循环改到主程序中,函数运行一次就返回一次,在主程序中完成循环调用:
if __name__ == '__main__':
while True: # while循环移动到主程序段,问题解决
camera_detect(0, True, True, True, 280, False))
问题解决,由此说明,问题肯定出在任务调度。
正常帧率
问题解决以后,开启双摄像头时,CPU总体使用率为50%左右,两个摄像头的帧率均能达到7.5帧/秒,基本满足运行需要
问题溯源
接下来依然用问题代码运行程序,
IDE我用的是Pycharm,改为VSCode以后,问题依然。
直接用命令行运行程序,问题依然。
这说明与编译器无关。
而无限循环是位于主程序,还是位于函数中,这决定了程序最终运行的效率。这说明问题与Win10的任务调度无关,只与Python的任务调度有关。
在主程序中运行的代码,明显优先级更高。
函数中的代码,会因为某种神秘原因,导致运行效率降低。
水平有限,只能分析到这里,具体原因欢迎留言讨论。