multiprocessing.Pool 似乎可以在 Windows 中工作,但不能在 ubuntu 中工作?
已解决:问题出在 Wingware Python IDE 上。我想现在自然的问题是这如何可能以及如何解决。
我昨天问了一个问题( Problem with multiprocessing.Pool in Python ),这个问题几乎是一样的,但我发现它似乎在 Windows 计算机上工作,而不是在我的 ubuntu 上工作。在这篇文章的末尾,我将发布一个稍微不同的代码版本,它可以完成相同的事情。
我的问题的简短摘要:在 Python 中使用 multiprocessing.Pool 时,我并不总是能够获得我所要求的工作人员数量。当这种情况发生时,程序就会停止。
我一整天都在寻找解决方案,然后我开始思考诺亚对我之前问题的评论。他说它可以在他的机器上运行,所以我把代码给了我的同事,他运行着 Windows 机器和 Enthoughts 64 位 Python 2.7.1 发行版。我的和我在ubuntu上运行的有很大的不同。我还提到我们都有 Wingware Python IDE,但我怀疑这有什么重要性吗?
当我的同事在他的机器上运行代码时,我的代码有两个问题不会出现。
我并不总是能够得到我要求的四个工人(尽管我的机器有 12 个工人)。当这种情况发生时,该过程就会停止并且不会继续。没有异常或错误发生。
当我能够找到我要求的四名工人时(这种情况大约发生五分之一左右),所有四张图片产生的数字(纯随机数)完全相同。我的同事情况并非如此。
有些事情很可疑,我非常感谢你们可以提供的任何帮助。
代码:
import multiprocessing as mp
import scipy as sp
import scipy.stats as spstat
import pylab
def testfunc(x0, N):
print 'working with x0 = %s' % x0
x = [x0]
for i in xrange(1,N):
x.append(spstat.norm.rvs(size = 1)) # stupid appending to make it slower
if i % 10000 == 0:
print 'x0 = %s, i = %s' % (x0, i)
return sp.array(x)
def testfuncParallel(fargs):
return testfunc(*fargs)
# Define Number of tasks.
nTasks = 4
N = 100000
if __name__ == '__main__':
"""
Try number 1. Using multiprocessing.Pool together with Pool.map_async
"""
pool = mp.Pool(processes = nTasks) # I have 12 threads (six cores) available so I am suprised that it does not get access to nTasks = 4 amount of workers
# Define tasks:
tasks = [(x, n) for x, n in enumerate(nTasks*[N])] # nTasks different tasks
# Compute parallel: async - asynchronically, i.e. not necessary in order.
result = pool.map_async(testfuncParallel, tasks)
pool.close() # These are needed if map_async is used
pool.join()
# Get results:
sim = sp.zeros((N, nTasks))
for nn, res in enumerate(result.get()):
sim[:, nn] = res
pylab.figure()
for i in xrange(nTasks):
pylab.subplot(nTasks,1, i + 1)
pylab.plot(sim[:, i])
pylab.show()
提前致谢。
真挚地, 马蒂亚斯
SOLVED: The problem was Wingware Python IDE. I guess the natural question now is how it is possible and how this could be fixed.
I asked a question yesterday ( Problem with multiprocessing.Pool in Python ) and this question is almost the same but I have figured out that it seems to work on a Windows computer and not in my ubuntu. At the end of this post I will post a slightly different version of the code that does the same thing.
Short summary of my problem: When using multiprocessing.Pool in Python I am not always able to get the amount of workers that I am asking for. When this happens, the program just stalls.
I have been working for a solution all day, and then I came to think about Noahs' comment on my previous question. He said that it worked on his machine so I gave the code to my colleague who runs a Windows machine with Enthoughts 64-bit Python 2.7.1 distribution. I have the same with the big difference that mine runs on ubuntu. I also mention that we both have Wingware Python IDE, but I doubt that this is of any importance?
There are two problems with my code that don't arise when my colleague runs the code on his machine.
I am not always able to get the four workers I am asking for (Although my machine has 12 workers). When this happens, the process just stalls and does not continue. No exception or Error is raised.
When I am able to get the four workers I ask for (which happens approximately 1 out 5 times or so), the figures that are produced (plain random numbers) are EXACTLY the same for all four pictures. This is not the case for my colleague.
Something is very fishy and I am very thankful for any kind of help you guys can offer.
The code:
import multiprocessing as mp
import scipy as sp
import scipy.stats as spstat
import pylab
def testfunc(x0, N):
print 'working with x0 = %s' % x0
x = [x0]
for i in xrange(1,N):
x.append(spstat.norm.rvs(size = 1)) # stupid appending to make it slower
if i % 10000 == 0:
print 'x0 = %s, i = %s' % (x0, i)
return sp.array(x)
def testfuncParallel(fargs):
return testfunc(*fargs)
# Define Number of tasks.
nTasks = 4
N = 100000
if __name__ == '__main__':
"""
Try number 1. Using multiprocessing.Pool together with Pool.map_async
"""
pool = mp.Pool(processes = nTasks) # I have 12 threads (six cores) available so I am suprised that it does not get access to nTasks = 4 amount of workers
# Define tasks:
tasks = [(x, n) for x, n in enumerate(nTasks*[N])] # nTasks different tasks
# Compute parallel: async - asynchronically, i.e. not necessary in order.
result = pool.map_async(testfuncParallel, tasks)
pool.close() # These are needed if map_async is used
pool.join()
# Get results:
sim = sp.zeros((N, nTasks))
for nn, res in enumerate(result.get()):
sim[:, nn] = res
pylab.figure()
for i in xrange(nTasks):
pylab.subplot(nTasks,1, i + 1)
pylab.plot(sim[:, i])
pylab.show()
Thanks in advance.
Sincerely,
Matias
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有办法解决你的第一个问题。事实上,我可以使用 Enthought 的 Python 2.7.1 [EPD 7.0-2(64 位)] 在我的 64 位 Ubuntu 机器上重复运行您的代码,不会失败。 编辑:事实证明问题是由您的 IDE (Wingware) 引起的。明显的解决方法是从 IDE 外部运行脚本。
至于第二个问题,在 Unix 上,每个工作进程都会从父进程继承相同的随机数生成器状态。这就是为什么它们生成相同的伪随机序列。要解决此问题,您所需要做的就是在
testfunc
顶部调用scipy.random.seed
:I don't have a solution for your first problem. In fact, I can run your code repeatedly without fail on my 64-bit Ubuntu box with Enthought's Python 2.7.1 [EPD 7.0-2 (64-bit)]. edit: It turns out the problem was being caused by your IDE (Wingware). The obvious workaround is to run the script from outside the IDE.
As to the second question, what happens is that on Unix every worker process inherits the same state of the random number generator from the parent process. This is why they generate identical pseudo-random sequences. All you have to do to fix this is call
scipy.random.seed
at the top oftestfunc
:更新:事实证明,这与 matplotlib 或后端无关,而是与一般与多处理相关的错误有关。我们已针对 Wing 版本 4.0.4+ 修复了此问题。解决方法是不在子进程中执行的代码中设置断点。
似乎是 Wing IDE 的 matplotlib 支持 Tkinter 后端与多处理交互不良。当我尝试这个示例时,它在 TCL/Tk 代码中崩溃了。我怀疑在 Windows 上工作的人使用的是不同的 matplotlib 后端。
关闭“扩展”选项卡下的“项目属性”中的“matplotlib 事件循环支持”似乎可以解决此问题。
或者,当打开“matplotlib 事件循环支持”时,添加以下内容似乎可以为我修复它。
导入 matplotlib
matplotlib.use('WXAgg')
仅当您有 WXAgg 后端时才有效。 Wing IDE 支持的其他后端(即使调试过程暂停,绘图仍保持交互)是 GTKAgg 和 Qt4Agg,但我还没有尝试这些。
我会看看是否能找到并修复该错误。我怀疑当进程 ID 更改时我们需要禁用事件循环支持。感谢您报告此事。
Update: Turns out this had nothing to do with matplotlib or the backends but rather with a bug associated with multiprocessing in general. We've fixed this for Wing version 4.0.4+. The work-around is not to set breakpoints in the code that is executed in the sub-processes.
It seems to be Wing IDE's matplotlib support for the Tkinter backend interacting badly with multiprocessing. When I try this example it crashes in TCL/Tk code. I suspect the person working on Windows was using a different matplotlib backend.
Turning off the "matplotlib event loop support" in Project Properties under the Extensions tab seems to work around it.
Or, adding the following seems to fix it for me when the "matplotlib event loop support" is turned on.
import matplotlib
matplotlib.use('WXAgg')
This will only work if you have the WXAgg backend. Other backends supported by Wing IDE (in such a way that plots remain interactive even if the debug process is paused) are GTKAgg and Qt4Agg but I didn't try those yet.
I'll see if I can find and fix the bug. I suspect we need to disable our event loop support when the process ID changes. Thanks for reporting this.