r doParallel qbeta vs RcppParallel - 如何使用满容量的核心

时间:2017-07-24 18:42:02

标签: r rcpp doparallel

我运行以下示例代码来模拟值,下面是4个内核的使用快照。使用满容量的所有核心需要一段时间,我想了解正在发生的事情以及最终如何使其更快。

library(doParallel)
library(data.table)

data<-data.table(a=runif(10000000),b=runif(10000000),quantile=runif(10000000))

e <- nrow(data)%/%1000000+1 
dataSplit<-split(data[],seq_len(nrow(data))%/%1000000)
qbetaVec<-function(lossvalues) qbeta(lossvalues$quantile,lossvalues$a,lossvalues$b)

cl <- makeCluster(4)
registerDoParallel(cl)
res2<-foreach(i=1:e) %dopar% qbetaVec(dataSplit[[i]])
res3<-unlist(res2)

在我的机器上完成大约需要67秒。当res2运行时,我看了一下性能监视器,看起来需要一段时间才能使用全容量的所有4个核心。我想了解这是什么原因。这是不可避免的吗?在所有核心以满负荷使用之前发生了什么?用RcppParallel尝试这个会更快吗?

enter image description here

1 个答案:

答案 0 :(得分:1)

并行化涉及开销,特别是与工作者之间的数据传输。此外,如果您只使用四名工作人员并且每项任务花费的时间相同,则将其分成四个以上的任务是没有意义的。

library(microbenchmark)

microbenchmark(
  OP = {
    e <- nrow(data)%/%1000000+1 
    dataSplit<-split(data[],seq_len(nrow(data))%/%1000000)
    qbetaVec<-function(lossvalues) qbeta(lossvalues$quantile,lossvalues$a,lossvalues$b)

    cl <- makeCluster(4)
    registerDoParallel(cl)
    res2<-foreach(i=1:e) %dopar% qbetaVec(dataSplit[[i]])
    res3<-unlist(res2)
    stopCluster(cl)
  },
  OP_4split = {
    e <- 4 
    dataSplit<-split(data[],seq_len(nrow(data)) %% e) #note this change
    qbetaVec<-function(lossvalues) qbeta(lossvalues$quantile,lossvalues$a,lossvalues$b)

    cl <- makeCluster(e)
    registerDoParallel(cl)
    res2<-foreach(i=1:e) %dopar% qbetaVec(dataSplit[[i]])
    res3<-unlist(res2)
    stopCluster(cl)
  },
  serial = {
    res3 <- data[, qbeta(quantile, a, b)]
  },
  times = 3
)

#Unit: seconds
#      expr      min       lq     mean   median       uq      max neval
#        OP 17.31950 17.35962 17.37491 17.39975 17.40262 17.40549     3
# OP_4split 15.98415 16.03414 16.10776 16.08413 16.16957 16.25500     3
#    serial 22.62642 22.64165 22.66247 22.65689 22.68050 22.70411     3

只有4块好一点。但是,确实有很多数据需要传输和重新组装。拆分数据也是一项代价高昂的操作。我不打扰这里的并行化。