首页 > 解决方案 > Python多处理奇怪的输出

问题描述

所以我一直在尝试使用多处理优化我的程序,以便它更快地处理信息,但我得到了一些非常奇怪的结果。

代码如下:

from random import randint
import multiprocessing
import time

t = time.time()

def dice_calc(rolls):
    mutex.acquire()
    global wins
    global loss
    while rolls > 0:

        dice1 = randint(1, 6)
        dice2 = randint(1, 6)

        if dice1+dice2 == 11 or dice1+dice2 == 7 or dice1 == dice2:
            wins += 1

        else:
            loss += 1

        rolls -= 1
    mutex.release()


mutex = multiprocessing.Lock()
wins = 0
loss = 0
rolls = 1000000

if __name__ == "__main__":
    p1 = multiprocessing.Process(target=dice_calc, args=(rolls/4,))
    p2 = multiprocessing.Process(target=dice_calc, args=(rolls/4,))
    p3 = multiprocessing.Process(target=dice_calc, args=(rolls/4,))
    p4 = multiprocessing.Process(target=dice_calc, args=(rolls/4,))

    p1.start()
    p2.start()
    p3.start()
    p4.start()

    p1.join()
    p2.join()
    p3.join()
    p4.join()

    print(wins)
    print(loss)
    #percentage = (wins / (wins + loss)) * 100
    #print("Calculated percentage of a roll fulfilling requirements are:", round(percentage, 2), "%")


print(round((time.time()-t), 3))

目的是基本上找出两个骰子的总和为 7、11 或相同的机会是多少。我已经用线程模块尝试了同样的代码,效果很好(在性能方面没有真正的好处,但是嘿,它有效)

让我大吃一惊的是这个版本使用多处理的输出:

0.012
0.012
0.011
0.012
0
0
0.764

打印的前 4 个值让我很困惑。不应该有任何东西使这些输出成为可能,这些值也因运行而异。我相信它们起源于 p1、p2、p3 和 p4。

这之后的两个值不应为 0(这些值表示获胜和失败的数量,它们加起来应该是 1 000 000)

最后一个值是唯一有意义的值。它基本上只是一个计时器来检查程序运行了多长时间。

如果有人对我如何使这项工作有任何见解,我很想听听。

标签: pythonpython-3.xmultithreading

解决方案


您看到这些奇怪值的原因是因为您的陈述:

print(round((time.time()-t), 3))

如果您缩进该行,它将仅在名为__main__.

发生这种情况的原因是因为在创建.Python 时Process(),Python 在具有不同模块名称的新实例下执行该进程。因此,当函数执行完成时dice_calcs返回并继续执行脚本,最终到达该行。

同样,您不会从您的胜利和损失变量中获得任何正确的值,因为它们存在于不同的流程中。当每个 Process 引用该变量时,它引用的是它自己的该变量的副本,而不是存在于__main__.

要从其他模块中获取这些变量的实际值,您需要实现某种方式来跨模块进行通信。

Queue使用模块中的 a之类的东西,queue您可以执行以下操作:(注意:我添加的代码由 包围#######

from random import randint
import multiprocessing
import time

t = time.time()

def dice_calc(rolls, q):
    mutex.acquire()
    global wins
    global loss
    while rolls > 0:

        dice1 = randint(1, 6)
        dice2 = randint(1, 6)

        if dice1+dice2 == 11 or dice1+dice2 == 7 or dice1 == dice2:
            wins += 1

        else:
            loss += 1

        rolls -= 1

    ########
    #return wins and losses to queue
    q.put((wins,loss))
    ########
    mutex.release()


mutex = multiprocessing.Lock()
wins = 0
loss = 0
rolls = 1000000

if __name__ == "__main__":
    ########
    #create a multiprocessing.Queue() instance that spans across Processes
    q = multiprocessing.Queue()
    ########

    p1 = multiprocessing.Process(target=dice_calc, args=(rolls/4,q))
    p2 = multiprocessing.Process(target=dice_calc, args=(rolls/4, q))
    p3 = multiprocessing.Process(target=dice_calc, args=(rolls/4, q))
    p4 = multiprocessing.Process(target=dice_calc, args=(rolls/4, q))
    p1.start()
    p2.start()
    p3.start()
    p4.start()

    ########
    #Get wins and losses from the queue
    for _ in range(4):
        item = q.get(timeout=5000)
        wins = wins + item[0]
        loss = loss + item[1]
    ########    

    p1.join()
    p2.join()
    p3.join()
    p4.join()

    print(wins)
    print(loss)
    #percentage = (wins / (wins + loss)) * 100
    #print("Calculated percentage of a roll fulfilling requirements are:", round(percentage, 2), "%")

    ########
    #Added an indent to this line
    print(round((time.time()-t), 3))
    ########

推荐阅读