Search code examples
rparallel-processingprogress-barpurrrfurrr

How to increment a shared counter between parallel processes from the furrr package?


The example below parallelizes 64 Sys.sleep(1) instructions using the furrr package.

The package progressr is used to display the progression of the parallel execution.

This package allows to update some text details where I want to show the count of the number of terminated instructions.

But I do not know how to share a counter between the furrr process so with my 8-core cpu it shows 8/64 at max as you can see:

enter image description here


library(furrr)
library(progressr)

handlers("progress")

long_process <- function(items) {

  nb_of_cores <- parallel::detectCores()
  plan(multisession, workers = nb_of_cores)

  N <- length(items)
  p <- progressr::progressor(along = items)

  n <- 0

  item_process <- function(item) {
    n <<- n + 1
    p(paste(n, "/", N))
    Sys.sleep(1)
  }

  future_walk(items, item_process)
}

with_progress(long_process(1:64))

Solution

  • Example showing how to customize the progress package handler taken from https://progressr.futureverse.org/#further-configuration-of-progress-handlers:

    library(furrr)
    library(progressr)
    
    ## Use the 'progress' package with custom format output for
    ## progress reporting, 
    handlers(handler_progress(
      format = ":spin :current/:total [:bar] :percent"
    ))
      
    ## Parallelize on the local machine using all available cores
    ## Comment: Avoid putting this inside functions; leave it to
    ## the end-user to control this
    plan(multisession)
    
    
    long_process <- function(items) {
      p <- progressr::progressor(along = items)
      item_process <- function(item) {
        p()
        Sys.sleep(1)
      }
      future_walk(items, item_process)
    }
    
    with_progress(long_process(1:64))
    

    This gives a progress bar in the terminal that looks like:

    / 19/64 [============>------------------------------]  30%
    

    Note that progress is superseded by the cli package. To achieve the same using the cli handler, use:

    handlers(handler_cli(
      type = "tasks",
      format = "{cli::pb_spin} {cli::pb_current}/{cli::pb_total} {cli::pb_bar} {cli::pb_percent}"
    ))
    

    That will render like:

    ⠼ 19/64 ■■■■■■■■■                       30%