<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>callr | A Random Walk</title>
    <link>https://jchau.org/tag/callr/</link>
      <atom:link href="https://jchau.org/tag/callr/index.xml" rel="self" type="application/rss+xml" />
    <description>callr</description>
    <generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Tue, 02 Feb 2021 00:00:00 +0000</lastBuildDate>
    <image>
      <url>https://jchau.org/images/icon_hu420b60820276999b9c035da28fba099e_7100_512x512_fill_lanczos_center_3.png</url>
      <title>callr</title>
      <link>https://jchau.org/tag/callr/</link>
    </image>
    
    <item>
      <title>Tracking Stan sampling progress in Shiny</title>
      <link>https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/</link>
      <pubDate>Tue, 02 Feb 2021 00:00:00 +0000</pubDate>
      <guid>https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/</guid>
      <description>
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/d3/d3.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/dagre/dagre-d3.min.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/mermaid/dist/mermaid.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/mermaid/dist/mermaid.slim.min.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/DiagrammeR-styles/styles.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/chromatography/chromatography.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/DiagrammeR-binding/DiagrammeR.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;The &lt;a href=&#34;https://jchau.org/2021/02/01/running-stan-models-in-shiny&#34;&gt;previous post&lt;/a&gt; demonstrates the use of pre-compiled &lt;a href=&#34;https://mc-stan.org/&#34;&gt;Stan&lt;/a&gt; models in interactive &lt;a href=&#34;https://shiny.rstudio.com/&#34;&gt;R Shiny&lt;/a&gt; applications to avoid unnecessary Stan model (re-)compilation on application start-up. In this short follow-up post we go a step further and tackle the issue of tracking the Stan model sampling progress itself in a shiny-application. The idea, mainly inspired by &lt;a href=&#34;https://discindo.org/post/asynchronous-execution-in-shiny/&#34;&gt;this blog post&lt;/a&gt;, is to execute the Stan model sampling in a separate background R process using the convenient &lt;a href=&#34;https://callr.r-lib.org/&#34;&gt;&lt;code&gt;callr&lt;/code&gt;&lt;/a&gt;-package to avoid blocking of the shiny-application.&lt;/p&gt;
&lt;div id=&#34;demo-shiny-app&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Demo Shiny-app&lt;/h2&gt;
&lt;p&gt;For illustration purposes, we start from the basic shiny-app in the previous post that fits a simple linear model in Stan and plots the sampled posteriors:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(shiny)

ui &amp;lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput(&amp;quot;N&amp;quot;, label = &amp;quot;N&amp;quot;, value = 10)
    ),
    mainPanel(
      plotOutput(&amp;quot;posteriors&amp;quot;)
    )
  )
)

server &amp;lt;- function(input, output, session) {
  ## draw samples 
  draws &amp;lt;- reactive({
    N &amp;lt;- input$N
    rstan::sampling(
      object = shinyStanModels:::stanmodels[[&amp;quot;lm&amp;quot;]],
      data = list(N = N, x = seq_len(N), y = rnorm(N, seq_len(N), 0.1)),
      chains = 2,
      iter = 1000
    )
  })
  ## plot histograms
  output$posteriors &amp;lt;- renderPlot({
    req(draws())
    op &amp;lt;- par(mfrow = c(1, 2), cex = 1.25)
    hist(rstan::extract(draws(), &amp;quot;alpha&amp;quot;)[[1]], main = bquote(&amp;quot;Posterior samples&amp;quot;~alpha), xlab = expression(alpha))
    hist(rstan::extract(draws(), &amp;quot;beta&amp;quot;)[[1]], main = bquote(&amp;quot;Posterior samples&amp;quot;~beta), xlab = expression(beta))
    par(op)
  })
  
}

