并行运行时写入全局环境

Rom*_*rik 6 parallel-processing r snowfall

我有一个data.frame的单元格,值和坐标.它驻留在全球环境中.

> head(cont.values)
   cell value   x   y
1 11117    NA -34 322
2 11118    NA -30 322
3 11119    NA -26 322
4 11120    NA -22 322
5 11121    NA -18 322
6 11122    NA -14 322
Run Code Online (Sandbox Code Playgroud)

因为我的自定义函数花了将近一秒来计算单个单元格(我需要计算数万个单元格),我不想复制已经有值的单元格的计算.以下解决方案试图避免这种情况.每个单元格可以独立计算,尖叫为并行执行.

我的函数实际上做的是检查是否有指定单元格编号的值,如果它是NA,则计算它并将其插入代替NA.

我可以使用apply函数系列来运行我的魔术函数(结果是value相应的cell),从内部apply,我可以读写cont.values没有问题(它在全局环境中).

现在,我想并行运行(使用snowfall),我无法从单个核心读取或写入此变量.

问题:在并行执行函数时,从工作者(核心)内部驻留在全局环境中的动态变量可以读取/写入什么解决方案.这样做有更好的方法吗?

Mar*_*gan 4

工作人员查询值的中央存储模式是在CRAN 上的rrredis包中实现的。这个想法是,Redis 服务器维护键值对的存储(重新实现的全局数据框架)。工作人员查询服务器以查看该值是否已计算(redisGet),如果没有计算并存储它(redisSet),以便其他工作人员可以重复使用它。Workers可以是R脚本,因此很容易扩展劳动力。这是一个非常好的替代并行范例。这是一个使用“记忆”每个结果概念的示例。我们有一个很慢的函数(休眠一秒钟)

fun <- function(x) { Sys.sleep(1); x }
Run Code Online (Sandbox Code Playgroud)

我们编写一个“memoizer”,它返回一个变体,fun首先检查是否x已经计算出 的值,如果是,则使用该值

memoize <-
    function(FUN)
{
    force(FUN) # circumvent lazy evaluation
    require(rredis)
    redisConnect()
    function(x)
    {
        key <- as.character(x)
        val <- redisGet(key)
        if (is.null(val)) {
            val <- FUN(x)
            redisSet(key, val)
        }
        val
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们记住我们的函数

funmem <- memoize(fun)
Run Code Online (Sandbox Code Playgroud)

> system.time(res <- funmem(10)); res
   user  system elapsed 
  0.003   0.000   1.082 
[1] 10
> system.time(res <- funmem(10)); res
   user  system elapsed 
  0.001   0.001   0.040 
[1] 10
Run Code Online (Sandbox Code Playgroud)

这确实需要一个在 R 之外运行的 Redis 服务器,但安装起来非常容易;请参阅 rrredis 软件包附带的文档。

R 内并行版本可能是

library(snow)
cl <- makeCluster(c("localhost","localhost"), type = "SOCK")
clusterEvalQ(cl, { require(rredis); redisConnect() })
tasks <- sample(1:5, 100, TRUE)
system.time(res <- parSapply(cl, tasks, funmem))
Run Code Online (Sandbox Code Playgroud)