Reputation: 35
The problem in short: I have to visualise an optimisation process on a plot. On a pre-plotted device the new solutions (as points(x,y)) should appear as they are available. I have working sequential code by a nested loop, but it should possible to make it parallel. I gave a try with the foreach package (with the doParallel backend) but the spawned processes can not plot on the parent processe's device - obviously. Is it possible to overcome this maybe with another package or anyhow?
Upvotes: 3
Views: 725
Reputation: 19667
I don't think it's possible to have one process plot to another process's graphics device in R. Instead, the processes need to send messages to a designated process that does all of the graphics operations. That would be rather difficult using parallel or foreach/doParallel, but it's relatively easy using foreach with a parallel backend that supports processing worker results on-the-fly, such as doMPI or doRedis. In that case, you can plot the points in the combine function as they are computed by the workers. Here's a simple example:
library(doMPI)
nworkers <- 4
cl <- startMPIcluster(nworkers)
comm <- cl$comm # get communicator number
registerDoMPI(cl)
cap <- capabilities()
if (cap['aqua']) quartz() else if (cap['X11']) X11() else windows()
plot(integer(0), integer(0),
main='Random points generated by doMPI workers',
xlab='X', ylab='Y', xlim=c(1,100), ylim=c(1,100))
legend('topright', sprintf('worker %d', 1:nworkers), pch=1:nworkers)
# The argument "p" is a list of arguments to the function "points"
plotpoint <- function(x, p) {
do.call('points', p)
x
}
foreach(i=icount(100), .combine='plotpoint',
.init=NULL, .inorder=FALSE) %dopar% {
Sys.sleep(abs(rnorm(1, mean=3)))
list(x=sample(100,1), y=sample(80,1), pch=mpi.comm.rank(comm))
}
text(50, 90, 'Finished')
Sys.sleep(10)
closeCluster(cl)
mpi.quit()
I'm throwing away the results since they are only used to call points
, but you could modify plotpoint
to save some part of the result in the first argument x
. Just make sure that you modify the .init
argument to the appropriate data structure.
Upvotes: 1
Reputation: 309
You might be able to try something like this:
foreach(i=1:10) %dopar% with(env.profile(.GlobalEnv), #Your Code#)
I'm not sure if this would work or not. You may be running into problems because of the sequential nature of plotting with base R graphics works. You might also try creating a list and just adding the results of each iteration to the list during the %dopar% call. After it's finished, you should be able to just use lapply(point.list, points).
Upvotes: 0