I am trying to learn how to use the parallel foreach loops in R:
I tried running the following code:
testParForEach<-function(){
#testing a parallel for each loop
#to parallelize loop:
library(foreach)
library(doSNOW)
cl<-makeCluster(2)
registerDoSNOW(cl)
resultdf <- foreach(i=1:8, .combine='rbind') %dopar% {
foreach(j=1:2, .combine='c') %do% {
l <- runif(1, i, 100)
i + j + l
}
}
return(resultdf)
#close cluster
stopCluster(cl)
}
(which I got from another post on Stackoverflow) but am getting the error:
Error in { : task 1 failed - "konnte Funktion "%do%" nicht finden"
which means "could not find function %do%".
Has anyone seen this error before?
That is because %do% is defined in the foreach package. The outer parallelization via foreach is starting separate R processes (in your case 2) which independently execute the to-be-parallelized code. But in those processes no foreach package is loaded. This is done via the .packages-paramter of the foreach-function.
An example you can find here.
Related
I created a package myself and try to apply it in parallel computing.
Suppose the package contains function1 and function2.
My code is
cl = makeCluster(2)
registerDoParallel(cl)
foreach(i=1:N,.packages='mypackage') %dopar% {
res = function1(i)
res
}
stopCluster(cl)
Then there is an error, the function1 is in mypackage.
Error in { : task 1 failed - "could not find function "function1""
However, if I change the code by adding
.export = 'function1'
The error disappears.
Thank you to anyone who can explain this.
Either use .export as OP mentioned or specify the function as packageName::functionName
cl = makeCluster(2)
registerDoParallel(cl)
foreach(i=1:N,.packages='mypackage') %dopar% {
res = mypackage::function1(i)
res
}
stopCluster(cl)
I am developing an R package and trying to use parallel processing in it for an embarrassingly parallel problem. I would like to write a loop or functional that uses the other functions from my package. I am working in Windows, and I have tried using parallel::parLapply and foreach::%dopar%, but cannot get the workers (cores) to access the functions in my package.
Here's an example of a simple package with two functions, where the second calls the first inside a parallel loop using %dopar%:
add10 <- function(x) x + 10
slowadd <- function(m) {
cl <- parallel::makeCluster(parallel::detectCores() - 1)
doParallel::registerDoParallel(cl)
`%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached
foreach::foreach(i = 1:m) %dopar% {
Sys.sleep(1)
add10(i)
}
stopCluster(cl)
}
When I load the package with devtools::load_all() and call the slowadd function, Error in { : task 1 failed - "could not find function "add10"" is returned.
I have also tried explicitly initializing the workers with my package:
add10 <- function(x) x + 10
slowadd <- function(m) {
cl <- parallel::makeCluster(parallel::detectCores() - 1)
doParallel::registerDoParallel(cl)
`%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached
foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
Sys.sleep(1)
add10(i)
}
stopCluster(cl)
}
but I get the error Error in e$fun(obj, substitute(ex), parent.frame(), e$data) : worker initialization failed: there is no package called 'mypackage'.
How can I get the workers to access the functions in my package? A solution using foreach would be great, but I'm completely open to solutions using parLapply or other functions/packages.
I was able to initialize the workers with my package's functions, thanks to people's helpful comments. By making sure that all of the package functions that were needed were exported in the NAMESPACE and installing my package with devtools::install(), foreach was able to find the package for initialization. The R script for the example would look like this:
#' #export
add10 <- function(x) x + 10
#' #export
slowadd <- function(m) {
cl <- parallel::makeCluster(parallel::detectCores() - 1)
doParallel::registerDoParallel(cl)
`%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached
out <- foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
Sys.sleep(1)
add10(i)
}
stopCluster(cl)
return(out)
}
This is working, but it's not an ideal solution. First, it makes for a much slower workflow. I was using devtools::load_all() every time I made a change to the package and wanted to test it (before incorporating parallelism), but now I have to reinstall the package every time, which is slow when the package is large. Second, every function that is needed in the parallel loop needs to be exported so that foreach can find it. My actual use case has a lot of small utility functions which I would rather keep internal.
You can use devtools::load_all() inside the foreach loop or load the functions you need with source.
out <- foreach::foreach(i = 1:m ) %dopar% {
Sys.sleep(1)
source("R/some_functions.R")
load("R/sysdata.rda")
add10(i)
}
I have the following code where i get an error like:
object 'a' could not be found
This file is inside a package.
It works when i use %do% instead of %dopar%
a <- 2
fun1 <- function(x)
{
y <- x*a
return(y)
}
fun2 <- function(n)
{
foreach(data = 1:n, .combine = rbind, .multicombine = TRUE, .export = c("a","fun1")) %dopar%
{
load_all() # Works, get error if line is removed
y <- fun1(data)
return(y)
}
}
In my main file where i use devtools::load-all() to load the package and have used doParallel to run my foreach on multiple cores i execute fun2(5) when getting the error.
If i use a directly in the foreach function body everything works. But when i use a function that uses the a variable, i get the error.
My main issue is i wan't to be able to call the function fun1 from both fun2 aswell as stand alone from the package.
Cluster is created as
cl <- makeCluster(16)
registerDoParallel(cl)
clusterCall(cl, function(x) .libPaths(x), .libPaths())
# %dopar% code
stopCluster(cl)
I have over a thousand matlab files that I want to read into R. I use the R.matlab package to read them and I would like to parallel the operation.
However, once I call the loop (I am generating a single data set from all the .mat files) I get an error:
Error in { : task 1 failed - "not possible to encounter function
"readMat""
(I translated the part of the error between "", since my R is not in english)
without the foreach command, everything goes fine, but it takes too long. Here is the code
library(R.matlab)
library(plyr)
library(foreach)
library(doParallel)
a = list.files()
data <- readMat(a[1])
for(j in 2:length(a)) {
data1 <- readMat(a[j])
if (is.null(data1)==FALSE) {
data <- rbind.fill(data,data1)
}}
print(j)
}
with the foreach command I get the above error. Here is the code:
library(R.matlab)
library(plyr)
library(foreach)
library(doParallel)
cl<-makeCluster(8)
registerDoParallel(cl)
a = list.files()
data <- readMat(a[1])
foreach(j = 2:length(a)) %dopar% {
data1 <- readMat(a[j])
if (is.null(data1)==FALSE) {
data <- rbind.fill(data,data1)
}}
print(j)
}
Does it mean foreach and readMat should not be used together?
Just if anyone is wondering, I forgot to export R.matlab to each cluster node. Just needed to add .packages argument inside the foreach call
library(R.matlab)
library(plyr)
library(foreach)
library(doParallel)
cl<-makeCluster(8)
registerDoParallel(cl)
a <- list.files()
data <- readMat(a[1])
foreach(j = 2:length(a), .packages = c("plyr", "doParallel",
"R.matlab")) %dopar% {
data1 <- readMat(a[j])
if (!is.null(data1)) {
data <- rbind.fill(data,data1)
}
}
I have an R code that involves several foreach workers to perform some tasks in parallel. I am using foreach and doMC for this purpose. I want to let each of the foreach workers recruits some new workers and distribute some parts of their code, which is parallelizable, to them.
The current code looks like:
require(doMC)
require(foreach)
registerDoMC(cores = 8)
foreach (i = (1:8)) %dopar% {
<<some code here>>
for (j in c(1:4)) {
<<some other code here>>
}
}
I am looking for an ideal code that would look like:
require(doMC)
require(foreach)
registerDoMC(cores = 8)
foreach (i = (1:8)) %dopar% {
<<some code here>>
foreach (j = (1:4)) %dopar% {
<<some other code here>>
}
}
I saw an example of multi-paradigm parallelism using doSNOW and doMC here (https://www.rmetrics.org/files/Meielisalp2009/Presentations/Lewis.pdf#page=17). However, I do not know whether it does what I want or not.
Also, it seems Nested foreach is not applicable because it requires merging the two loops (see here), while in my case this is not preferred; the second loop only helps the first one for a portion of the code. Please correct me if I am wrong.
Thanks.
There's no particular problem with having a foreach loop inside of a foreach loop. Here's an example of a doMC loop inside a doSNOW loop:
library(doSNOW)
hosts <- c('host-1', 'host-2')
cl <- makeSOCKcluster(hosts)
registerDoSNOW(cl)
r <- foreach(i=1:4, .packages='doMC') %dopar% {
registerDoMC(2)
foreach(j=1:8, .combine='c') %dopar% {
i * j
}
}
stopCluster(cl)
It seems natural to me to use doMC for the inner loop, but you can do it anyway you want. You could also use doSNOW for both loops, but then you would need to create and stop the snow cluster inside the outer foreach loop.
Here's an example of using doMC inside a doMC loop:
library(doMC)
registerDoMC(2)
r <- foreach(i=1:2, .packages='doMC') %dopar% {
ppid <- Sys.getpid()
registerDoMC(2)
foreach(j=1:2) %dopar% {
c(ppid, Sys.getpid())
}
}
The results demonstrate that a total of six processes are forked by the doMC package, although only four execute the body of the inner loop:
> r
[[1]]
[[1]][[1]]
[1] 14946 14949
[[1]][[2]]
[1] 14946 14951
[[2]]
[[2]][[1]]
[1] 14947 14948
[[2]][[2]]
[1] 14947 14950
Of course, you need to be careful not to start too many processes on a single node. I found this kind of nesting a bit awkward, which led to the development of the nesting operator.