[英]Why is my Python app stalled with 'system' / kernel CPU time
首先,我不确定是否应将此作为Ubuntu问题发布或在此处。 但我猜它更像是一个Python问题,而不是一个OS问题。
我的Python应用程序在64核AMD服务器上运行在Ubuntu之上。 它通过网络从5 GigE摄像机中提取图像,通过ctypes
调用.so然后处理它们。 我看到我的应用程序经常暂停,导致相机的帧被外部相机库丢弃。
为了调试这个,我使用了流行的psutil
Python包,我在一个单独的线程中每0.2秒注销一次CPU统计数据。 我在该线程中睡眠0.2秒,当睡眠时间长得多时,我也看到相机帧被丢弃。 我看到长达17秒的停顿! 我的大多数处理是在OpenCV或Numpy(两者都发布GIL)或应用程序的一部分中的multiprocessing.Pool
有59个进程(这是为了绕过Python GIL)。
当暂停发生时,我的调试日志记录在我的许多进程'线程上显示非常高的'系统'(即内核)CPU时间。
例如。 我看到CPU时间如下(通常每0.2秒),然后突然大跳('进程'数字在CPU利用率,即1个CPU完全使用将是1,Linux top
显示123%将是1.2):
Process user | Process system | OS system % | OS idle %
19.9 | 10.5 | 6 | 74
5.6 | 2.3 | 4 | 87
6.8 | 1.7 | 11 | 75
4.6 | 5.5 | 43 | 52
0.5 | 26.4 | 4 | 90
我不知道为什么在匹配高流程系统使用之前报告一行高OS系统使用情况。 两者相比,64核中的26.4 = 41%。 此时,我的应用程序经历了大约3.5秒的暂停(由我的CPU信息记录线程使用OpenCV的cv2.getTickCount()
以及Python日志记录输出中的时间戳跳转确定)导致多个相机帧被丢弃。
发生这种情况时,我还记录了我的进程的每个线程的CPU信息。 对于上面的示例,25个线程在“系统”CPU利用率为0.9时运行,并且在0.6处运行更多,这与上面26.4的进程的总数相匹配。 那时大约有183个线程在运行。
在使用多处理池(它用于短脉冲串)之后,这种暂停通常似乎很接近,但每次使用池时都不会发生。 此外,如果我将需要在池外进行的处理量减半,则不会发生相机跳过。
问题:如何确定操作系统'系统'/内核时间突然出现的原因? 为什么会在Python应用程序中发生?
更重要的是:任何想法为什么会发生这种情况以及如何避免它?
笔记:
upstart
以root身份运行的(不幸的是,它不得不用于相机库) respawn
)并且这种情况每天发生多次,因此不是由于长时间运行,我也看到这在进程开始后很快发生 nice
的-2,我已经尝试删除没有影响的nice
好。 我有自己的问题的答案。 是的,我需要3个多月的时间才能做到这一点。
它似乎是Python中的GIL颠簸,这是大规模“系统”CPU峰值和相关暂停的原因。 这是对颠簸来自何处的一个很好的解释 。 那次演讲也指出了我正确的方向。
Python 3.2 引入了一个新的GIL实现来避免这种颠簸。 结果可以通过一个简单的线程示例显示(摘自上面的演示文稿):
from threading import Thread
import psutil
def countdown():
n = 100000000
while n > 0:
n -= 1
t1 = Thread(target=countdown)
t2 = Thread(target=countdown)
t1.start(); t2.start()
t1.join(); t2.join()
print(psutil.Process().cpu_times())
在我的Macbook Pro with Python 2.7.9中,它使用14.7秒的“用户”CPU和13.2秒的“系统”CPU。
Python 3.4使用15.0的'user'(略多)但只有0.2s的'system'。
因此,GIL仍然存在,它仍然只运行与代码是单线程时一样快,但它避免了Python 2的所有GIL争用,表现为内核('系统')CPU时间。 我认为,这种争论正是造成原始问题的原因。
发现CPU问题的另一个原因是OpenCV / TBB。 完整记录在这个SO问题中 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.