我有一个使用大量内存的 python 应用程序,当我在循环中处理它时应该没问题try / except MemoryError。不幸的是,MemoryError 异常从未引发 - 在此之前,python 被 OOM Killer 杀死(在 Debian Linux 上)。
问题是为什么......以及我如何在 Python 中捕获错误。如果我能抓住它,我有一个简单的缓解措施,但无一例外,我无法调用我的缓解措施。
有关信息,该应用程序正在处理视频,每帧大约是 15MB 的 numpy 对象。如果内存不足,我很乐意降低帧速率并重试。
我还尝试在加载每一帧时使用 psutil.available 跟踪内存使用情况,但该进程被终止,仍然有大约 350MB 显示为可用内存(总共 2GB)。我认为这是一个碎片问题。
因此我遇到的问题是我可以任意设置一些限制,例如,如果我获得 <500MB 的可用内存,然后以较低的帧速率重新开始,但这一切都感觉有点随意且不是很健壮。如果应用程序或者操作系统或硬件发生变化,我可能会发现下次它在剩余 501MB 时崩溃,或者其他什么......这就是为什么我宁愿通过 MemoryError 异常来处理它。
可悲的是,这似乎不是一个常见问题,“python 调用 oom-killer 异常”只给了我两页 Google 搜索结果!以前这里的大多数答案是“不要使用太多内存”,这不是很有帮助 - 在我的情况下,我想使用尽可能多的可用内存,但如果需要,我很乐意减少使用。只是 Python 没有给我机会在它被杀死之前这样做!
任何想法都非常感谢。
我一直在研究一个使用OpenCV从视频中读取帧并创建“活动”(即从一帧变为另一帧的事物)组合的python应用程序。为此,我只想每秒检查一帧左右。
很长时间以来,我一直在使用以下代码(简化后的代码,简化了一些错误检查,分类等操作)来获取视频对象和第一帧:
video_capture = cv2.VideoCapture(video_fullpath)
this_frame = get_frame(0)
def get_frame(time):
video_capture.set(cv2.CAP_PROP_POS_MSEC, time)
capture_success, this_frame = video_capture.read()
return this_frame
Run Code Online (Sandbox Code Playgroud)
使用上面的后两行代码获取后续帧的过程确实很慢。在2015年的MacBook Pro上,每帧的获取时间为0.3-0.4s(视频中的间隔为1秒,这是一个约100MB的.mp4视频文件)。相比之下,我将其余各帧与其前一帧进行比较的其余操作非常快-通常少于0.01s。
因此,我一直在研究多线程,但我一直在努力。
我可以在“超前”的基础上进行多线程工作,即在处理一帧的同时可以获取下一帧。处理完前一帧后,我将等待“超前”操作完成后再继续。我使用以下代码进行操作:
while True:
this_frame, next_frame_thread = get_frame_async(prev_frame.time + time_increment)
<< do processing of this_frame ... >>
next_frame_thread.join()
def get_frame_async(time):
if time not in frames:
frames[time] = get_frame(time)
next_frame_thread = Thread(target=get_frame, args=(time,))
next_frame_thread.start()
return frames[time], next_frame_thread
Run Code Online (Sandbox Code Playgroud)
上面的方法似乎是可行的,但是因为与其他所有操作相比,查找操作是如此缓慢,因此实际上并没有节省太多时间-实际上很难看到任何好处。
然后,我想知道是否可以并行获取多个帧。但是,每当我尝试尝试时,都会遇到一系列错误,这些错误大多与async_lock有关(例如Assertion fctx->async_lock failed at libavcodec/pthread_frame.c:155)。我想知道这是否仅仅是OpenCV VideoCapture对象不能一次搜索多个位置……这似乎是合理的。但是,如果是这样,是否有任何方法可以大大加快此操作?
我一直在使用一些不同的资源,包括这个https://nrsyed.com/2018/07/05/multithreading-with-opencv-python-to-improve-video-processing-performance/,它显示了巨大的速度-起伏,但我正在为为什么我在async_lock周围遇到这些错误而感到困惑。仅仅是搜索操作吗?在寻找视频时,找不到任何多线程示例,而只是人们顺序阅读所有帧的示例。
任何在哪里/哪些部件最有可能从多线程中受益(或另一种方法)的任何技巧或指南都将受到欢迎。这是我第一次尝试多线程,因此完全接受我可能错过了一些显而易见的事情!基于此页面(https://www.toptal.com/python/beginners-guide-to-concurrency-and-parallelism-in-python),我对各种可用的选项感到有些不知所措。
谢谢!