首页 > 解决方案 > Python 多处理使 OSX 刹车

问题描述

我有一个程序,它从一副牌中随机选择 13 张牌,并分析牌的形状、点数和其他一些对桥牌游戏很重要的特征。该程序将在大约 5 分钟内选择和分析 10**7 手牌。检查活动监视器显示,在执行期间,CPU(即 6 核处理器)将大约 9% 的时间用于程序,而大约 90% 的时间处于空闲状态。所以它看起来像是多处理的主要候选者,我使用队列创建了一个多处理版本,将信息从每个进程传递回主程序。解决了 IDLE 无法工作的问题后,将进行多处理(我现在使用 PyCharm 运行它),并且在进程完成冻结程序之前对其进行连接,我让它开始工作。

但是,无论我使用多少个进程 5、10、25 或 50,结果总是相同的。CPU 将大约 18% 的时间用于程序,大约 75% 的时间处于空闲状态,执行时间在 10 分钟多一点时增加了一倍多。

谁能解释我如何让进程占用更多的 CPU 时间以及如何让执行时间来反映这一点?以下是该计划的相关部分:

import random
import collections
import datetime
import time

from math import log10
from multiprocessing import Process, Queue


NUM_OF_HANDS = 10**6
NUM_OF_PROCESSES = 25


def analyse_hands(numofhands, q):

#code remove as not relevant to the problem

        q.put((distribution, points, notrumps))


if __name__ == '__main__':

    processlist = []
    q = Queue()

    handsperprocess = NUM_OF_HANDS // NUM_OF_PROCESSES
    print(handsperprocess)
    # Set up the processes and get them to do their stuff
    start_time = time.time()
    for _ in range(NUM_OF_PROCESSES):
        p = Process(target=analyse_hands, args=((handsperprocess, q)))
        processlist.append(p)
        p.start()

    # Allow q to get a few items
    time.sleep(.05)
    while not q.empty():
        while not q.empty():
            #code remove as not relevant to the problem

        # Allow q to be refreshed so allowing all processes to finish before
        # doing a join.  It seems that doing a join before a process is
        # finished will cause the program to lock
        time.sleep(.05)
        counter['empty'] += 1

    for p in processlist:
        p.join()

    while not q.empty():
        # This is never executed as all the processes have finished and q
        # emptied before the join command above.

        #code remove as not relevant to the problem       

    finish_time = time.time()

标签: python-3.xmacosmultiprocessing

解决方案


对于 IDLE 无法正确运行多处理器启动指令的原因,我没有答案,但我相信执行时间加倍的答案在于我正在处理的问题类型。也许其他人可以发表评论,但在我看来,在队列中添加和删除项目所涉及的开销非常高,因此当通过队列传递的数据量与数量相比较小时,性能改进将得到最好的实现获得该数据所需的处理。

在我的程序中,我正在创建和传递 10**7 项数据,我想这是通过队列传递这些项目的开销,这会扼杀通过单独进程获取数据的任何性能改进。通过使用地图,似乎所有 10^7 项数据都需要存储在地图中,然后才能进行任何进一步的处理。这可能会提高性能,具体取决于使用地图和处理大量数据的开销,但目前我将坚持使用我原来的原始单处理代码。


推荐阅读