shinyApp(ui = ui, server = server)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/figure-html/app.gif&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: here the pre-compiled &lt;code&gt;&#34;lm&#34;&lt;/code&gt; Stan model is called from a dummy R-package &lt;code&gt;shinyStanModels&lt;/code&gt; as explained &lt;a href=&#34;%5Bprevious%20post%5D(/2021/02/01/running-stan-models-in-shiny)&#34;&gt;previously&lt;/a&gt; to avoid model recompilation every time the shiny-app is launched.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;shiny-app-blocking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shiny-app blocking&lt;/h2&gt;
&lt;p&gt;By increasing the number observations &lt;span class=&#34;math inline&#34;&gt;\(N\)&lt;/span&gt;, we also increase the execution time of the MCMC sampling process. Setting e.g. &lt;span class=&#34;math inline&#34;&gt;\(N = 500\)&lt;/span&gt;, it already takes quite a while for the computations to complete&lt;a href=&#34;#fn1&#34; class=&#34;footnote-ref&#34; id=&#34;fnref1&#34;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. Unfortunately, there is no way to tell from the shiny-app whether the sampling iterations are progressing quickly or still require a long time to finish. In an interactive R-session, the progress of the sampling iterations across individual chains is either printed to the console (that is, the current &lt;code&gt;stdout&lt;/code&gt; connection) or to a temporary file when multiple chains are being sampled in parallel. It would be great if we could divert these progress messages to the shiny-app itself, so that the sampling iterations can be tracked in real-time in the same way as in any interactive R-session.&lt;/p&gt;
&lt;p&gt;A first idea that comes to mind is to make use of shiny’s &lt;code&gt;reactivePoll()&lt;/code&gt; or &lt;code&gt;reactiveFileReader()&lt;/code&gt; to periodically read the contents of the temporary progress file generated by Stan, and display these contents in reactively in the shiny-app. The problem, however, is that due to shiny’s synchronous reactive nature the shiny-app is effectively &lt;strong&gt;blocked&lt;/strong&gt; while executing the sampling process, and the &lt;code&gt;reactiveFileReader()&lt;/code&gt; will only have a chance to read the progress file when the model sampling is already finished, thereby defeating its purpose.&lt;/p&gt;
&lt;p&gt;Instead, we have to somehow detach the slow model sampling process from the main shiny-app process so that both processes do not interfere with each other and the shiny-app is free to execute other requests. In fact, what is needed is a way to launch the sampling process in a separate background R-process, and, as it turns out, this is exactly what is provided by the convenient &lt;code&gt;callr&lt;/code&gt;-package.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;unblocking-a-shiny-app-with-callr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Unblocking a shiny-app with &lt;code&gt;callr&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In order to execute the Stan model sampling procedure in a separate R-process, we wrap the call to &lt;code&gt;rstan::sampling()&lt;/code&gt; in a function and pass it to the &lt;code&gt;func&lt;/code&gt; argument of &lt;code&gt;callr::r_bg()&lt;/code&gt;. The function is evaluated in a background R-process and may take a long time to complete, but &lt;code&gt;callr::r_bg()&lt;/code&gt; &lt;strong&gt;immediately&lt;/strong&gt; returns control to the current R-process so that it is free to perform other operations:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(callr)

## launch job in separate R process
r_process &amp;lt;- r_bg(
  func = function(N) {
    rstan::sampling(
      object = shinyStanModels:::stanmodels[[&amp;quot;lm&amp;quot;]],
      data = list(N = N, x = seq_len(N), y = rnorm(N, seq_len(N), 0.1)),
      open_progress = FALSE,
      chains = 2,
      iter = 1000
    )
  },
  args = list(N = 500)
)

## the process object is returned immediately
## and can be polled from the current R process
r_process
#&amp;gt; PROCESS &amp;#39;R&amp;#39;, running, pid 31672.

## check if job is still running
r_process$is_alive()
#&amp;gt; [1] TRUE

## result is not yet available
tryCatch(r_process$get_result(), error = function(e) e$message)
#&amp;gt; [1] &amp;quot;Still alive&amp;quot;

