Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 为什么“多重处理.队列.get”这么慢?_Python 3.x_Message Queue_Python Multiprocessing - Fatal编程技术网

Python 3.x 为什么“多重处理.队列.get”这么慢?

Python 3.x 为什么“多重处理.队列.get”这么慢?,python-3.x,message-queue,python-multiprocessing,Python 3.x,Message Queue,Python Multiprocessing,我需要帮助理解多处理.Queue。我面临的问题是,与对queue.put(…)和队列缓冲区(deque)的调用相比,从queue.get(…)获取结果的速度要慢得多 这个泄漏的抽象让我调查了队列的内部。它直截了当地告诉了我,这似乎也足够简单,我无法用它来解释我所看到的行为。我还读到队列使用管道,但在源代码中似乎找不到 我把它归结为一个再现问题的最小示例,并在下面指定了一个可能的输出 import threading import multiprocessing import queue q =

我需要帮助理解
多处理.Queue
。我面临的问题是,与对
queue.put(…)
和队列缓冲区(deque)的调用相比,从
queue.get(…)
获取结果的速度要慢得多

这个泄漏的抽象让我调查了队列的内部。它直截了当地告诉了我,这似乎也足够简单,我无法用它来解释我所看到的行为。我还读到队列使用管道,但在源代码中似乎找不到

我把它归结为一个再现问题的最小示例,并在下面指定了一个可能的输出

import threading
import multiprocessing
import queue

q = None
def enqueue(item):
    global q
    if q is None:
        q = multiprocessing.Queue()
        process = threading.Thread(target=worker, args=(q,))  # or multiprocessing.Process Doesn't matter
        process.start()
    q.put(item)
    print(f'len putted item: {len(item)}. qsize: {q.qsize()}. buffer len: {len(q._buffer)}')


def worker(local_queue):
    while True:
        try:
            while True:  # get all items
                item = local_queue.get(block=False)
                print(f'len got item: {len(item)}. qsize: {q.qsize()}. buffer len: {len(q._buffer)}')
        except queue.Empty:
            print('empty')


if __name__ == '__main__':
    for i in range(1, 100000, 1000):
        enqueue(list(range(i)))
输出:

empty
empty
empty
len putted item: 1. qsize: 1. buffer len: 1
len putted item: 1001. qsize: 2. buffer len: 2
len putted item: 2001. qsize: 3. buffer len: 1
len putted item: 3001. qsize: 4. buffer len: 2
len putted item: 4001. qsize: 5. buffer len: 3
len putted item: 5001. qsize: 6. buffer len: 4
len putted item: 6001. qsize: 7. buffer len: 5
len putted item: 7001. qsize: 8. buffer len: 6
len putted item: 8001. qsize: 9. buffer len: 7
len putted item: 9001. qsize: 10. buffer len: 8
len putted item: 10001. qsize: 11. buffer len: 9
len putted item: 11001. qsize: 12. buffer len: 10
len putted item: 12001. qsize: 13. buffer len: 11
len putted item: 13001. qsize: 14. buffer len: 12
len putted item: 14001. qsize: 15. buffer len: 13
len putted item: 15001. qsize: 16. buffer len: 14
len got item: 1. qsize: 15. buffer len: 14
len putted item: 16001. qsize: 16. buffer len: 15
len putted item: 17001. qsize: 17. buffer len: 16
len putted item: 18001. qsize: 18. buffer len: 17
len putted item: 19001. qsize: 19. buffer len: 18
len putted item: 20001. qsize: 20. buffer len: 19
len putted item: 21001. qsize: 21. buffer len: 20
len putted item: 22001. qsize: 22. buffer len: 21
len putted item: 23001. qsize: 23. buffer len: 22
len putted item: 24001. qsize: 24. buffer len: 23
len putted item: 25001. qsize: 25. buffer len: 24
len putted item: 26001. qsize: 26. buffer len: 25
len putted item: 27001. qsize: 27. buffer len: 26
len putted item: 28001. qsize: 28. buffer len: 27
len got item: 1001. qsize: 27. buffer len: 27
empty
len putted item: 29001. qsize: 28. buffer len: 28
empty
empty
empty
len got item: 2001. qsize: 27. buffer len: 27
empty
len putted item: 30001. qsize: 28. buffer len: 28
我希望您注意以下结果:插入元素28001后,worker发现队列中没有元素,而还有几十个元素。因为同步,我可以只得到所有的,除了一些。但它只找到了两个

这种模式还在继续

这似乎与我放在队列上的对象的大小有关。对于小型对象,例如
i
,与
列表(范围(i))
相反,此问题不会出现。但所讨论的对象的大小仍然是千字节,几乎不足以体现如此显著的延迟(在我的真实非最小示例中,这很容易就花了几分钟)

我的问题是:如何在Python中的进程之间共享(不那么)大量数据?
另外,我想知道队列的内部实现中,这种惰性是从哪里来的

我也遇到了这个问题。我正在发送大的numpy数组(~300MB),而mp.queue.get()的速度非常慢

在研究了mp.Queue的python2.7源代码之后,我发现最慢的部分(在类unix系统上)是中的
\u conn\u recvall()
,但我没有深入研究

为了解决这个问题,我构建了一个实验包

这个项目的灵感来自于multiprocessing.Queue(mp.Queue)的使用。由于管道的速度限制(在类Unix系统上),对于大型数据项,mp.Queue速度较慢

通过mp.Queue处理进程间传输,FMQ实现了一个窃取者线程,一旦任何项目可用,它就会从mp.Queue中窃取一个项目,并将其放入Queue.Queue。然后,使用者进程可以立即从Queue.Queue获取数据

加速基于这样的假设:生产者和消费者过程都是计算密集型的(因此需要多处理),数据量大(例如>50 227x227个图像)。否则,使用多处理的mp.Queue或使用线程的Queue.Queue就足够了

Queue与mp.Queue一样易于使用


请注意,由于此项目尚处于早期阶段,仍有一些问题。

对于未来的读者,您还可以尝试使用:

q = multiprocessing.Manager().Queue()
而不仅仅是

q = multiprocessing.Queue()
我还没有完全提炼和理解这种行为背后的机制,但我读过的一篇文章声称它是关于:

“将大型项目推到队列上时,这些项目基本上是 缓冲,尽管队列的put函数立即返回。“

作者继续解释了更多关于它的内容和修复方法,但对我来说,补充说经理做的很简单

更新:我认为这有助于解释这个问题


在公认的答案中提到的FMQ也是Python2独有的,这也是我觉得这个答案有一天可能会帮助更多人的原因之一。

而且我是Python新手,因此,我愿意接受注释你找到解决方案了吗?我的队列很慢,尽管我只在上面放了三个整数的元组。一个相关的so问题:用multiprocessing.Manager()替换multiprocessing.queue()。queue()为我解决了这个问题。