multiprocessing.Pool似乎在Windows中工作但在ubuntu中不起作用?

时间:2011-08-02 15:06:54

标签: python multiprocessing

解决:问题是Wingware Python IDE。我想现在的自然问题是它是如何可行的以及如何解决这个问题。

我昨天问了一个问题(Problem with multiprocessing.Pool in Python),这个问题几乎是一样的,但我发现它似乎可以在Windows电脑上运行,而不是在我的ubuntu上运行。在这篇文章的最后,我将发布一个稍微不同的代码版本,它会做同样的事情。

我的问题的简短摘要:在Python中使用multiprocessing.Pool时,我并不总能获得我要求的工作量。当发生这种情况时,程序就会停止。

我一直在寻找解决方案,然后我开始考虑诺亚斯对我之前的问题的评论。他说它在他的机器上工作,所以我把代码交给我的同事,他运行一台带有Enthoughts 64位Python 2.7.1发行版的Windows机器。我和ubuntu上运行的差别很大。我还提到我们都有Wingware Python IDE,但我怀疑这有什么重要意义吗?

当我的同事在他的机器上运行代码时,我的代码有两个问题。

  1. 我并不总能得到我要求的四名工人(虽然我的机器有12名工人)。当发生这种情况时,该过程就会停止并且不会继续。没有异常或引发错误。

  2. 当我能够得到我要求的四名工人时(大概发生约1次5次左右),所产生的数字(普通随机数)对于所有四张图片都是完全相同的。我的同事不是这种情况。

  3. 有些东西非常可疑,我非常感谢你们提供的任何帮助。

    代码:

    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()
    

    提前致谢。

    此致 Matias的

2 个答案:

答案 0 :(得分:4)

我没有第一个问题的解决方案。事实上,我可以在我的64位Ubuntu盒子上使用Enthought的Python 2.7.1 [EPD 7.0-2(64位)]重复运行你的代码。 编辑:事实证明问题是由您的IDE(Wingware)引起的。显而易见的解决方法是从IDE外部运行脚本。

关于第二个问题,所发生的是在Unix上,每个工作进程都从父进程继承随机数生成器的相同状态。这就是他们生成相同的伪随机序列的原因。要解决这个问题,您只需在scipy.random.seed顶部调用testfunc

def testfunc(x0, N):
    sp.random.seed()
    print 'working with x0 = %s' % x0
    ...

答案 1 :(得分:1)

更新:原来这与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更改时禁用事件循环支持。感谢您报告此事。