我试图在python中学习多处理。
我想要发生的是随着时间的推移x增加,然后当我点击'输入'它会随着时间的推移而减少,我可以继续按下Enter键从增加切换到减少。
到目前为止,我所做的一切都是
import time
from multiprocessing import Pool
def f(x):
return (x+1)
def f1(x):
return (x-1)
if __name__ == '__main__':
pool = Pool(processes=2)
x=0
while x<100:
x = pool.apply_async(f, [10])
time.sleep(0.05)
我无法查看文档,因为他们没有提供明确的示例。 请帮忙我不知道
答案 0 :(得分:2)
汇总了一个例子来给你一些想法。
#!/usr/bin/python3
import time
from multiprocessing import Pool, Manager
from threading import Thread
NUM_PROCESSES = 4
def consumer(q):
out = []
while True:
val = q.get()
if val is None:
#poison pill
break
#doing some work here
time.sleep(0.01)
out.append(val)
return out
def producer(queue):
flip = True
val = 5
def flipper():
nonlocal flip
input('enter to flip it!')
while True:
flip = not flip
txt = 'up' if flip else 'down'
input('val is {}, now counting {}'.format(val, txt))
t = Thread(target=flipper, args=(), daemon=True)
t.start()
while val > 0:
for _ in range(NUM_PROCESSES):
queue.put(val)
val = val + (1 if flip else -1)
time.sleep(0.2)
print()
print('hit zero, shutting down.')
for _ in range(NUM_PROCESSES):
#poison pills
queue.put(None)
if __name__ == '__main__':
pool = Pool(processes=NUM_PROCESSES)
m = Manager() # N.B.: multiprocessing.Queue doesn't work with Pool.apply_async
q = m.Queue()
results = pool.apply_async(consumer, args=(q,))
producer(q) # running in main thread because I'm lazy
print(results.get())
输出:
ben@nixbox:~$ python3 multithread.py
enter to flip it!
val is 13, now counting down
val is 4, now counting up
val is 8, now counting down
hit zero, shutting down.
[5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1]
原始代码的设置方式,并行化并没有多大意义。所以我改用生产者/消费者范例:你的制作人生产&#34;工作单位&#34;增加直到你点击进入,然后减少直到它达到零,然后它加载工作队列与毒丸,告诉消费者关闭。有一些技巧可以让输入/翻转的东西工作,但我会让你看看代码。请注意,我使用 threads 等待阻塞I / O操作,进程执行(模拟)CPU繁重的工作。这是故意的。
有很多方法可以构建多处理代码,但我发现生产者/消费者是一个非常有用的模式。你真正想要做的一件事就是迅速创建流程来完成少量的工作,然后将它们拆除。这是慢! (我会注意到正确地使用Pool
可以避免这种情况 - 它可以让你的工作人员保持活着。但是,值得一提的是,因为很多人开始通过在一个循环中触发一堆Process
es,然后想知道为什么他们的并行代码比他们的单线程代码慢: - ))
答案 1 :(得分:1)
这不是测试multiprocessing
的好方法。您正在对x
执行无法实际有效的操作 - 您只希望一个进程能够一次增加x
。否则,不同的工人会踩踏其他工人设定的x值。而且,由于你所有的工作人员都在增加x,所以他们基本上需要完全按顺序运行,而不需要并发运行。
也就是说,要使此代码正常工作,您需要实际从apply_async
返回的AsyncResult
对象中获取实际结果:
import time
from multiprocessing import Pool
def f(x):
return (x+1)
def f1(x1):
return (x-1)
if __name__ == '__main__':
pool = Pool(processes=2)
x=0
while x<100:
x = pool.apply_async(f, [x]).get() # Added get, changed 10 to x
time.sleep(0.05)
添加get
调用将使主进程阻塞,直到工作人员实际完成为止。当然,这意味着你并没有真正做到平行,但这确实是安全增加变量的唯一方法。