1

我正在尝试使用多处理来返回一个列表,但不是等到所有进程都完成,而是从 mp_factorizer 中的一个 return 语句中获得多个返回,如下所示:

None
None
(returns list)

在这个例子中,我使用了 2 个线程。如果我使用 5 个线程,则在列出列表之前将有 5 个 None 返回。这是代码:

def mp_factorizer(nums, nprocs, objecttouse):
    if __name__ == '__main__':
        out_q = multiprocessing.Queue()
        chunksize = int(math.ceil(len(nums) / float(nprocs)))
        procs = []
        for i in range(nprocs):
            p = multiprocessing.Process(
                    target=worker,                   
                    args=(nums[chunksize * i:chunksize * (i + 1)],
                          out_q,
                    objecttouse))
            procs.append(p)
            p.start()

        # Collect all results into a single result dict. We know how many dicts
        # with results to expect.
        resultlist = []
        for i in range(nprocs):
            temp=out_q.get()
            index =0
            for i in temp:
                resultlist.append(temp[index][0][0:])
                index +=1

        # Wait for all worker processes to finish
        for p in procs:
            p.join()
            resultlist2 = [x for x in resultlist if x != []]
        return resultlist2

def worker(nums, out_q, objecttouse):
    """ The worker function, invoked in a process. 'nums' is a
        list of numbers to factor. The results are placed in
        a dictionary that's pushed to a queue.
    """
    outlist = []
    for n in nums:        
        outputlist=objecttouse.getevents(n)
        if outputlist:
            outlist.append(outputlist)   
    out_q.put(outlist)

mp_factorizer 获取项目列表、线程数和工作人员应使用的对象,然后拆分项目列表,以便所有线程获得相同数量的列表,并启动工作人员。然后工作人员使用该对象从给定列表中计算某些内容,并将结果添加到队列中。Mp_factorizer 应该从队列中收集所有结果,将它们合并到一个大列表中并返回该列表。但是 - 我得到了多个回报。

我究竟做错了什么?还是由于 Windows 处理多处理的奇怪方式导致了这种预期的行为?(Python 2.7.3,Windows7 64 位)

编辑:问题是if __name__ == '__main__':. 我在处理另一个问题时发现,请参阅在子进程中使用多处理以获得完整的解释。

4

2 回答 2

1

if __name__ == '__main__'是在错误的地方。一个快速的解决方法是只保护对 mp_factorizer 的调用,就像 Janne Karila 建议的那样:

if __name__ == '__main__':
    print mp_factorizer(list, 2, someobject)

但是,在 Windows 上,主文件将在执行时执行一次 + 每个工作线程执行一次,在这种情况下为 2。所以这将是主线程的总共 3 次执行,不包括代码的受保护部分。

一旦在同一个主线程中进行其他计算,这可能会导致问题,并且至少会不必要地降低性能。即使只有工作函数应该执行几次,在 Windows 中,所有不受if __name__ == '__main__'.

因此解决方案是通过仅在 if __name__ == '__main__'.

但是,如果工作函数在同一个文件中,则需要从该 if 语句中排除它,因为否则它不能被多次调用以进行多处理。

伪代码主线程:

# Import stuff
if __name__ == '__main__':
    #execute whatever you want, it will only be executed 
    #as often as you intend it to
    #execute the function that starts multiprocessing, 
    #in this case mp_factorizer()
    #there is no worker function code here, it's in another file.

即使整个主进程都受到保护,worker函数仍然可以启动,只要它在另一个文件中。

伪代码主线程,带有worker函数:

# Import stuff
#If the worker code is in the main thread, exclude it from the if statement:
def worker():
    #worker code
if __name__ == '__main__':
    #execute whatever you want, it will only be executed 
    #as often as you intend it to
    #execute the function that starts multiprocessing, 
    #in this case mp_factorizer()
#All code outside of the if statement will be executed multiple times
#depending on the # of assigned worker threads.

有关可运行代码的详细说明,请参阅在子进程中使用多处理

于 2013-01-31T13:05:08.553 回答
0

你的if __name__ == '__main__'陈述在错误的地方。将它放在print语句周围以防止子进程执行该行:

if __name__ == '__main__':
    print mp_factorizer(list, 2, someobject)

现在你有了ifinside mp_factorizer,它使函数None在子进程中调用时返回。

于 2013-01-30T11:00:03.047 回答