我运行以下示例代码来模拟值,下面是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尝试这个会更快吗?
答案 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块好一点。但是,确实有很多数据需要传输和重新组装。拆分数据也是一项代价高昂的操作。我不打扰这里的并行化。