Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以同时使用for循环和apply族的并行版本吗?_R_For Loop_Parallel Processing_Apply_Doparallel - Fatal编程技术网

我可以同时使用for循环和apply族的并行版本吗?

我可以同时使用for循环和apply族的并行版本吗?,r,for-loop,parallel-processing,apply,doparallel,R,For Loop,Parallel Processing,Apply,Doparallel,最近我在做研究时遇到了一个问题:首先,我定义了一个函数myfunction,其中包含两个for循环,然后我使用lappy(datalist,myfunction),但处理速度太慢 然后我学习了两个并行包“foreach”和“parallel”来进行并行计算。因此,我将这两个进程都更改为并行版本 但我发现,当我运行代码时,函数中的foreach似乎不起作用 myfunction <- function{data} { df <- foreach (i = 1:200, .co

最近我在做研究时遇到了一个问题:首先,我定义了一个函数
myfunction
,其中包含两个for循环,然后我使用
lappy(datalist,myfunction)
,但处理速度太慢

然后我学习了两个并行包“foreach”和“parallel”来进行并行计算。因此,我将这两个进程都更改为并行版本

但我发现,当我运行代码时,函数中的foreach似乎不起作用

myfunction <- function{data} {

   df  <- foreach (i = 1:200, .combine = "rbind") %:% 
    foreach(j = 1:200, .combine = "rbind") %dopar% {

      *****
      process
      *****
    }

  data <- df[1,1]
  return(data)
}

system.time({

  cl <- detectCores()
  cl <- makeCluster(cl)
  registerDoParallel(cl)

  mat <- t(parSapply(cl, list, myfuntion))

  stopCluster(cl)

}) 
myfunction
我觉得这是因为parSapply占据了整个核心,所以foreach没有额外的核心来计算。有什么好办法来修理它吗?基本上,我想实现两个进程在并行版本中运行

不,这不是个好主意。在这里,您基本上是在尝试过度并行化(但正如下面所解释的,这确实发生在您的代码中)

另一个问题是:假设我们只能选择一个进程来进行并行计算,我应该选择哪一个?for循环还是apply族

没有一个正确的答案。我建议您分析您的
***进程***
代码,以了解它从并行化中获得了多少收益

因此,我发现您的
parSapply(cl,…)
位于
foreach()%dopar%{…}
顶部,使用相同的集群
cl
很有趣。我第一次看到这样的提问/提议。你肯定不想这么做,但这个问题/尝试并不疯狂。您的直觉是,当
foreach()%dopar%{…}
尝试使用它们时,所有工作人员都会被占用,这在一定程度上是正确的。然而,真正发生的事情是,
foreach()%dopar%{…}
语句在workers中进行计算,而不是在定义集群
cl
的主R会话中进行计算。在worker上,没有注册foreach适配器,因此这些调用将默认为顺序处理(=
foreach::registerDoSEQ()
)。为了实现嵌套并行化,您必须在每个worker内设置并注册一个集群,例如在
myfunction()
函数内

作为该框架的作者,我想建议您利用它。它将保护您免受上述错误的影响,而且也不会过度并行(如果您真的想这样做,您可以这样做)。下面是我将如何重写您的代码示例:

library(foreach) ## foreach() and %dopar%

myfunction <- function{data} {
   df  <- foreach(i = 1:200, .combine = "rbind") %:% 
    foreach(j = 1:200, .combine = "rbind") %dopar% {
      *****
      process
      *****
    }

  data <- df[1,1]
  return(data)
}


## Tell foreach to parallelize via the future framework
doFuture::registerDoFuture()

## Have the future framework parallelize using a cluster of
## local workers (similar to makeCluster(detectCores()))
library(future)
plan(multisession)

library(future.apply) ## future_sapply()

system.time({
  mat <- t(future_sapply(list, myfuntion))
})
如果确实要进行嵌套并行化,例如,两个外部级别的辅助对象和4个内部级别的辅助对象,可以使用:

plan(list(tweak(multisession, workers = 2), tweak(multisession, workers = 4))
这将同时运行2*4=8个并行R进程

更有用的是,当您有多台机器可用时,您可以将这些机器用于外部级别,然后在每个机器上使用多会话集群。比如:

plan(list(tweak(cluster, workers = c("machine1", "machine2")), multisession))

您可以在vignettes中了解更多信息。

您所说的“不起作用”是什么意思?@JérômeRichard当
列表
仅包含一个数据集时,我运行相同的代码。理想情况下,我希望调用所有的内核进行计算,但这表明只使用了大约10-15%的cpu。换句话说,我的denied函数中的
foreach
不起作用。我想我会尝试您在稍后的回复中提到的嵌套并行化。顺便说一句,组合多台机器的代码非常好。谢谢:D
plan(list(tweak(cluster, workers = c("machine1", "machine2")), multisession))