IPython并行计算命名空间问题



我一直在反复阅读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的定义中是必要的

已编辑:这根本不是命名空间错误——我在一个不包含代码的目录中执行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

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

这主要是IPython.parallel的Python名称空间问题的重复,它有更详细的答案,但要点是:

当客户端向引擎发送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()是模块全局,它们通常在任何地方都是相同的。

最新更新