## extract the result when the job is finished
system.time({
  r_process$wait()
})
#&amp;gt;    user  system elapsed 
#&amp;gt;  22.239   0.099  22.247
r_process
#&amp;gt; PROCESS &amp;#39;R&amp;#39;, finished.
r_process$get_result()
#&amp;gt; Inference for Stan model: lm.
#&amp;gt; 2 chains, each with iter=1000; warmup=500; thin=1; 
#&amp;gt; post-warmup draws per chain=500, total post-warmup draws=1000.
#&amp;gt; 
#&amp;gt;         mean se_mean   sd   2.5%    25%    50%    75%  97.5% n_eff Rhat
#&amp;gt; alpha   0.02    0.00 0.01   0.00   0.01   0.02   0.03   0.04   248 1.01
#&amp;gt; beta    1.00    0.00 0.00   1.00   1.00   1.00   1.00   1.00   338 1.01
#&amp;gt; sigma   0.10    0.00 0.00   0.09   0.10   0.10   0.10   0.10   293 1.00
#&amp;gt; lp__  909.03    0.07 1.23 905.93 908.46 909.40 909.93 910.40   296 1.01
#&amp;gt; 
#&amp;gt; Samples were drawn using NUTS(diag_e) at Mon Apr 12 09:00:15 2021.
#&amp;gt; For each parameter, n_eff is a crude measure of effective sample size,
#&amp;gt; and Rhat is the potential scale reduction factor on split chains (at 
#&amp;gt; convergence, Rhat=1).&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: launching a separate R-process does not necessarily require a multi-core processor and also works using only a single-core processor. On the other hand, the R-session does need to have sufficient permission/rights to launch a separate R-process on the system.&lt;/p&gt;
&lt;div id=&#34;demo-shiny-app-continued&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Demo Shiny-app (continued)&lt;/h2&gt;
&lt;p&gt;In a first step, we update the shiny-app by wrapping the &lt;code&gt;rstan::sampling()&lt;/code&gt; call in a call to &lt;code&gt;callr::r_bg()&lt;/code&gt; so that the execution of the model sampling no longer blocks the shiny-app process. Using the &lt;code&gt;stdout&lt;/code&gt; argument of &lt;code&gt;callr::r_bg()&lt;/code&gt; we can divert&lt;a href=&#34;#fn2&#34; class=&#34;footnote-ref&#34; id=&#34;fnref2&#34;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; all messages generated by &lt;code&gt;rstan::sampling()&lt;/code&gt; (and printed to &lt;code&gt;stdout&lt;/code&gt;) to a temporary file &lt;code&gt;tfile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Whenever the number of observations &lt;span class=&#34;math inline&#34;&gt;\(N\)&lt;/span&gt; is changed and a new background R-process is launched, we instruct the shiny-app to start polling the process object (&lt;code&gt;r$bg_process&lt;/code&gt;) by updating the reactive value &lt;code&gt;r$poll&lt;/code&gt;. This will trigger an observer to: (1) read and assign the contents of the progress file &lt;code&gt;tfile&lt;/code&gt; to a reactive value &lt;code&gt;r$progress&lt;/code&gt; whenever the progress file has been modified; (2) check if the background process has finished executing and if this is the case retrieve the sampling results. The observer will be re-executed every second and only stops re-executing when the background process is no longer alive and &lt;code&gt;r$poll&lt;/code&gt; has been turned off (i.e. set to &lt;code&gt;FALSE&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The progress messages can now be rendered in real-time in the shiny-app by simply pasting the contents of the reactive value &lt;code&gt;r$progress&lt;/code&gt;. The posterior histograms only need to be updated whenever new sampling results are available in the reactive value &lt;code&gt;r$draws&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In short, we can summarize the updated shiny-app with the following graph:&lt;/p&gt;
&lt;div id=&#34;htmlwidget-1&#34; style=&#34;width:100%;height:350px;&#34; class=&#34;DiagrammeR html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-1&#34;&gt;{&#34;x&#34;:{&#34;diagram&#34;:&#34;\ngraph TB\n   A[Update N] --&gt; B[Start sampling in background process];\n   B --&gt; B2[Background process is alive?];\n   B2 --&gt;|Yes| C[\&#34;Read progress file (if modified)\&#34;];\n   C --&gt; B2;\n   B2 --&gt;|No| F1[Extract sampling results];\n   F1 --&gt; G[Plot posterior histograms];\n  &#34;},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;p&gt;More importantly, the updated shiny-app –including model sampling progress– now looks as follows:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(shiny)

