我用foreach
+ doParallel
在R的功能應用到各行的矩陣的multithreadedly當矩陣有很多行,之前以及在迭代multithreadedly會後foreach
需要很長的時間。如何減少多線程迭代之前和之後的foreach時間?
例如,如果我運行:
library(foreach)
library(doParallel)
doWork <- function(data) {
# setup parallel backend to use many processors
cores=detectCores()
number_of_cores_to_use = cores[1]-1 # not to overload the computer
cat(paste('number_of_cores_to_use:',number_of_cores_to_use))
cl <- makeCluster(number_of_cores_to_use)
clusterExport(cl=cl, varlist=c('ns','weights'))
registerDoParallel(cl)
cat('...Starting foreach initialization')
output <- foreach(i=1:length(data[,1]), .combine=rbind) %dopar% {
cat(i)
y = data[i,5]
a = 100
for (i in 1:3) { # Useless busy work
b=matrix(runif(a*a), nrow = a, ncol=a)
}
return(runif(10))
}
# stop cluster
cat('...Stop cluster')
stopCluster(cl)
return(output)
}
r = 100000
c = 10
data = matrix(runif(r*c), nrow = r, ncol=c)
output = doWork(data)
output[1:10,]
CPU使用率是如下(100%是指所有核都得到充分利用):
與註釋:
我該如何選擇使代碼變得簡單,這樣foreach
在多線程迭代之前和之後都不需要很長時間?主要的時間點是花費的時間。花費的時間隨着foreach迭代次數的增加而顯着增加,有時會使代碼慢,就好像使用簡單的for循環一樣。
另一個例子(假設lm
和poly
不能採取矩陣作爲參數):
library(foreach)
library(doParallel)
doWork <- function(data,weights) {
# setup parallel backend to use many processors
cores=detectCores()
number_of_cores_to_use = cores[1]-1 # not to overload the computer
cat(paste('number_of_cores_to_use:',number_of_cores_to_use))
cl <- makeCluster(number_of_cores_to_use)
clusterExport(cl=cl, varlist=c('weights'))
registerDoParallel(cl)
cat('...Starting foreach initialization')
output <- foreach(i=1:nrow(data), .combine=rbind) %dopar% {
x = sort(data[i,])
fit = lm(x[1:(length(x)-1)] ~ poly(x[-1], degree = 2,raw=TRUE), na.action=na.omit, weights=weights)
return(fit$coef)
}
# stop cluster
cat('...Stop cluster')
stopCluster(cl)
return(output)
}
r = 10000
c = 10
weights=runif(c-1)
data = matrix(runif(r*c), nrow = r, ncol=c)
output = doWork(data,weights)
output[1:10,]
問題出在'rbind' I認爲。 'rbind'列表中的很多值需要很長時間。另外,填充行很糟糕,因爲矩陣是按列存儲的。另外,製作一個long foreach循環效率不高(使用塊代替)。最後,在矩陣上進行並行化時,使用共享內存總是更好。如果您製作的示例與您想要的更接近,我可以爲您制定解決方案。 –
問題在於認爲''foreach%dopar%'*總是比矢量化方法快。由於您通過'i = 1:length(data [,1])'和'data'具有100,000行迭代,因此'foreach%dopar%'需要在100,000個工作者實例之間進行通信。在實施並行化方法之前,您應該在矢量化方法(sapply,lapply,apply)和並行化方法之間進行基準測試。如果你想堅持一種並行化的方法,把你的代碼改爲在列(其中有10個)而不是行上工作。更好的辦法是減少每個工作人員的工作量。 – CPak
@F.Privé謝謝,我會非常感興趣。我添加了一個與我想要的更接近的例子。 –