Is there any way to break out of a foreach loop?

前端 未结 6 1161
耶瑟儿~
耶瑟儿~ 2020-12-04 22:29

I am using the R package foreach() with %dopar% to do long (~days) calculations in parallel. I would like the ability to stop the entire set of cal

6条回答
  •  -上瘾入骨i
    2020-12-04 23:06

    Steve Weston's original answer essentially answered this. But here is a slightly modified version of his answer which also preserves two additional features in the way I need them: (1) random number generation; (2) printing run-time diagnostics.

    suppressMessages(library(doMPI))
    
    comb <- function(x, y) {
      if(inherits(y, 'error')) {
        stop(y)
      }
      rbind(x, y) # forces the row names to be 'y'
    }
    
    myfunc <- function() {
      writeLines(text="foreach log", con="log.txt")
      foreach(i=1:12, .errorhandling='pass', .combine='comb', .inorder=FALSE, .init=NULL) %dopar% {
        set.seed(100)
        sink("log.txt", append=TRUE)
        if(i==6) {
          stop('testing abort')
        }
        Sys.sleep(10)
        cat("Completed task", i, "\n")
        sink(NULL)
        rnorm(5,mean=i)
      }
    }
    
    myerr <- function(e) {
      cat(sprintf('Caught error: %s\n', conditionMessage(e)))
      mpi.abort(cl$comm)
    }
    
    cl <- startMPIcluster(4)
    registerDoMPI(cl)
    r <- tryCatch(myfunc(), error=myerr)
    closeCluster(cl)
    

    When this file is sourced, it exits as intended with an error message

    > source("exp2.R")
        4 slaves are spawned successfully. 0 failed.
    Caught error: testing abort
    [ganges.local:16325] MPI_ABORT invoked on rank 0 in communicator  with errorcode 0
    

    The 'log.txt' files provides correct diagnostics up to the point of error, and then provides additional error information. Crucially, the execution of all tasks is halted as soon as the stop() in the foreach loop is encountered: it does not wait until the entire foreach loop has completed. Thus I only see the 'Completed task' message up to i=4. (Note that if Sys.sleep() is shorter, then later tasks may be started before the mpi.abort() is processed.)

    If I change the stop condition to be "i==100", then the stop and hence the error is not triggered. The code successfully exists without an error message, and r is a 2D array with dimensions 12*5.

    Incidentally, it seems that I don't actually need .inorder=FALSE (I think that just gives me a small speed increase in the event that an error is found).

提交回复
热议问题