Home > other >  Is there a way to do parallelism in this R Code?
Is there a way to do parallelism in this R Code?

Time:10-27

I am trying to learn parallelism in R. I have written a code where I have a 50*50 matrix from the value 1 to 250000. For each element in the matrix, I am looking for its neighbor with the lowest value. The neighbors can be in a diagonal position too. Then I am replacing the element itself with the lowest neighbor. The amount of time taken for running this code is about 4.5 seconds on my computer. If it is possible to do, could anyone help me make the for loops parallel? Here is the Code Snippet

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



Thank you for your response.

CodePudding user response:

Your script is going to result in a matrix with all elements equal to 2. If that's not the intention, you should create a copy of myMatrix to use when building li (inside the if statements).

I realize that this is probably a contrived example to explore parallelization, but with R it's usually best to focus on vectorization first. When vectorized, this operation can be fast enough that parallelization may actually be slower due to overhead. For example, here is a vectorized solution using a padded matrix (this doesn't give all 2's, and it still doesn't include the current cell in the min calculation):

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 

Compare it to a parallel version of the same vectorized code using 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 

If I didn't mess up something, the parallel solution is slower, and that is even without including plan(multisession) in the timing.

  • Related