如何控制多线程中的内存使用?
How to control memory usage in multithreading?
我正在使用多线程处理图像。
在我有足够内存的电脑上运行良好(处理大量图像时增加2~3GB),但我的服务器只有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
...
代码:
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")
如何解决这个问题或控制内存使用的任何方式?
我认为你从错误的角度看待这个问题。您的代码启动了 n 个线程。这些线程然后执行您为它们定义的 work。
如果这项工作需要他们分配大量内存 - 该上下文的任何 "outside" 应该对此做什么?应该发生什么?一些线程应该被杀死吗?应该在某个地方,在 C 代码的深处 malloc
... 不会发生 ... 然后?
我的意思是:您的问题很可能是因为您只是启动了太多 的线程。
因此答案是:在你弄坏了东西之后,不要试图修复它们 - 最好确保你根本不弄坏它们:
- 仔细分析,了解您的申请;所以你可以评估一个线程需要多少内存来完成它的"work"
- 然后更改您的 "main" 程序以查询它 运行 所在的硬件(例如:检查可用内存和可用物理 CPU 的数量)
- 并根据该评估,启动应该在上述硬件详细信息下工作的线程数
除此之外:这是非常常见的模式。开发人员有一台 "powerful" 机器正在使用;并且他隐含地假设任何目标系统 运行 他的产品将具有相同或更好的特性。这根本不是真的。
换句话说:当您不知道硬件看起来像您的代码时 运行 打开时 - 那么只有 一个 合理的事情要做:首先获得这些知识。之后根据真实数据做不同的事情。
在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)
我使用 psutil 模块来获取可用内存。
参考代码:yosemitebandit/ibm_queue.py
我问题中的代码存在创建线程超过CPU_COUNT
的问题。
我正在使用多线程处理图像。
在我有足够内存的电脑上运行良好(处理大量图像时增加2~3GB),但我的服务器只有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
...
代码:
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")
如何解决这个问题或控制内存使用的任何方式?
我认为你从错误的角度看待这个问题。您的代码启动了 n 个线程。这些线程然后执行您为它们定义的 work。
如果这项工作需要他们分配大量内存 - 该上下文的任何 "outside" 应该对此做什么?应该发生什么?一些线程应该被杀死吗?应该在某个地方,在 C 代码的深处 malloc
... 不会发生 ... 然后?
我的意思是:您的问题很可能是因为您只是启动了太多 的线程。
因此答案是:在你弄坏了东西之后,不要试图修复它们 - 最好确保你根本不弄坏它们:
- 仔细分析,了解您的申请;所以你可以评估一个线程需要多少内存来完成它的"work"
- 然后更改您的 "main" 程序以查询它 运行 所在的硬件(例如:检查可用内存和可用物理 CPU 的数量)
- 并根据该评估,启动应该在上述硬件详细信息下工作的线程数
除此之外:这是非常常见的模式。开发人员有一台 "powerful" 机器正在使用;并且他隐含地假设任何目标系统 运行 他的产品将具有相同或更好的特性。这根本不是真的。
换句话说:当您不知道硬件看起来像您的代码时 运行 打开时 - 那么只有 一个 合理的事情要做:首先获得这些知识。之后根据真实数据做不同的事情。
在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)
我使用 psutil 模块来获取可用内存。
参考代码:yosemitebandit/ibm_queue.py
我问题中的代码存在创建线程超过CPU_COUNT
的问题。