IPython并行计算命名空间问题

Mic*_*l K 4 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)
Run Code Online (Sandbox Code Playgroud)

ipcluster start --n=6生成已排序的全局字典(包括mathos模块)和parallel_rundimensionless_run函数之后执行此代码.接下来是一个IPython.parallel.error.CompositeError:调用方法的一个或多个异常:parallel_run,由大量的[n:apply]: NameError: global name 'dimensionless_run' is not definedn 组成,其中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
Run Code Online (Sandbox Code Playgroud)

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

min*_*nrk 7

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

当客户端发送parallel_run到引擎时,它只发送该函数,而不是定义函数的整个命名空间(__main__模块).所以运行远程时parallel_run,查找到mathosdimensionless_run将首先在locals()(什么已经在函数已经被定义,即你的函数内进口),然后在globals(),这是__main__模块上的发动机.

有各种方法来使引擎上提供一定的名字,但也许最简单的就是明确定义/它们发送到引擎(交互式命名空间 __main__在发动机,就像在本地是在IPython中):

client[:].execute("import os, math")
client[:]['dimensionless_run'] = dimensionless_run
Run Code Online (Sandbox Code Playgroud)

在运行之前,在这种情况下,一切都应该按预期工作.

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

from mymod import parallel_run
lbview.map(parallel_run, inputs)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,globals()模块全局变量,到处都是相同的.

  • 我做了三种方法中的一种,所有方法都产生了完整的命名空间:1.首先使用`%% px` magic远程定义函数(我在使用IPython笔记本时这样做).2.使用模块,这个问题永远不会出现.3.使所有函数在本地定义,但打算远程使用,永远不要解析全局变量之外的名称(100%的名称是函数参数或函数内的导入).当你从像你这样的脚本工作时,另一个选择就是简单地推送`globals()`(当然不包括Client对象本身). (2认同)