<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/boost-the-speed-of-r-calls-from-rcpp/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.enchufa2.es/archives/boost-the-speed-of-r-calls-from-rcpp.html"> R – Enchufa2</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>If you are a user who needs to work with <code>Rcpp</code>-based packages, or you are a maintainer of one of such packages, you may be interested in the recent development of the unwind API, which can be leveraged to boost performance since <a rel="nofollow" href="http://dirk.eddelbuettel.com/blog/2018/07/23/#rcpp_0.12.18" target="_blank">the last <code>Rcpp</code> update</a>. In a nutshell, until R 3.5.0, every R call from C++ code was executed inside a try-catch, which is really slow, to avoid breaking things apart. From v3.5.0 on, this API provides a new and safe fast evaluation path for such calls.</p>
<div>
<h3>Some motivation</h3>
<p>Here is a small comparison of the old and the new APIs. The following toy example just calls an R function <code>N</code> times from C++. A pure R <code>for</code> loop is also provided as a reference.</p>
<pre><code>Rcpp::cppFunction(<span>'
void old_api(Function func, int n) {
for (int i=0; i&lt;n; i++) func();
}
'</span>)

Rcpp::cppFunction(plugins = <span>&quot;unwindProtect&quot;</span>, <span>'
void new_api(Function func, int n) {
for (int i=0; i&lt;n; i++) func();
}
'</span>)

reference &lt;- <span>function</span>(func, N) {
  <span>for</span> (i <span>in</span> <span>1</span>:N) func()
}

func &lt;- <span>function</span>() <span>1</span>
N &lt;- <span>1e6</span>

system.time(old_api(func, N))</code></pre>
<pre><code>##    user  system elapsed 
##  17.863   0.006  17.950</code></pre>
<pre><code>system.time(new_api(func, N))</code></pre>
<pre><code>##    user  system elapsed 
##   0.289   0.000   0.290</code></pre>
<pre><code>system.time(reference(func, N))</code></pre>
<pre><code>##    user  system elapsed 
##   0.216   0.000   0.217</code></pre>
<p>Obviously, there is still some penalty compared to not switching between domains, but the performance gain with respect to the old API is outstanding.</p>
</div>
<div>
<h3>A real-world example</h3>
<p>This is a quite heavy simulation of an M/M/1 system using <code>simmer</code>:</p>
<pre><code><span>library</span>(simmer)

system.time({
  mm1 &lt;- trajectory() %>%
    seize(<span>&quot;server&quot;</span>, <span>1</span>) %>%
    timeout(<span>function</span>() rexp(<span>1</span>, <span>66</span>)) %>%
    release(<span>&quot;server&quot;</span>, <span>1</span>)

  env &lt;- simmer() %>%
    add_resource(<span>&quot;server&quot;</span>, <span>1</span>) %>%
    add_generator(<span>&quot;customer&quot;</span>, mm1, <span>function</span>() rexp(<span>50</span>, <span>60</span>), mon=<span>F</span>) %>%
    run(<span>10000</span>, progress=progress::progress_bar$new()$update)
})</code></pre>
<p>In my system, it takes around <strong>17 seconds</strong> with the old API. The new API makes it in <strong>less than 5 seconds</strong>. As a reference, if we avoid R calls in the <code>timeout</code> activity and precompute all the arrivals instead of defining a dynamic generator, i.e.:</p>
<pre><code>system.time({
  input &lt;- data.frame(
    time = rexp(<span>10000</span>*<span>60</span>, <span>60</span>),
    service = rexp(<span>10000</span>*<span>60</span>, <span>66</span>)
  )

  mm1 &lt;- trajectory() %>%
    seize(<span>&quot;server&quot;</span>, <span>1</span>) %>%
    timeout_from_attribute(<span>&quot;service&quot;</span>) %>%
    release(<span>&quot;server&quot;</span>, <span>1</span>)

  env &lt;- simmer() %>%
    add_resource(<span>&quot;server&quot;</span>, <span>1</span>) %>%
    add_dataframe(<span>&quot;customer&quot;</span>, mm1, input, mon=<span>F</span>, batch=<span>50</span>) %>%
    run(<span>10000</span>, progress=progress::progress_bar$new()$update)
})</code></pre>
<p>then the simulation takes <strong>around 2.5 seconds</strong>.</p>
</div>
<div>
<h3>How to start using this feature</h3>
<p>First of all, you need R >= 3.5.0 and Rcpp >= 0.12.18 installed. Then, if you are a user, the easiest way to enable this globally is to add <code>CPPFLAGS += -DRCPP_USE_UNWIND_PROTECT</code> to your <code>~/.R/Makevars</code>. Packages installed or re-installed, as well as functions compiled with <code>Rcpp::sourceCpp</code> and <code>Rcpp::cppFunction</code>, will benefit from this performance gains. If you are a package maintainer, you can add <code>-DRCPP_USE_UNWIND_PROTECT</code> to your package’s <code>PKG_CPPFLAGS</code> in <code>src/Makevars</code>. Alternatively, there is a plugin available, so this flag can be enabled by adding <code>[[Rcpp::plugins(unwindProtect)]]</code> to one of your source files.</p>
<p>Note that this is fairly safe according to reverse dependency checks, but there might be still issues in some packages. But the sooner we start testing this feature and reporting possible issues, the sooner it will be enabled by default in <code>Rcpp</code>.</p>
</div>
<p><em>Article originally published in Enchufa2.es: <a rel="nofollow" href="https://www.enchufa2.es/archives/boost-the-speed-of-r-calls-from-rcpp.html" target="_blank">Boost the speed of R calls from Rcpp</a></em>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://www.enchufa2.es/archives/boost-the-speed-of-r-calls-from-rcpp.html"> R – Enchufa2</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/slxN4iTcZ1U" height="1"></a></div>