【问题标题】:saving and loading all environments in R在 R 中保存和加载所有环境
【发布时间】:2011-09-14 00:05:40
【问题描述】:

我正在开发一个包来在 R 中执行分布式计算(在 github 上的 RHadoop 项目下的 rmr)。我试图使事情对用户尽可能透明,并且只是让计算在其他机器上的另一个解释器中继续进行,就好像它在同一台机器上一样。类似的东西

lapply(my.list, my.function)

my.function 的每次调用原则上都可以在集群中的不同节点上发生,因此需要一个单独的解释器。我正在使用 saveload 这对在一定程度上取得了成功,但我希望有一个在所有可能情况下都有效的解决方案,而不仅仅是在大量用例中。

不管my.function做什么,不管它是在哪里定义的,不管它指的是什么其他对象和包,我想确定的是,如果它在本地工作,它也可以在远程工作,包括加载必要的包和一切。 saveload 保存对象列表并分别加载文件。从或到特定环境。我想找到或编写一些东西,将所有必要的对象从必要的环境中保存和加载到必要的环境中,以便在my.list 的每个元素上评估my.function 将在本地和远程具有相同的语义。

以前有没有这样做过,我应该检查任何包,还有其他建议吗?我认为这是 rmr 中最难的技术问题,您可以将您的解决方案贡献给 OSS 项目。

【问题讨论】:

  • 我的第一次回答是断言这不是您要求的可行,但我认为有一个可行的答案。 RHIPE 呢?令人满意且有效。
  • 很高兴 RHIPE 为你工作,但它根本不处理环境,所以它与这个问题无关。使用 rmr,我们试图使 mapreduce 像 lapply-tapply 组合一样工作,并具有正常的变量作用域。我们只是认为这是最类似于 R 的方式,并且以这种方式编写的程序既简单又美观。当然,美是值得商榷的,历史将成为评判者。但问题是关于恢复环境,而不是 RHIPE 是否比 rmr 更好。如果您有任何论据支持我的请求不可行,我会很感兴趣。
  • 抱歉,由于某种原因,我误读了您的问题 - 我假设您使用的是 rmr,而不是开发它。无论如何,这将是非常具有挑战性的。正如您所指出的,环境很棘手。就我而言,我通过识别和保存环境的功能来解决它​​们。更难处理的是与操作系统交互的任何对象(例如内存映射文件、连接),而不是仅存在于 R 中。您还可以检查包的加载顺序,以确保复制掩码。跨度>
  • (续)关于不可行 - 在尝试进行可重复的统计数据时,我的头撞到了墙上,特别是在网格上,它并不是不可行的(至少我无法证明它;-)) ,但是跨异构网格复制整个 R 设置(除非使用 VM,否则大多数网格最终会变成)是一项艰巨的工作。我愿意试验任何东西,因为它会帮助我,但我不能说有任何明显的解决方案。我发现最好的方法是在所有主要和辅助代码和脚本中强调可重现性。
  • 追问:能否提供一点代码来演示要解决的问题?我还在考虑这个问题。虽然在许多 Hadoop 节点上复制本地实例很困难,但解决保存环境的问题是一个相当简洁的子问题。

标签: r environment


【解决方案1】:

通常saveload 应该按照你的意愿工作:当一个函数被保存时(实际上,它是一个被保存的“闭包”),它被定义的环境也被保存了。如果该函数被定义为包的一部分,则会保存对该包的引用,并在load 看到该引用时再次加载该包。 (如果包没有命名空间,保存时会收到警告)。

唯一的问题应该是全球环境。在那里,还保存了一个引用,但这不会保存全局环境中的所有变量,因此您必须明确保存它们。

保存其他环境,包括它们的内容,然后递归地保存父环境(除非它是如上所述的包或 globalenv)。

请注意,saveRDSserialize 替代方案提供了更多控制:您可以提供一个在保存环境时调用的 refhook 函数。然后你可以做任何你想做的事情来存储环境并返回一个字符串 id。加载时,会调用类似的 refhook 从该字符串 id 重新创建环境。但是,您仍然没有被要求拯救全球环境。

e <- new.env() # parent is global env
e$foo <- 42
ee <- new.env(parent=e)
ee$bar <- 13
f <- local(function() foo+bar, ee) 
f() # foo+bar = 55
b <- serialize(f, NULL) # Gives you the serialized bytes

g <- unserialize(b) # Loads from the bytes
g() # 55
# It created new environments...
!identical(environment(g), environment(f))

希望这会有所帮助。

祝你好运rmr

【讨论】:

  • 很好的答案,就像你对约书亚问题的回答一样。对于您在 SO 上发布的环境的解释,您还有其他指示吗?你的回答对我很有启发。 (我只是发布我能找到的信息,尽管您显然对如何管理环境和闭包有更好的了解。)
  • @Iterator - 谢谢!很高兴听到有人欣赏我的胡言乱语 :) 我不记得在其他地方写过更多关于环境的文章,但你总是可以发布问题 ;)
  • 这就是问题所在——我还不知道该问什么。 :)
  • 嗨,Tommy,您可能指出了一个有趣的方向。问题不在于我认为的 save 不是递归的,而是对全局环境的不同处理。一些从事类似 rmr 项目的 Google 人员告诉我,处理全球环境是最大的问题。你应该来帮助 rmr,更重要的是因为你对高性能 R 感兴趣!
  • @piccolbo 感谢邀请,但目前我正忙于其他项目:)
【解决方案2】:

在进一步思考this question 之后,似乎答案可能对您的问题有用。如果您在保存环境时遇到与 OP 相同的问题,那么Gabor's answer 可能会帮助您走上正轨。但是,如果基本的序列化和环境保存是问题,我的(诚然不太复杂)的答案可能会有所帮助 - 通过as.list() 转换为列表,然后以通常的方式对其进行序列化,或者考虑通过 JSON 进行序列化;我最喜欢这样的包是RJSONIO

不过,Tommy 的回答对正在发生的事情提供了更多信息。假设您将广泛研究这些问题,尤其是它们的序列化,我还建议您查看 Tommy 的其他出色见解in this answer 以了解有关环境、闭包和框架的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 2020-03-27
    • 2016-07-03
    • 2023-03-22
    相关资源
    最近更新 更多