如何结合python多处理和管道技术?

问题描述 投票:0回答:1

您好我是新来的,我想问一些问题。现在我正在使用python多处理来处理队列中的数据。示例I有3个函数来计算队列中的数据,而队列中我有3个数据。是否可以将管道技术与多处理结合使用以使其更快?

在这段代码中,我尝试使用多处理队列在多处理进程之间进行通信,并使用Lock来防止其他进程在从前一个函数完成之前使用队列中的数据。但它


from multiprocessing import Process, current_process, cpu_count, Queue, Pool, Lock, Array
from threading import Thread, current_thread
import time
import os

def a(pid, q1, q2, lock):
    while not q1.empty():
        data = q1.get()
        print("data from q1 is %s" % data)
        # for i in range(1000000):
        new_data = data*2
        lock.acquire()
        q2.put(new_data)
        print(pid)
        lock.release()

def b(pid, q2, q3, lock):
    while not q2.empty():
        data = q2.get()
        print("data from q2 is %s" % data)
        # for i in range(1000000):
        lock.acquire()
        new_data = data*3
        q3.put(new_data)
        print(pid)
        lock.release()

def c(pid, q3, q4, lock):
    while not q3.empty():
        data = q3.get()
        print("data from q3 is %s" % data)
        # for i in range(1000000):
        lock.acquire()
        new_data = data*4
        q4.put(new_data)
        print(pid)
        lock.release()

if __name__ == "__main__":

    number = [1,2,3]

    lock = Lock()

    q1 = Queue()
    q2 = Queue()
    q3 = Queue()
    q4 = Queue()

    for data in number:
        q1.put(data)

    p1 = Process(target=a,args=(1, q1, q2, lock))
    p2 = Process(target=b,args=(2, q2, q3, lock))
    p3 = Process(target=c,args=(3, q3, q4, lock))

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

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

    for i in range(q4.qsize()):
        print(q4.get())

我希望管道的顺序应该像这个f1 |一样执行f1 f2 | f1 f2 f3 | f2 f3 |如果我的信息正确,f3和队列中的解决方案是24,48,72。我尽力解释这些事情应该如何运作,因为这是我第一次在stackoverflow中提问并且我的英语技能不好而且我真的需要帮助。

python parallel-processing pipeline
1个回答
1
投票

您的问题是您使用q.empty()来终止循环。其中一些Queues在开始时将是空的,那些Process将太早终止。你需要一种不同的技术让p2p3进程知道什么时候退出。

以下是对代码的修改,它使用None作为队列中的标志,以便在完成时发出信号:

from multiprocessing import Process, current_process, cpu_count, Queue, Pool, Lock, Array
from threading import Thread, current_thread
import time
import os

def a(pid, q1, q2, lock):
    while not q1.empty():
        data = q1.get()
        print("data from q1 is %s" % data)
        # for i in range(1000000):
        new_data = data*2
        lock.acquire()
        q2.put(new_data)
        print(pid)
        lock.release()
    q2.put(None)

def b(pid, q2, q3, lock):
    while True:
        data = q2.get()
        if data is None:
            q3.put(None)
            return
        print("data from q2 is %s" % data)
        # for i in range(1000000):
        lock.acquire()
        new_data = data*3
        q3.put(new_data)
        print(pid)
        lock.release()

def c(pid, q3, q4, lock):
    while True:
        data = q3.get()
        if data is None:
            return
        print("data from q3 is %s" % data)
        # for i in range(1000000):
        lock.acquire()
        new_data = data*4
        q4.put(new_data)
        print(pid)
        lock.release()

if __name__ == "__main__":

    number = [1,2,3]

    lock = Lock()

    q1 = Queue()
    q2 = Queue()
    q3 = Queue()
    q4 = Queue()

    for data in number:
        q1.put(data)

    p1 = Process(target=a,args=(1, q1, q2, lock))
    p2 = Process(target=b,args=(2, q2, q3, lock))
    p3 = Process(target=c,args=(3, q3, q4, lock))

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

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

    for i in range(q4.qsize()):
        print(q4.get())

此外,你实际上并不需要Lock。根据documentation

队列模块实现多生产者,多消费者队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。此模块中的Queue类实现了所有必需的锁定语义。

© www.soinside.com 2019 - 2024. All rights reserved.