我正在尝试学习r中的并行性。我写了一个代码,其中我有一个50*50的矩阵,从值1到250000。对于矩阵中的每一个元素,我都在寻找它的邻居值最小的元素。邻居也可以在对角线上。然后我把元素本身替换成最小的邻居。在我的计算机上运行这段代码所需的时间大约是4.5秒。如果可能的话,谁能帮我把for循环平行?下面是代码片段
start_time <- Sys.time()
myMatrix <- matrix(1:250000, nrow=500) # a 500 * 500 matrix from 1 to 250000
indexBound <- function(row,col) { # this function is to check if the indexes are out of bound
if(row<0 || col <0 || row > 500 || col >500){
return (FALSE)
}
else{
return (TRUE)
}
}
for(row in 1:nrow(myMatrix)){
for(col in 1:ncol(myMatrix)){
li <- list()
if(indexBound(row-1,col-1)){
li <- c(li,myMatrix[row-1,col-1])
}
if(indexBound(row-1,col)){
li <- c(li,myMatrix[row-1,col])
}
if(indexBound(row-1,col+1)){
li <- c(li,myMatrix[row-1,col+1])
}
if(indexBound(row,col-1)){
li <- c(li,myMatrix[row,col-1])
}
if(indexBound(row-1,col+1)){
li <- c(li,myMatrix[row,col+1])
}
if(indexBound(row+1,col-1)){
li <- c(li,myMatrix[row+1,col-1])
}
if(indexBound(row+1,col)){
li <- c(li,myMatrix[row+1,col])
}
if(indexBound(row+1,col+1)){
li <- c(li, myMatrix[row+1,col+1])
}
min = Reduce(min,li) #find the lowest value from the list
myMatrix[row,col] = min
}
}
end_time <- Sys.time()
end_time - start_time
感谢您的回复。
您的脚本将产生一个所有元素都等于2的矩阵。如果这不是目的,您应该创建myMatrix
的副本,以便在构建li
时使用(在if
语句中)。
我意识到这可能是一个探索并行化的人为例子,但使用R通常最好首先关注向量化。当向量化时,此操作可能足够快,而并行化实际上可能由于开销而变慢。例如,以下是使用填充矩阵的矢量化解决方案(这不会给出所有2,并且它仍然不包括min
计算中的当前单元格):
library(matrixStats)
system.time({
idxShift <- expand.grid(rep(list(-1:1), 2))[-5,] # don't include the current cell (0, 0)
myMatrix <- matrix(nrow = 502, ncol = 502)
myMatrix[2:501, 2:501] <- matrix(1:250000, nrow = 500)
myMatrix <- matrix(rowMins(mapply(function(i,j) c(myMatrix[2:501 + i, 2:501 + j]), idxShift$Var1, idxShift$Var2), na.rm = TRUE), nrow = 500)
})
user system elapsed
0.03 0.00 0.03
将其与使用future.apply
的相同矢量化代码的并行版本进行比较:
library(future.apply)
plan(multisession)
system.time({
idxShift <- expand.grid(rep(list(-1:1), 2))[-5,]
myMatrix <- matrix(nrow = 502, ncol = 502)
myMatrix[2:501, 2:501] <- matrix(1:250000, nrow = 500)
myMatrix <- matrix(rowMins(future_mapply(function(i,j) c(myMatrix[2:501 + i, 2:501 + j]), idxShift$Var1, idxShift$Var2), na.rm = TRUE), nrow = 500)
})
future:::ClusterRegistry("stop")
user system elapsed
0.10 0.05 2.11
如果我没有搞砸什么,并行解决方案会更慢,这甚至不包括plan(multisession)
在计时。