为什么foreach()%do%有时比for慢?

为什么foreach()%do%有时比for慢?,r,parallel-processing,R,Parallel Processing,我第一次在R中玩并行化。作为第一个玩具示例,我尝试了 library(doMC) registerDoMC() B<-10000 myFunc<-function() { for(i in 1:B) sqrt(i) } myFunc2<-function() { foreach(i = 1:B) %do% sqrt(i) } myParFunc<-function() { foreach(i = 1:B) %dopar% sqrt(i)

我第一次在R中玩并行化。作为第一个玩具示例,我尝试了

library(doMC)
registerDoMC()

B<-10000

myFunc<-function()
{
    for(i in 1:B) sqrt(i)
}

myFunc2<-function()
{
    foreach(i = 1:B)  %do% sqrt(i)
}

myParFunc<-function()
{
    foreach(i = 1:B) %dopar% sqrt(i)
}
在我看到的大多数示例中,
foreach()%dopar%
foreach()%do%
相比较,而不是
for()
。因为在我的玩具示例中,
foreach()%do%
for()
慢得多,所以我现在有点困惑。不知何故,我认为这是构造for循环的等效方法。有什么区别?它们是等价的吗?
foreach()%do%
是否总是较慢

更新:在@Peter Fines回答之后,我更新了
myFunc
,如下所示:

 a<-rep(NA,B)
 myFunc<-function()
 {
     for(i in 1:B) a[i]<-sqrt(i)
 }

for
将运行
sqrt
B次,可能每次都会丢弃答案<但是,code>foreach返回一个列表,其中包含循环体每次执行的结果。无论它是以并行模式还是顺序模式运行(
%dopar%
%do%

我通过运行以下代码得出了我的答案,这似乎得到了的确认,其中指出“foreach与for循环的不同之处在于它的返回是一个值列表,而for循环没有值,并且使用副作用来传递其结果。”

更新:我从您更新的问题中看到,上述答案几乎不足以解释性能差异。因此,我查看了for
foreach
,可以看到有很多事情正在进行!我还没有试图确切地理解它是如何工作的,但是
do.R
foreach.R
表明,即使运行了
%do%
,大部分
foreach
配置仍在运行,如果提供的
%do%
选项允许您在不必配置和加载并行后端的情况下测试
foreach
代码,那么这是有意义的。它还需要支持
foreach
提供的更高级的嵌套和迭代功能


代码中引用了结果缓存、错误检查、调试以及为每次迭代的参数创建本地环境变量(例如,请参见
do.R
中的函数
doSEQ
)。我想这就是你所观察到的不同之处。当然,如果您在循环中运行更复杂的代码(这实际上会受益于类似于
foreach
)的并行化框架),那么与它提供的好处相比,这种开销将变得无关紧要。

另请参见这个问题:谢谢@Charlie,这些问题的答案对我完成玩具示例后要做的事情非常有帮助!:)我仍然不明白为什么使用
%do%
选项时,
foreach
需要更多的时间。其中很大一部分原因是%do%必须将工件/工作分配打包,发送给处理者,然后在最后酌情重新加入。这些步骤需要组织时间,而非非非并行版本。这不是
%dopar%
所做的吗?很有趣!我得到了完全相反的结果!看右边——这至少可以解释部分差异!但我仍然不确定它是否解释了所有这些;查看我的问题的更新!
 a<-rep(NA,B)
 myFunc<-function()
 {
     for(i in 1:B) a[i]<-sqrt(i)
 }
> system.time(myFunc())
   user  system elapsed 
  0.036   0.000   0.035 
> system.time(myFunc2())
   user  system elapsed 
  6.380   0.000   6.385 
> print(for(i in 1:10) sqrt(i))
NULL

> print(foreach(i = 1:10) %do% sqrt(i))
[[1]]
[1] 1

[[2]]
[1] 1.414214

[[3]]
... etc