【问题标题】:How to control memory usage in multithreading?如何控制多线程中的内存使用?
【发布时间】:2017-07-07 09:01:09
【问题描述】:

我正在使用多线程来处理图像。

它在我有足够内存的电脑上运行良好(处理许多图像时增加 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
  ...

代码:

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")

如何解决这个问题或任何控制内存使用的方法?

【问题讨论】:

    标签: python multithreading image-processing memory-management out-of-memory


    【解决方案1】:

    我认为您从错误的角度看待这个问题。您的代码启动了 n 个线程。然后这些线程执行您为它们定义的work

    如果这项工作需要他们分配大量内存 - 该上下文“外部”的任何内容应该如何处理?应该发生什么?是否应该杀死一些线程?应该在某个地方,在 C 代码的深处,malloc ...不会发生...然后?

    我的意思是:您的问题很可能是您启动了太多这些线程。

    因此答案是:不要尝试在您破坏它们之后修复它们 - 最好确保您根本不破坏它们:

    • 仔细分析,以了解您的应用程序;这样您就可以评估单个线程需要多少内存才能完成其“工作”
    • 然后更改您的“主”程序以查询它正在运行的硬件(例如:检查可用内存和可用物理 CPU 的数量)
    • 并根据该评估,在上述硬件详细信息的情况下启动应该工作的线程数

    除此之外:这是非常常见的模式。开发人员正在开发一台“强大”的机器;他隐含地假设任何运行他的产品的目标系统都将具有相同或更好的特性。这根本不是真的。

    换句话说:当您不知道您的代码在硬件上运行时的样子 - 那么只有一个合理的事情可以做:首先获得这些知识。之后根据真实数据做不同的事情。

    【讨论】:

    • 感谢列表让我知道从哪里开始。
    【解决方案2】:

    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的问题。

    【讨论】:

    • 非常好的自我回答!
    猜你喜欢
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多