IPython并行计算命名空间问题

时间:2012-09-06 16:54:56

标签: python parallel-processing ipython nameerror

我一直在阅读并重新阅读IPython文档/教程,我无法弄清楚这段特殊代码的问题。似乎函数dimensionless_run对于传递给每个引擎的命名空间是不可见的,但我很困惑因为函数在__main__中定义,并且作为全局的一部分清晰可见命名空间。

wrapper.py:

import math, os

def dimensionless_run(inputs):
    output_file = open(inputs['fn'],'w')
    ...
    return output_stats

def parallel_run(inputs):
    import math, os  ## Removing this line causes a NameError: global name 'math'
                     ## is not defined.
    folder = inputs['folder']
    zfill_amt = int(math.floor(math.log10(inputs['num_iters'])))
    for i in range(inputs['num_iters']):
        run_num_str = str(i).zfill(zfill_amt)
        if not os.path.exists(folder + '/'):
            os.mkdir(folder)
        dimensionless_run(inputs)
    return

if __name__ == "__main__":
    inputs = [input1,input2,...]
    client = Client()
    lbview = client.load_balanced_view()
    lbview.block = True
    for x in sorted(globals().items()):
        print x
    lbview.map(parallel_run,inputs)

ipcluster start --n=6之后执行此代码会生成已排序的全局字典,包括mathos模块以及parallel_rundimensionless_run函数。接下来是一个IPython.parallel.error.CompositeError:调用方法的一个或多个异常:parallel_run,它由大量[n:apply]: NameError: global name 'dimensionless_run' is not defined组成,其中n从0-5开始。

有两件事我不明白,而且它们之间有明显的联系。

  1. 为什么代码不能识别全局命名空间中的dimensionless_run
  2. 为什么import math, os必须在里面定义parallel_run?
  3. 已编辑:根本没有太多的命名空间错误 - 我在一个不包含代码的目录中执行ipcluster start --n=6。要修复它,我需要做的就是在我的代码目录中执行start命令。我还通过添加以下行来修复它:

        inputs = input_pairs
        os.system("ipcluster start -n 6") #NEW
        client = Client()
        ...
        lbview.map(parallel_run,inputs)
        os.system("ipcluster stop")       #NEW
    

    在正确的位置启动所需的群集。

1 个答案:

答案 0 :(得分:7)

这主要是Python name space issues with IPython.parallel的副本,其中有更详细的答案,但要点:

当客户端将parallel_run发送到引擎时,它只发送该函数,而不是发送定义函数的整个命名空间(__main__模块)。因此,在运行远程parallel_run时,mathosdimensionless_run的查找将首先在locals()中查找(已在函数中定义的内容,即您的函数内导入),然后在globals(),即引擎上的__main__模块

有多种方法可以确保引擎上的名称可用,但最简单的方法是明确定义/发送它们到引擎(引擎上的交互式命名空间 __main__ ,就像它在IPython本地一样):

client[:].execute("import os, math")
client[:]['dimensionless_run'] = dimensionless_run

在您开始运行之前,在这种情况下,一切都应该按预期运行。

这是交互式/脚本中定义的模块所特有的问题 - 如果此文件是模块而不是脚本,则不会出现此问题,例如

from mymod import parallel_run
lbview.map(parallel_run, inputs)

在这种情况下,globals()是模块全局变量,在各处通常都是相同的。