Python多处理:在变为空之前将多处理队列加满

Python多处理:在变为空之前将多处理队列加满,python,queue,multiprocessing,Python,Queue,Multiprocessing,我试图在Python2.7中创建一个多处理队列,用进程填充到它的maxsize,然后,当有更多的进程尚未放入队列时,将在当前任何进程完成时重新填充队列。我正试图最大限度地提高性能,使队列的大小在PC上是numCores,这样每个核心都在工作(理想情况下CPU将在整个时间内100%使用)。我还试图避免上下文切换,这就是为什么我在任何时候都只希望队列中有这么多人 例如,假设有50个任务要完成,CPU有4个内核,因此队列的大小将为maxsize 4。我们首先用4个进程填充队列,在这4个进程中的任何一个

我试图在Python2.7中创建一个多处理队列,用进程填充到它的maxsize,然后,当有更多的进程尚未放入队列时,将在当前任何进程完成时重新填充队列。我正试图最大限度地提高性能,使队列的大小在PC上是numCores,这样每个核心都在工作(理想情况下CPU将在整个时间内100%使用)。我还试图避免上下文切换,这就是为什么我在任何时候都只希望队列中有这么多人

例如,假设有50个任务要完成,CPU有4个内核,因此队列的大小将为maxsize 4。我们首先用4个进程填充队列,在这4个进程中的任何一个完成后(此时队列中将有3个进程),将生成一个新的进程并发送到队列。它将继续这样做,直到生成并完成所有50项任务

这项任务被证明是困难的,因为我是多处理新手,而且join()函数似乎对我不起作用,因为这会强制执行阻塞语句,直到队列中的所有进程都完成,这不是我想要的

这是我现在的代码:

def queuePut(q, thread):
    q.put(thread)


def launchThreads(threadList, performanceTestList, resultsPath, cofluentExeName):
    numThreads = len(threadList)
    threadsLeft = numThreads
    print "numThreads: " + str(numThreads)
    cpuCount = multiprocessing.cpu_count()
    q = multiprocessing.Queue(maxsize=cpuCount) 
        count = 0
    while count != numThreads:
        while not q.full():
            thread = threadList[numThreads - threadsLeft]
            p = multiprocessing.Process(target=queuePut, args=(q,thread))
            print "Starting thread " + str(numThreads - threadsLeft)
            p.start()
            threadsLeft-=1
            count +=1
        if(threadsLeft == 0):
            threadsLeft+=1
            break
下面是在代码中调用它的地方:

for i in testNames:
            p = multiprocessing.Process(target=worker,args=(i,paths[0],cofluentExeName,))
            jobs.append(p)

launchThreads(jobs, testNames, testDirectory, cofluentExeName)
进程似乎被创建并放入队列,例如,有12个任务和40个内核,输出如下,错误如下:

numThreads: 12
Starting thread 0
Starting thread 1
Starting thread 2
Starting thread 3
Starting thread 4
Starting thread 5
Starting thread 6
Starting thread 7
Starting thread 8
Starting thread 9
Starting thread 10
Starting thread 11

  File "C:\Python27\lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
  File "C:\Python27\lib\multiprocessing\process.py", line 290, in __reduce__
    'Pickling an AuthenticationString object is '
TypeError: Pickling an AuthenticationString object is disallowed for security re
asons
Traceback (most recent call last):
  File "C:\Python27\lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
  File "C:\Python27\lib\multiprocessing\process.py", line 290, in __reduce__
    'Pickling an AuthenticationString object is '
TTypeError: Pickling an AuthenticationString object is disallowed for security r
easons
raceback (most recent call last):
  File "C:\Python27\lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
  File "C:\Python27\lib\multiprocessing\process.py", line 290, in __reduce__
    'Pickling an AuthenticationString object is '
TTypeError: Pickling an AuthenticationString object is disallowed for security r
easons
raceback (most recent call last):
  File "C:\Python27\lib\multiprocessing\queues.py", line 262, in _feed
    send(obj)
  File "C:\Python27\lib\multiprocessing\process.py", line 290, in __reduce__
    'Pickling an AuthenticationString object is '
TypeError: Pickling an AuthenticationString object is disallowed for security re
asons

为什么不使用多处理池来实现这一点

import multiprocessing
pool = multiprocessing.Pool()
pool.map(your_function, dataset) ##dataset is a list; could be other iterable object
pool.close()
pool.join()
multiprocessing.Pool()
可以使用参数
processs=#
指定要启动的作业的数量。如果不指定此参数,它将启动与内核数量相同的作业(因此,如果有4个内核,则启动4个作业)。当一个作业完成时,它将自动启动下一个作业;你不必管理它


多处理:

这是一种使用同步队列的非常奇怪的方式。通常,你把作业放在队列中,而不是工人,工人们使用队列来获得工作。我没有写代码,我相信线程列表实际上就是作业列表。我将要求代码的创建者进行检查。
q.put()
已经自己完成了您想要的大部分工作:只要队列已满(在其定义的最大大小上),
.put()
阻塞。从队列中删除某些内容后,
.put()
将唤醒并添加下一项。不相关,您显示的错误消息一定是由于您没有向我们显示的内容。最好给出一个完整的例子:嘿,蒂姆,好吧,我会尽量减少我的代码,因为这听起来更容易让程序自己阻塞。至于错误消息,我很确定它们与代码有关。。。我没有改变任何事情。是的,我确信MSG是“相关的”。但它们不是由你给我们看的任何东西造成的。如果我们不能运行您发布的代码,任何人都只能瞎猜。我经常使用这种东西,在我的生活中从来没有看到过
AuthenticationString
投诉-代码正在做其他事情,这是真正的原因。你显示的代码只是触发了它,你是救命恩人。我会做的。很乐意帮忙!如果你对此有任何疑问,请告诉我。好的,我确实有一个问题。在我的例子中,我有一个threadList,它是一个已经创建的进程列表。应该作为可移植对象工作,对吗?所以我只是把它作为iterable传递进来,然后我有一个函数runProc,它只是在遍历列表中的线程时启动它们。我将在上面发布更新的代码。但是,当我这样做时,仍然会出现pickle错误。不确定发生了什么。剧本的目标是什么?您试图启动的多个函数实例是什么?该函数的参数是什么(不是launchThreads)?threadList中的每个进程都是一个exe实例,该exe在外部以不同的参数运行。这些作业是在“testNames中的i”代码段上方创建的。exe完全是另一个程序,一个我无法控制的程序。因此,所有这些参数都应该已经传递到threadList中的每个作业中。脚本应该将所有这些实例与所有CPU一起运行到池中,然后在旧实例完成后运行新实例。