保存并加载R中的所有环境

时间:2011-09-14 00:05:40

标签: r environment

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

这样的东西
lapply(my.list, my.function)

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

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

以前是否已经完成,我应该检查的任何套餐,还有其他任何建议吗?我认为这是rmr中最难的技术问题,您将为OSS项目贡献您的解决方案。

2 个答案:

答案 0 :(得分:4)

通常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

答案 1 :(得分:1)

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

然而,汤米的答案对于正在发生的事情提供了更多信息。假设您将广泛调查这些问题,特别是他们的序列化,我还建议您查看Tommy关于环境,闭包和框架的其他优秀见解in this answer