Python的多进程队列是否有序?

4

如果这很显然,请原谅我,但从文档中我无法确定在使用队列时输出是否有序。也就是说,如果输入是[1, 2, 3],那么输出会是f(1)、f(2)、f(3),还是可能是无序的?

编辑:我知道输入按照先进先出(FIFO)的方式处理。但是,FIFO检索是否必然保证结果也以有序的方式返回?

5个回答

10
不,它们将按照完成的顺序进入队列,而不是按照启动的顺序。这意味着,如果您在启动进程时有特定的顺序要求,它们可能会按照该顺序完成,也可能不会。如果顺序对您很重要,您应该在队列中返回启动顺序以及结果,例如作为元组queue.put((order, result))。下面是一个示例,显示您从队列中得到的随机顺序(仍然是FIFO)。
import multiprocessing
import random
import time

def square(x, queue):
    # Sleep for a value between 0 and 1. 
    time.sleep(random.random())
    queue.put(x**2)

queue = multiprocessing.Queue()

for i in range(10):
    process = multiprocessing.Process(target = square, args = (i, queue))
    process.start()

results = []
for i in range(10):
    results.append(queue.get())

print (results)

这给了我 [25, 16, 9, 0, 36, 64, 81, 1, 49, 4]。

假设您的任务相对简单,我总是更喜欢使用Python的Pool功能及其相应的pool.map()函数,该函数可以保证输出顺序与输入顺序相同。


询问者正在寻求用于多线程目的的“正常”队列行为。因此,Yassine Faris的答案与此问题相关。但是,您对multiprocessing.Queue的描述是正确的。 - Amuoeba

4

我有一个问题需要把所有的 multiprocessing.Queue 替换成 m.Queue,其中 m = multiprocess.Manager(),这样所有的队列都会被排序。然而,我无法通过简单的示例进行复现。

我不太清楚原因,但如果有人因为他们的队列无序而来到这里,我建议尝试一下这个方法。


1
这个答案应该被接受为正确的。使用经理类中的队列使队列有序。谢谢! - anlgrses

2

队列

在先进先出(FIFO)队列中,首先添加的任务是首先检索到的。

class Queue.Queue(maxsize=0) FIFO队列的构造器。

是的,多进程队列是FIFO(先进先出)的。


FIFO检索是否必然保证结果也按顺序返回? - Teknophilia

0
我发现多进程使用队列时,即使设置maxsize=1,也会出现非常意外的排序问题。官方文档证实了我的实验结果:
如果多个进程将对象加入队列,则可能在另一端收到的对象是无序的。但同一进程放入队列的对象在彼此之间始终是按预期顺序排列的。
当访问manager Queue的进程数量增加时,我遇到了同样的问题。
从我的实验中,我发现管理这种情况的最佳方式是使用JoinableQueue,并手动调用task_done()来处理队列获取的代码的末尾,特别是在我的情况下,需要操作两个输入和输出的队列。例如:JoinableQueue1.get() - 处理数据 - JoinableQueue2.put() - 然后time.sleep(0.1)和JoinableQueue1.task_done()。如果使用JoinableQueue.join()方法,则还可以更好地从被多个进程使用的共享队列中获取FIFO。

0

多进程队列从未失序。文档中明确提到了三种类型:FIFOLIFO和优先级队列(一种自定义顺序的方式)。默认顺序即 class Queue.Queue 使用 FIFO

在FIFO队列中,添加的第一个任务是第一个被检索到的。

因此,考虑到这一点,是的,多进程队列维护顺序。


每次我使用多进程时,它都会随机执行。例如,如果每个进程都应该从数字1到10的数字列表中选择一个整数,则执行是完全随机的,也就是说,第一个输出可能来自5,下一个来自2等等。我认为这就是问题所在。 - West

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接