您好我是新来的,我想问一些问题。现在我正在使用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中提问并且我的英语技能不好而且我真的需要帮助。
您的问题是您使用q.empty()
来终止循环。其中一些Queues
在开始时将是空的,那些Process
将太早终止。你需要一种不同的技术让p2
和p3
进程知道什么时候退出。
以下是对代码的修改,它使用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类实现了所有必需的锁定语义。