tom*_*wel 3 python multithreading memory-management image-processing out-of-memory
我正在使用多线程来处理图像。
它在我有足够内存的计算机上运行良好(处理大量图像时增加2~3 GB),但我的服务器只有1GB内存,代码无法正常运行。
有时以 结尾Segmentation fault,有时:
Exception in thread Thread-13:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "passportRecognizeNew.py", line 267, in doSomething
...
Run Code Online (Sandbox Code Playgroud)
代码:
import threading
def doSomething(image):
# picture processing code
print("processing over")
threads = []
for i in range(20):
thread = threading.Thread(target=doSomething, args=("image",))
threads.append(thread)
for t in threads:
t.setDaemon(True)
t.start()
t.join()
print("All over")
Run Code Online (Sandbox Code Playgroud)
如何解决这个问题或有什么方法可以控制内存使用?
我认为你从错误的角度看待这个问题。你的代码启动了n 个线程。然后,这些线程执行您为它们定义的工作。
如果这项工作需要他们分配大量内存 - 该上下文“外部”的任何内容应该对此做什么?应该发生什么?是否应该杀死一些线程?是否应该在 C 代码深处的某处malloc……不发生……然后呢?
我想说的是:你的问题很可能是你只是启动了太多的线程。
因此,答案是:不要在破坏它们之后尝试修复它们- 最好确保您根本没有破坏它们:
除此之外:这是非常常见的模式。开发人员正在开发一台“强大”的机器;他隐含地假设运行他的产品的任何目标系统都将具有相同或更好的特性。但这根本不是真的。
换句话说:当您不知道代码运行时的硬件是什么样子时,那么只有一件合理的事情要做:首先获取这些知识。然后根据真实数据做不同的事情。
在GhostCat 的帮助下,我使用以下代码来解决内存使用问题。
import Queue
import threading
import multiprocessing
import time
import psutil
class ThreadSomething(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
# check available memory
virtualMemoryInfo = psutil.virtual_memory()
availableMemory = virtualMemoryInfo.available
print(str(availableMemory/1025/1024)+"M")
if availableMemory > MEMORY_WARNING:
# image from queue
image = self.queue.get()
# do something
doSomething(image)
# signals to queue job is done
self.queue.task_done()
else:
print("memory warning!")
def doSomething(image):
# picture processing code, cost time and memory
print("processing over")
# After testing, there seems no use to create threads more than CPU_COUNT,
# execution time is not reduce.
CPU_COUNT = multiprocessing.cpu_count()
MEMORY_WARNING = 200*1024*1024 # 200M
images = ["1.png", "2.png", "3.png", "4.png", "5.png"]
queue = Queue.Queue()
def main():
# spawn a pool of threads, and pass them queue instance
for i in range(CPU_COUNT):
t = ThreadSomething(queue)
t.setDaemon(True)
t.start()
# populate queue with data
for image in images:
queue.put(image)
# wait on the queue until everything has been processed
queue.join()
start = time.time()
main()
print 'All over. Elapsed Time: %s' % (time.time() - start)
Run Code Online (Sandbox Code Playgroud)
我使用psutil模块来获取可用内存。
参考代码:yosemitebandit/ibm_queue.py
我的问题中的代码存在创建线程超过CPU_COUNT.