rloopssimulationphylogenyape-phylo

Skipping slow tasks in a loop in R


I'm trying to run a simulation in R where I make a whole bunch of phylogenetic trees. The tree simulation is a bit of a problem because its run time is highly variable, sometimes 0.005 seconds and sometimes minutes. I want to avoid the slow trees so I'm trying to use evalWithTimeout to skip them. So far I'm having problems because I can't make it kill slow tasks without also killing the loop. My problem is similar to this question but the solution to that question hasn't helped me.

library(TreeSim)
library(R.utils)
for (i in 1:100){
  tryCatch(
    expr = {
      evalWithTimeout(sim.rateshift.taxa(10,1,c(0.5,2),c(0.5,0),
                                         c(1,1),c(0,0.5),complete=F),
      timeout=0.005)
    }, 
    TimeoutException = function(ex) cat("Timeout. Skipping.\n")
  )
  print(i)
}

This is what I have so far. I would like to it continue printing "i" regardless of whether the simulation goes over the time limit, but currently it gives me "reached CPU time limit" errors and stops.


Solution

  • Using https://www.rdocumentation.org/packages/R.utils/versions/2.5.0/topics/withTimeout as a source. Here's a test unit that works as expected.

    foo = function() {
        print("Tic");
        x <- ceiling(runif(1) * 100)+1;
        for (kk in 1:x) {
            print(kk);
            Sys.sleep(runif(1));
        }
        print("Tac");
    }
    
    bar = function() { 
      for (i in 1:100) { 
        tryCatch({
          res <- withTimeout({
            foo();
         }, timeout=1.08);
        }, TimeoutException=function(ex) {
            cat("Timeout. Skipping.\n");
           }); 
        print(i); 
       } 
    }
    

    So the question is, is there an error that is thrown by interrupting by sim.rateshift.taxa that is not being caught, use error as thc mentions in order to catch that but use the TimeoutException to skip over proper timeouts

    There is also a problem with setting too low a time limit:

    https://github.com/mhahsler/arules/issues/22

    You may want to simply use setTimeLimit yourself and ensure that transient is set to TRUE that way you have finer control.

    Here's an example taken from http://blog.revolutionanalytics.com/2014/10/r-in-production-controlling-runtime.html

    system.time(Sys.sleep(5))
    
    ##user system elapsed 
    ## 0.000 0.000 5.005
    
    system.time(local({
      setTimeLimit(elapsed = 1, transient = TRUE)
      Sys.sleep(5)
    }))
    
    ## Error in Sys.sleep(5): reached elapsed time limit
    
    ## Timing stopped at: 0 0 5.006