Python Multiprocessing输出整个程序

时间:2016-07-10 19:53:02

标签: python multiprocessing

我通常不会在互联网上提问,也不是一个非常优秀的程序员,但我一直在努力解决这个问题,但我无法理解为什么它不起作用。我正在尝试做一些我认为可以在多个线程中进行的数学运算,下面的代码显示了我尝试输出每个工作人员完成后的答案。我已经意识到这是相当低效的,工人不得不等待其他人,当然还有许多其他问题,但我只想让这个版本正常工作。非常感谢任何帮助

我正在运行Windows 10,python 3.5,包含4个内核和8个线程,并通过控制台运行该程序,

这是我的代码:

import math
from multiprocessing import Process, Lock
import time

lowMult = 0
highMult = 0
dist = "ERROR!"
print("Welcome to this maths test program")
print("We will be testing the nature of closest whole multiple pairs")
print("this test will run for all values 900000 to 900100")
print("press enter to begin")
input()

def worker(name, l, num):
    l.acquire()
    print (name, "Starting")
    l.release()
    found = False
    test = math.sqrt(num)
    if (test % 1) == 0:
        l.acquire()
        print(num, "=", int(test), "*", int(test), "0", "SQRT!")
        l.release()

    else:
        test = int(test)
        for lowMult in range(test, 0, -1):
                for highMult in range(test, (num +1)):
                    if (lowMult * highMult) == num:
                        found = True
                        dist = highMult - lowMult
                        break

                if found:
                    break

        l.acquire()
        if lowMult == 1:
            print(num, "=", lowMult, "*", highMult, dist, "PRIME!")
        else:
            print(num, "=", lowMult, "*", highMult, dist)

        print (name, "Exiting")
        l.release()

if __name__ == '__main__':
    lock = Lock()
    jobs = []
    num0 = 900000
    num1 = 900001
    num2 = 900002
    num3 = 900003
    for num in range(1, 100):
        thread1 = Process(name='worker 1', target=worker, args=("worker 1", lock, num0,))
        jobs.append(thread1)
        thread1.start()

        thread2 = Process(name='worker 2', target=worker, args=("worker 2", lock, num1,))
        jobs.append(thread2)
        thread2.start()

        thread3 = Process(name='worker 3', target=worker, args=("worker 3", lock, num2,))
        jobs.append(thread3)
        thread3.start()

        thread4 = Process(name='worker 4', target=worker, args=("worker 4", lock, num3,))
        jobs.append(thread4)
        thread4.start()

        thread1.join()
        thread2.join()
        thread3.join()
        thread4.join()

        num0 += 4
        num1 += 4
        num2 += 4
        num3 += 4

        while True:
            if thread1.is_alive() & thread2.is_alive() & thread3.is_alive() & thread4.is_alive():
                time.sleep(2)
            else:
                input()
                break
我没有得到任何东西,但我读到这会发生这种情况,但在控制台中,我得到的是前几个打印命令,而不是我期待的多次:

print("Welcome to this maths test program")
print("We will be testing the nature of closest whole multiple pairs")
print("this test will run for all values 900000 to 900100")
print("press enter to begin")

我在另一个输入提示之前得到了其中的四个,此时第一次计算已经完成,但似乎没有并行,第二次从未完成。从我的CPU使用情况来看,它似乎永远不会启动,但程序不会终止。我不知道发生了什么。

修改

似乎实际的计算问题在于我使用input()和'name'的定义。 .join()的一些其他问题导致我将其删除,.is_alive()检查已修复为使用OR代替AND。不过,当我在python 3.5中运行此代码并获得一个Windows控制台时,我无意中得到了此代码的四个副本:

Welcome to this maths test program
We will be testing the nature of closest whole multiple pairs
this test will run for all values 900000 to 900100
press enter to begin

这就是我目前正在努力解决的问题。

3 个答案:

答案 0 :(得分:0)

如果您使用的是Python 2.7,那么input()可能会“崩溃”,因为它根据文档“等同于eval(raw_input(prompt))”: https://docs.python.org/2/library/functions.html#input

你可以使用raw_input来阅读用户输入(实际上我没有看到在这里要求按键的要点)。

另一个问题是变量name未在worker函数中定义。

此外,thread1.is_alive() & thread2.is_alive() & thread3.is_alive() & thread4.is_alive()应始终评估为False

删除所有input()之后,得到的输出是(使用Python 2.7)以下内容,这似乎是我所理解的预期结果:

Welcome to this maths test program
We will be testing the nature of closest whole multiple pairs
this test will run for all values 900000 to 900100
press enter to begin
(900000, 'Starting')
(900001, 'Starting')
(900002, 'Starting')
(900003, 'Starting')
(900000, '=', 900, '*', 1000, 100)
('worker 1', 'Exiting')
(900003, '=', 611, '*', 1473, 862)
('worker 4', 'Exiting')
(900002, '=', 2, '*', 450001, 449999)
('worker 3', 'Exiting')
(900001, '=', 1, '*', 900001, 900000, 'PRIME!')
('worker 2', 'Exiting')
(900004, 'Starting')
(900005, 'Starting')
(900006, 'Starting')
(900007, 'Starting')
(900006, '=', 6, '*', 150001, 149995)
('worker 3', 'Exiting')
(900004, '=', 28, '*', 32143, 32115)
('worker 1', 'Exiting')
(900007, '=', 1, '*', 900007, 900006, 'PRIME!')
('worker 4', 'Exiting')
(900005, '=', 5, '*', 180001, 179996)
('worker 2', 'Exiting')
...

答案 1 :(得分:0)

第一个工作人员在持有锁时因name没有被定义而崩溃。这可以防止任何其他工人提供他们的产出,并且由于他们从未完成,它也阻止了主要过程启动下一轮工人。

要解决此特定问题(而不是任何较大的设计问题),您应该将锁用作上下文管理器,而不是显式调用acquirerelease。这将使它在发生异常时自动解锁:

with l:
    print(num, "=", int(test), "*", int(test), "0", "SQRT!")

with l:
    if lowMult == 1:
        print(num, "=", lowMult, "*", highMult, dist, "PRIME!")
    else:
        print(num, "=", lowMult, "*", highMult, dist)

    print (name, "Exiting") # this still causes an exception, but it will no longer deadlock!

答案 2 :(得分:0)

好像我的大多数问题都得到了回答。我现在将努力实际优化代码,以便在我的原始问题得到解决后高效运行。似乎工作人员开始运行父程序中的所有代码,并因此阻止他们四次打印介绍性文本,我在介绍打印之前包含了if __name__ == __main__:。它还解释了input()导致问题开始的原因。很明显,我遇到的问题的核心在于我对工人的工作方式缺乏了解,因为我认为他们只运行了他们被指定的功能代码。

感谢所有回答的人,你们非常耐心和乐于助人,我希望有一天,一旦我的技能达到足够的水平,我就可以帮助他人