使用doSNOW加速R中的显式循环

时间:2010-12-18 09:13:09

标签: r parallel-processing

我在办公室使用的计算机最近升级为四核计算机,这对我来说是一种祝福,因为有时我需要使用R做一些显式循环,结果基于一些逻辑规则,除了明确的循环之外,我无法弄清楚如何解决这个问题。

对于某些背景信息,有时候我有大约10000-20000行,我需要查看2列,并根据它们的值和一些逻辑规则来为新列生成值。

我正在尝试使用doSNOW软件包来更好地利用未使用的CPU电源,我根据here中的示例编写了如下的演示脚本:

library(doSNOW)
# rm(list=ls())

cl<-makeCluster(2) # I have two cores
registerDoSNOW(cl)

table <- data.frame(a=rnorm(1000),b=rnorm(1000))

process <- function(table)
              {for (loop in (1:nrow(table)))
                   {table[loop,"c"] <- with(table[loop,], a*b)
                    assign("table",table,envir=.GlobalEnv)
                   }
              }


system.time(process(table))

system.time(foreach(j=1:2 ) %dopar% process(table))

stopCluster(cl)

我正在使用带有ATOM CPU的上网本试试这个,但结果很奇怪:

system.time(process(table))
user  system elapsed 
2.336   0.028   2.308 

system.time(foreach(j=1:2 ) %dopar% process(table))
user  system elapsed 
0.160   0.032   3.646 

使用doSNOW之后,结果所需的时间甚至比不使用doSNOW更长,我想知道这是我的ATOM上网本的问题,还是我在代码中做错了什么?

谢谢!

3 个答案:

答案 0 :(得分:6)

据我所知,在您的示例中,您在没有snow的情况下运行一次函数,在snow运行两次。并行运行流程会增加额外开销,尤其是当您添加foreach的基础架构时。因此,每次执行的平均时间少于串行运行时的平均时间,但是当你分开时,你不能指望相同的总时间。

所以你说“结果比不使用doSNOW更长”是不正确的。事实上,如果你第二次运行第一次,则需要几乎两倍的时间。所以snow确实提高了性能。

这是一个公平的比较:

system.time(for(i in 1:2) process(table))
system.time(foreach(j=1:2 ) %dopar% process(table))

以这种方式思考:假设你有两个人可以在1分钟内独立完成一项任务。假设如果一个人执行多个任务,则会产生额外的开销。但如果你要求他们独立工作,他们需要更长的时间才能将他们的成果汇总在一起。如果你要求一个人完成两项任务,则需要2分钟。如果你要求每个人分开工作,那么总共花费的时间会超过1分钟,因为他们需要在最后进行沟通。

答案 1 :(得分:2)

首先,在一台机器上使用多核比使用雪更好;它利用了可以使用管道代替套接字的事实,fork所需的时间也比初始化进程要小。

现在,这也是为什么并行版本在您的上网本上运行时间更长的原因;切换到并行评估是不可避免的时间成本,它可以支配多个线程的收益。随着工作时间的延长,这段时间将变得微不足道,您将获得加速。

答案 2 :(得分:0)

减速的部分原因还可能是由于您最有可能使用单核CPU(除非您有更新的双核Atom)。在这种情况下,您正在运行R而不使用foreach()函数,但是在尝试并行运行的过程中会增加一些开销。我的建议是试试你办公室的那个,看看那里发生了什么。