在Mac OS X版本10.6.7上,当.parallel = TRUE时,ddply较慢

时间:2011-08-24 18:24:47

标签: macos r parallel-processing plyr

我想让ddply在我的mac上并行运行。我使用的代码如下:

library(doMC)
library(ggplot2) # for the purposes of getting the baseball data.frame
registerDoMC(2)


> system.time(ddply(baseball, .(year), numcolwise(mean)))
   user  system elapsed 
  0.959   0.106   1.522 
> system.time(ddply(baseball, .(year), numcolwise(mean), .parallel=TRUE))
   user  system elapsed 
  2.221   2.790   2.552 

为什么运行时ddply变慢.parallel = TRUE?我在网上搜索无济于事。我也试过了registerDoMC(),结果是一样的。

2 个答案:

答案 0 :(得分:11)

baseball数据可能太小,无法通过使计算并行来看到改进;将数据传递给不同进程的开销可能通过并行执行计算来淹没任何加速。使用rbenchmark包:

baseball10 <- baseball[rep(seq(length=nrow(baseball)), 10),]

benchmark(noparallel = ddply(baseball, .(year), numcolwise(mean)),
    parallel = ddply(baseball, .(year), numcolwise(mean), .parallel=TRUE),
    noparallel10 = ddply(baseball10, .(year), numcolwise(mean)),
    parallel10 = ddply(baseball10, .(year), numcolwise(mean), .parallel=TRUE),
    replications = 10)

给出结果

          test replications elapsed relative user.self sys.self user.child sys.child
1   noparallel           10   4.562 1.000000     4.145    0.408      0.000     0.000
3 noparallel10           10  14.134 3.098203     9.815    4.242      0.000     0.000
2     parallel           10  11.927 2.614423     2.394    1.107      4.836     6.891
4   parallel10           10  18.406 4.034634     4.045    2.580     10.210     9.769

如果数据集大10倍,则并行的代价就会降低。一个更复杂的计算也会使它更倾向于平行,这可能会给它带来优势。

这是在Mac OS X 10.5.8 Core 2 Duo机器上运行的。

答案 1 :(得分:9)

当节点之间的通信成本大于函数的计算时间时,并行运行将比顺序运行慢。换句话说,与执行计算相比,向/从节点发送数据所需的时间更长。

对于相同的数据集,通信成本大致是固定的,因此并行处理将更有用,因为评估功能所花费的时间会增加。

更新:
下面的代码显示花费0.14秒(在我的机器上)用于评估.fun。这意味着通信必须小于0.07秒,这对于baseball大小的数据集来说是不现实的。

Rprof()
system.time(ddply(baseball, .(year), numcolwise(mean)))
#    user  system elapsed 
#    0.28    0.02    0.30
Rprof(NULL)
summaryRprof()$by.self
#               self.time self.pct total.time total.pct
# [.data.frame       0.04    12.50       0.10     31.25
# unlist             0.04    12.50       0.10     31.25
# match              0.04    12.50       0.04     12.50
# .fun               0.02     6.25       0.14     43.75
# structure          0.02     6.25       0.12     37.50
# [[                 0.02     6.25       0.08     25.00
# FUN                0.02     6.25       0.06     18.75
# rbind.fill         0.02     6.25       0.06     18.75
# anyDuplicated      0.02     6.25       0.02      6.25
# gc                 0.02     6.25       0.02      6.25
# is.array           0.02     6.25       0.02      6.25
# list               0.02     6.25       0.02      6.25
# mean.default       0.02     6.25       0.02      6.25

这是带雪的并行版本:

library(doSNOW)
cl <- makeSOCKcluster(2)
registerDoSNOW(cl)

Rprof()
system.time(ddply(baseball, .(year), numcolwise(mean), .parallel=TRUE))
#    user  system elapsed 
#    0.46    0.01    0.73
Rprof(NULL)
summaryRprof()$by.self
#                     self.time self.pct total.time total.pct
# .Call                    0.24    33.33       0.24     33.33
# socketSelect             0.16    22.22       0.16     22.22
# lazyLoadDBfetch          0.08    11.11       0.08     11.11
# accumulate.iforeach      0.04     5.56       0.06      8.33
# rbind.fill               0.04     5.56       0.06      8.33
# structure                0.04     5.56       0.04      5.56
# <Anonymous>              0.02     2.78       0.54     75.00
# lapply                   0.02     2.78       0.04      5.56
# constantFoldEnv          0.02     2.78       0.02      2.78
# gc                       0.02     2.78       0.02      2.78
# stopifnot                0.02     2.78       0.02      2.78
# summary.connection       0.02     2.78       0.02      2.78