【问题标题】:IPython Parallel Computing Namespace IssuesIPython 并行计算命名空间问题
【发布时间】:2012-08-31 13:18:48
【问题描述】:

我一直在阅读和重新阅读 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: an or more exceptions from call to method: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

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

【问题讨论】:

    标签: python parallel-processing ipython nameerror


    【解决方案1】:

    这多半是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() 是模块全局变量,通常在任何地方都相同。

    【讨论】:

    • 这两种解决方案都可以部分工作,因为它们将dimensionless_run 添加到命名空间。但是,dimensionless_run 调用的函数和类现在是命名空间中缺失的函数和类。必须有一种高效/pythonic 的方式将此数据发送到引擎,而无需为需要传递的每个函数编写一行代码。
    • 我采用以下三种方法中的一种,所有这些方法都会产生完整的命名空间: 1. 首先使用%%px 魔法远程定义函数(我在使用 IPython 笔记本时这样做)。 2.使用模块,这个问题永远不会出现。 3. 使所有在本地定义但打算远程使用的函数,永远不要从全局变量之外解析名称(100% 的名称是函数参数或函数内的导入)。在使用像您这样的脚本时,另一种选择是简单地推送globals()(当然,不包括 Client 对象本身)。
    • 嗯,我把所有的函数定义代码都移到了一个模块中,并把if __name__ == "__main__"from perceptions_wrapper import parallel_run import time, sys from IPython.parallel import Client移动了
    • (抱歉重复发帖)嗯,我将所有函数定义代码移到了一个模块中,并将 if __name__ == "__main__"... 代码移到了它自己的脚本中,该脚本仅依赖于:from wrapper import parallel_run from IPython.parallel import Client 和我仍然得到同样的错误。如果我从 parallel_run 中删除 import math, os 行(如果我从模块中导入,我应该可以这样做),它们将成为命名空间中缺少的第一个对象。
    • 这很奇怪,这不是我的经验。如果它不起作用,那么使用任何模块函数(例如 numpy.linalg.normjson.dumps)调用 apply 也不会起作用,而且它们显然会起作用,所以我不知道你在做什么有什么不同看到它。请提供一个完整的示例来重现您的问题,并可能将其带到 ipython-dev 或 GitHub,它们更适合详细讨论此类问题。
    猜你喜欢
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2013-03-26
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多