ui &amp;lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput(&amp;quot;N&amp;quot;, label = &amp;quot;N&amp;quot;, value = 10)
    ),
    mainPanel(
      plotOutput(&amp;quot;posteriors&amp;quot;),
      hr(),
      ## limit the height of the progress message box
      tags$head(tags$style(&amp;quot;#progress{overflow-y:scroll; max-height: 500px;}&amp;quot;)),
      verbatimTextOutput(&amp;quot;progress&amp;quot;)
    )
  )
)

server &amp;lt;- function(input, output, session) {
  
  ## file to write progress
  tfile &amp;lt;- tempfile(fileext = &amp;quot;.txt&amp;quot;)
  
  ## reactive values
  r &amp;lt;- reactiveValues(
    progress_mtime = -1
  )
  
  observeEvent(input$N, {
    ## start sampling in background process
    r$bg_process &amp;lt;- callr::r_bg(
      ## this is a long running computation
      func = function(N) {
        rstan::sampling(
          object = shinyStanModels:::stanmodels[[&amp;quot;lm&amp;quot;]],
          data = list(N = N, x = seq_len(N), y = rnorm(N, seq_len(N), 0.1)),
          open_progress = FALSE,
          iter = 1000,
          chains = 2
        )
      },
      args = list(N = input$N),
      stdout = tfile,
      supervise = TRUE
    )
    ## start polling bg process
    r$poll &amp;lt;- TRUE   
  })
  
  ## observe status of bg process
  observe({
    req(r$bg_process, r$poll)
    ## keep re-executing observer as 
    ## long as bg process is running
    invalidateLater(millis = 1000, session)
    ## read current progress if file is modified
    mtime &amp;lt;- file.info(tfile)$mtime
    if(mtime &amp;gt; r$progress_mtime) {
      r$progress &amp;lt;- readLines(tfile) 
      r$progress_mtime &amp;lt;- mtime
    }
    ## extract draws when bg process is finished
    if(!r$bg_process$is_alive()) {
      r$draws &amp;lt;- r$bg_process$get_result()
      r$poll &amp;lt;- FALSE  ## stop polling bg process
    } 
  })
  
  ## plot histograms
  output$posteriors &amp;lt;- renderPlot({
    req(r$draws)
    op &amp;lt;- par(mfrow = c(1, 2), cex = 1.25)
    hist(rstan::extract(r$draws, &amp;quot;alpha&amp;quot;)[[1]], main = bquote(&amp;quot;Posterior samples&amp;quot;~alpha), xlab = expression(alpha))
    hist(rstan::extract(r$draws, &amp;quot;beta&amp;quot;)[[1]], main = bquote(&amp;quot;Posterior samples&amp;quot;~beta), xlab = expression(beta))
    par(op)
  })
  
  ## print progress
  output$progress &amp;lt;- renderText({
    req(r$progress)
    paste(r$progress, collapse = &amp;quot;\n&amp;quot;)
  })
  
}

