如何正确使用doSMP和foreach包?

发布于 2024-10-22 03:16:38 字数 1227 浏览 3 评论 0原文

我正在尝试使用 doSMP 包,它为foreach 包。

你能指出我做错了什么吗?事实上,以这种方式使用 foreach 会显着增加计算时间...

#------register doSMP to be used with foreach------
library(doSMP)
w <- startWorkers(4)
registerDoSMP(w)
#--------------------------------------------------

#------A simple function------
sim <- function(a, b)
{
    return(10 * a + b)
}
avec <- 1:200
bvec <- 1:400
#-----------------------------

#------The naive method------
ptime <- system.time({
mat <- matrix(NA, nrow=length(avec), ncol=length(bvec))
for(i in 1:length(avec))
{
    for(j in 1:length(bvec))
    {
         mat[i, j] <- sim(avec[i], bvec[j])
    }
}
})[3]
ptime

elapsed 
   0.36
#----------------------------

#------Using foreach------
ptime <- system.time({
mat2 <- foreach(b=bvec, .combine="cbind") %:%
         foreach(a=avec, .combine="c") %dopar%
     {
            sim(a, b)
    }
})[3]
ptime

elapsed 
  86.98
#-------------------------

编辑

这个问题与这个问题非常相似,并且已从 stats.stackexchange 迁移。

I am trying to use the doSMP package that provides a parallel backend for the foreach package.

Can you point out what I do wrong? Indeed, using foreach in that way increases significantly the computing time...

#------register doSMP to be used with foreach------
library(doSMP)
w <- startWorkers(4)
registerDoSMP(w)
#--------------------------------------------------

#------A simple function------
sim <- function(a, b)
{
    return(10 * a + b)
}
avec <- 1:200
bvec <- 1:400
#-----------------------------

#------The naive method------
ptime <- system.time({
mat <- matrix(NA, nrow=length(avec), ncol=length(bvec))
for(i in 1:length(avec))
{
    for(j in 1:length(bvec))
    {
         mat[i, j] <- sim(avec[i], bvec[j])
    }
}
})[3]
ptime

elapsed 
   0.36
#----------------------------

#------Using foreach------
ptime <- system.time({
mat2 <- foreach(b=bvec, .combine="cbind") %:%
         foreach(a=avec, .combine="c") %dopar%
     {
            sim(a, b)
    }
})[3]
ptime

elapsed 
  86.98
#-------------------------

EDIT

That question is very very similar to this one and has been migrated from stats.stackexchange.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑脸一如从前 2024-10-29 03:16:38

我个人不喜欢 doSMP 包,因为它经常使我的 R 崩溃。它是为 REvolution 版本开发的,但不知何故无法在我的机器上顺利运行。例如,上面的代码未经更改,只会使我的 R 崩溃。

其次,尝试在循环函数中使用并行化函数似乎很奇怪,在外循环中进行并行化更符合逻辑。嵌套并行计算中涉及的通信导致计算时间急剧增加。您不会获得任何好处,因为您的 sim 函数速度快得令人难以置信。事实上,保持内部循环串行化更有意义,因为在这种情况下,一个核心上的计算时间会比通信造成的开销更大。

使用 Snowfall-package 并使用 apply for 循环而不是 for 循环的插图。这也非常天真,因为矢量化可以带来很多好处(见下文)。

library(snowfall)
sfInit(parallel=T,cpus=2)
#same avec, bvec, sim

system.time({
    out <- sapply(avec,function(i) {
      sapply(bvec,function(j){
        sim(i,j)
      })
    })
})[3]
elapsed 
   0.33 

sfExport("avec","bvec","sim")
system.time({
    out <- sfSapply(avec,function(i) { # this one is parallel
      sapply(bvec,function(j){ # this one is not, no sense in doing so
        sim(i,j)
      })
    })
})[3]
elapsed 
   0.17 

除了由于结构而导致的维度名称之外,两个矩阵都是相等的:

> all.equal(out1,out2)
[1] "Attributes: < Length mismatch: comparison on first 1 components >"

执行此操作的正确 R 方法是:

system.time(
  out3 <- outer(avec*10,bvec,"+")
)[3]
elapsed 
   0.01 

这明显更快,并且创建相同的(尽管转置)矩阵:(

> all.equal(out1,t(out3))
[1] TRUE

作为参考,您的双 for 循环在我的系统上运行时间为 0.73...)

I personally don't like the doSMP package as it crashes my R often. It is developed for the REvolution build, and somehow fails to run smooth on my machine. For example, your code above, unaltered, just crashes my R.

Next to that, it seems strange to try to use a parallelized function within a loop function It is more logic to do the parallelization in the outer loop. The communication involved in nested parallel computing is causing the dramatic increase in calculation time. You don't gain anything, as your sim function is incredibly fast. In fact, keeping the inner loop serialized makes more sense, as in that situation the calculation time on one core gets bigger than the overhead due to communication.

An illustration using the snowfall-package and using apply for looping instead of for loops. This is also very naive as there is a lot to win with vectorization (see below).

library(snowfall)
sfInit(parallel=T,cpus=2)
#same avec, bvec, sim

system.time({
    out <- sapply(avec,function(i) {
      sapply(bvec,function(j){
        sim(i,j)
      })
    })
})[3]
elapsed 
   0.33 

sfExport("avec","bvec","sim")
system.time({
    out <- sfSapply(avec,function(i) { # this one is parallel
      sapply(bvec,function(j){ # this one is not, no sense in doing so
        sim(i,j)
      })
    })
})[3]
elapsed 
   0.17 

Both matrices are equal, apart from the dimension names due to the structure :

> all.equal(out1,out2)
[1] "Attributes: < Length mismatch: comparison on first 1 components >"

The correct R way to do this would be :

system.time(
  out3 <- outer(avec*10,bvec,"+")
)[3]
elapsed 
   0.01 

which is significantly faster, and creates an identical (though transposed) matrix :

> all.equal(out1,t(out3))
[1] TRUE

(as a reference, your double for-loop runs on 0.73 elapsed time on my system...)

甜警司 2024-10-29 03:16:38

Joris Meys 在这里给了我一个很好的答案在这种情况下也是如此。抱歉“双发”

Joris Meys gave me a nice answer here that holds in that situation as well. Sorry for the "double-post"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文