shinyApp(ui = ui, server = server)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34; style=&#34;text-align: center&#34;&gt;&lt;span id=&#34;fig:unnamed-chunk-5&#34;&gt;&lt;/span&gt;
&lt;img src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/figure-html/app1.gif&#34; alt=&#34;Progress of sampling iterations with two chains (in parallel) on a multi-core processor&#34; width=&#34;100%&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;
Figure 1: Progress of sampling iterations with two chains (in parallel) on a multi-core processor
&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;figure&#34; style=&#34;text-align: center&#34;&gt;&lt;span id=&#34;fig:unnamed-chunk-6&#34;&gt;&lt;/span&gt;
&lt;img src=&#34;https://jchau.org/2021/02/02/tracking-stan-sampling-progress-shiny/index_files/figure-html/app2.gif&#34; alt=&#34;Progress of sampling iterations with two chains (in sequence) on a single-core processor[^3]&#34; width=&#34;100%&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;
Figure 2: Progress of sampling iterations with two chains (in sequence) on a single-core processor&lt;a href=&#34;#fn3&#34; class=&#34;footnote-ref&#34; id=&#34;fnref3&#34;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;session-info&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Session Info&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; R version 4.0.2 (2020-06-22)
#&amp;gt; Platform: x86_64-pc-linux-gnu (64-bit)
#&amp;gt; Running under: Ubuntu 18.04.5 LTS
#&amp;gt; 
#&amp;gt; Matrix products: default
#&amp;gt; BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
#&amp;gt; LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
#&amp;gt; 
#&amp;gt; locale:
#&amp;gt;  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#&amp;gt;  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#&amp;gt;  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#&amp;gt;  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#&amp;gt;  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#&amp;gt; [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#&amp;gt; 
#&amp;gt; attached base packages:
#&amp;gt; [1] stats     graphics  grDevices utils     datasets  methods   base     
#&amp;gt; 
#&amp;gt; other attached packages:
#&amp;gt; [1] callr_3.5.1
#&amp;gt; 
#&amp;gt; loaded via a namespace (and not attached):
#&amp;gt;  [1] rstan_2.21.2         tidyselect_1.1.0     xfun_0.22           
#&amp;gt;  [4] bslib_0.2.4          purrr_0.3.4          V8_3.4.0            
#&amp;gt;  [7] colorspace_2.0-0     vctrs_0.3.6          generics_0.1.0      
#&amp;gt; [10] htmltools_0.5.1.1    stats4_4.0.2         loo_2.4.1           
#&amp;gt; [13] yaml_2.2.1           rlang_0.4.10         pkgbuild_1.2.0      
#&amp;gt; [16] jquerylib_0.1.3      pillar_1.4.7         DBI_1.1.1           
#&amp;gt; [19] glue_1.4.2           withr_2.4.1          RColorBrewer_1.1-2  
#&amp;gt; [22] matrixStats_0.58.0   lifecycle_0.2.0      stringr_1.4.0       
#&amp;gt; [25] munsell_0.5.0        blogdown_1.2         gtable_0.3.0        
#&amp;gt; [28] visNetwork_2.0.9     htmlwidgets_1.5.3    codetools_0.2-16    
#&amp;gt; [31] evaluate_0.14        inline_0.3.17        knitr_1.31          
#&amp;gt; [34] ps_1.5.0             shinyStanModels_0.1  DiagrammeR_1.0.6.1  
#&amp;gt; [37] parallel_4.0.2       curl_4.3             highr_0.8           
#&amp;gt; [40] Rcpp_1.0.6           scales_1.1.1         RcppParallel_5.0.2  
#&amp;gt; [43] StanHeaders_2.21.0-7 jsonlite_1.7.2       gridExtra_2.3       
#&amp;gt; [46] ggplot2_3.3.3        digest_0.6.27        stringi_1.5.3       
#&amp;gt; [49] bookdown_0.21        processx_3.4.5       dplyr_1.0.4         
#&amp;gt; [52] grid_4.0.2           cli_2.3.0            tools_4.0.2         
#&amp;gt; [55] magrittr_2.0.1       sass_0.3.1           tibble_3.0.6        
#&amp;gt; [58] crayon_1.4.1         pkgconfig_2.0.3      ellipsis_0.3.1      
#&amp;gt; [61] prettyunits_1.1.1    assertthat_0.2.1     rmarkdown_2.6.6     
#&amp;gt; [64] R6_2.5.0             compiler_4.0.2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn1&#34;&gt;&lt;p&gt;this Stan program could be made more efficient by specifying reasonable priors, but that is not the purpose of this illustration.&lt;a href=&#34;#fnref1&#34; class=&#34;footnote-back&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&#34;fn2&#34;&gt;&lt;p&gt;this approach also works when multiple chains are sampled in parallel, i.e. if the &lt;code&gt;cores&lt;/code&gt; argument in &lt;code&gt;rstan::sampling()&lt;/code&gt; is larger than 1.&lt;a href=&#34;#fnref2&#34; class=&#34;footnote-back&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&#34;fn3&#34;&gt;&lt;p&gt;here the shiny-app is launched in an isolated docker container with a limit on the cpu-usage (&lt;a href=&#34;https://docs.docker.com/config/containers/resource_constraints/#cpu&#34; class=&#34;uri&#34;&gt;https://docs.docker.com/config/containers/resource_constraints/#cpu&lt;/a&gt;)&lt;a href=&#34;#fnref3&#34; class=&#34;footnote-back&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
