<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/"></div></div><div><a data-url="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/" data-counturl="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/" data-count="horizontal" data-text="Asynchronous and Distributed Programming in R with the Future Package" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://alexioannides.com/2016/11/02/asynchronous-and-distributed-programming-in-r-with-the-future-package/"> R – When Localhost Isn't Enough</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img title="the_future" alt="Alt" src="https://i1.wp.com/alexioannides.files.wordpress.com/2016/11/the_future.jpg?w=456&ssl=1" data-recalc-dims="1"></p>
<p>Every now and again someone comes along and writes an R package that I consider to be a ‘game changer’ for the language and it’s application to Data Science. For example, I consider <a title="dplyr on GitHub" target="_blank" rel="nofollow" href="https://github.com/hadley/dplyr">dplyr</a> one such package as it has made data munging/manipulation <em>that</em> more intuitive and more productive than it had been before. Although I only first read about it at the beginning of this week, my instinct tells me that in <a title="Henrik Bengtsson on LinkedIn" target="_blank" rel="nofollow" href="https://www.linkedin.com/in/henrikbengtsson">Henrik Bengtsson’s</a> <a title="future package in GitHub" target="_blank" rel="nofollow" href="https://github.com/HenrikBengtsson/future">future</a> package we might have another such game-changing R package.</p>
<p>The <a title="future package in GitHub" target="_blank" rel="nofollow" href="https://github.com/HenrikBengtsson/future">future</a> package provides an API for futures (or promises) in R. To quote Wikipedia, a <a title="Wikipedia on futures and promises" target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Futures_and_promises">future or promise</a> is,</p>
<blockquote><p>
<em>… a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.</em>
</p>
</blockquote>
<p><span></span></p>
<p>A classic example would be a request made to a web server via HTTP, that has yet to return and whose value remains unknown until it does (and which has promised to return at some point in the future). This ‘promise’ is an object assigned to a variable in R like any other, and allows code execution to progress until the moment the code explicitly requires the future to be resolved (i.e. to ‘make good’ on it’s promise). So the code does not need to wait for the web server until the very moment that the information anticipated in its response it actually needed. In the intervening execution time we can send requests to other web servers, run some other computations, etc. Ultimately, this leads to <strong>faster</strong> and <strong>more efficient code</strong>. This way of working also opens the door to distributed (i.e. parallel) computation, as the computation assigned to each new future can be executed on a new thread (and executed on a different core on the same machine, or on another machine/node).</p>
<p>The future API is extremely expressive and the associated documentation is excellent. My motivation here is not to repeat any of this, but rather to give a few examples to serve as inspiration for how futures could be used for day-to-day Data Science tasks in R.</p>
<h1>Creating a Future to be Executed on a Different Core to that Running the Main Script</h1>
<p>To demonstrate the syntax and structure required to achieve this aim, I am going to delegate to a future the task of estimating the mean of 10 million random samples from the normal distribution, and ask it to spawn a new R process on a different core in order to do so. The code to achieve this is as follows,</p>
<pre>
library(future)

f &lt;- future({
  samples &lt;- rnorm(10000000)
  mean(samples)
}) %plan% multiprocess
w &lt;- value(f)
w
# [1] 3.046653e-05
</pre>
<ul>
<li><code>future({...})</code> assigns the code (actually a construct known as a <a title="Hadley Wickham on closures" target="_blank" rel="nofollow" href="http://adv-r.had.co.nz/Functional-programming.html#closures">closure</a>), to be computed asynchronously from the main script. The code will be start execution the moment this initial assignment is made;</li>
<li><code>%plan% multiprocess</code> sets the future’s execution plan to be on a different core (or thread); and,</li>
<li><code>value</code> asks for the return value of future. This will block further code execution until the future can be resolved.</li>
</ul>
<p>The above example can easily be turned into a function that outputs dots (<code>...</code>) to the console until the future can be resolved and return it’s value,</p>
<pre>
f_dots &lt;- function() {
  f &lt;- future({
    s &lt;- rnorm(10000000)
    mean(s)
  }) %plan% multiprocess

  while (!resolved(f)) {
    cat(&quot;...&quot;)
  }
  cat(&quot;\n&quot;)

  value(f)
}
f_dots()
# ............
# [1] -0.0001872372
</pre>
<p>Here, <code>resolved(f)</code> will return <code>FALSE</code> until the future <code>f</code> has finished executing.</p>
<h1>Useful Use Cases</h1>
<p>I can recall many situations where futures would have been handy when writing R scripts. The examples below are the most obvious that come to mind. No doubt there will be many more.</p>
<h2>Distributed (Parallel) Computation</h2>
<p>In the past, when I’ve felt the need to distribute a calculation I have usually used the <code>mclapply</code> function (i.e. multi-core <code>lapply</code>), from the <code>parallel</code> library that comes bundled together with base R. Computing the mean of 100 million random samples from the normal distribution would look something like,</p>
<pre>
library(parallel)

sub_means &lt;- mclapply(
              X = 1:4,
              FUN = function(x) { samples &lt;- rnorm(25000000); mean(samples) },
              mc.cores = 4)

final_mean &lt;- mean(unlist(sub_mean))
final_mean
# [1] -0.0002100956
</pre>
<p>Perhaps more importantly, the script will be ‘blocked’ until <code>sub_means</code> has finished executing. We can achieve the same end-result, but without blocking, using futures,</p>
<pre>
single_thread_mean &lt;- function() {
  samples &lt;- rnorm(25000000)
  mean(samples)
}

multi_thread_mean &lt;- function() {
  f1 &lt;- future({ single_thread_mean() }) %plan% multiprocess
  f2 &lt;- future({ single_thread_mean() }) %plan% multiprocess
  f3 &lt;- future({ single_thread_mean() }) %plan% multiprocess
  f4 &lt;- future({ single_thread_mean() }) %plan% multiprocess

  mean(value(f1), value(f2), value(f3), value(f4))
}

multi_thread_mean()
# [1] -4.581293e-05
</pre>
<p>We can compare computation time between the single and multi-threaded versions of the mean computation (using the <a title="microbenchmark on CRAN" target="_blank" rel="nofollow" href="https://cran.r-project.org/web/packages/microbenchmark/index.html">microbenchmark</a> package),</p>
<pre>
library(microbenchmark)

microbenchmark({ samples &lt;- rnorm(100000000); mean(samples) },
               multi_thread_mean(),
               times = 10)
# Unit: seconds
#                  expr      min       lq     mean   median       uq      max neval
#  single_thread(1e+08) 7.671721 7.729608 7.886563 7.765452 7.957930 8.406778    10
#   multi_thread(1e+08) 2.046663 2.069641 2.139476 2.111769 2.206319 2.344448    10
</pre>
<p>We can see that the multi-threaded version is nearly 3 times faster, which is not surprising given that we’re using 3 extra threads. Note that time is lost spawning the extra threads and combining their results (usually referred to as ‘overhead’), such that distributing a calculation can actually increase computation time if the benefit of parallelisation is less than the cost of the overhead.</p>
<h2>Non-Blocking Asynchronous Input/Output</h2>
<p>I have often found myself in the situation where I need to read several large CSV files, each of which can take a long time to load. Because the files can only be loaded sequentially, I have had to wait for one file to be read before the next one can start loading, which compounds the time devoted to input. Thanks to futures, we can can now achieve <a title="Wikipedia on asynchronous io" target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Asynchronous_I/O">asynchronous input and output</a> as follows,</p>
<pre>
library(readr)

df1 &lt;- future({ read_csv(&quot;data/csv1.csv&quot;) }) %plan% multiprocess
df2 &lt;- future({ read_csv(&quot;data/csv2.csv&quot;) }) %plan% multiprocess
df3 &lt;- future({ read_csv(&quot;data/csv3.csv&quot;) }) %plan% multiprocess
df4 &lt;- future({ read_csv(&quot;data/csv4.csv&quot;) }) %plan% multiprocess

df &lt;- rbind(value(df1), value(df2), value(df3), value(df4))
</pre>
<p>Running <code>microbenchmark</code> on the above code illustrates the speed-up (each file is ~50MB in size),</p>
<pre>
# Unit: seconds
#                   min       lq     mean   median       uq      max neval
#  synchronous 7.880043 8.220015 8.502294 8.446078 8.604284 9.447176    10
# asynchronous 4.203271 4.256449 4.494366 4.388478 4.490442 5.748833    10
</pre>
<p>The same pattern can be applied to making HTTP requests asynchronously. In the following example I make an asynchronous HTTP GET request to the OpenCPU public API, to retrieve the Boston housing dataset via JSON. While I’m waiting for the future to resolve the response I keep making more asynchronous requests, but this time to <code><a target="_blank" rel="nofollow" href="http://time.jsontest.com/">http://time.jsontest.com</a></code> to get the current time. Once the original future has resolved, I block output until all remaining futures have been resolved.</p>
<pre>
library(httr)
library(jsonlite)

time_futures &lt;- list()

data_future &lt;- future({
  response &lt;- GET(&quot;http://public.opencpu.org/ocpu/library/MASS/data/Boston/json&quot;)
  fromJSON(content(response, as = &quot;text&quot;))
}) %plan% multiprocess

while (!resolved(data_future)) {
  time_futures &lt;- append(time_futures, future({ GET(&quot;http://time.jsontest.com&quot;) }) %plan% multiprocess)
}
values(time_futures)
# [[1]]
# Response [http://time.jsontest.com/]
#   Date: 2016-11-02 01:31
#   Status: 200
#   Content-Type: application/json; charset=ISO-8859-1
#   Size: 100 B
# {
#    &quot;time&quot;: &quot;01:31:19 AM&quot;,
#    &quot;milliseconds_since_epoch&quot;: 1478050279145,
#    &quot;date&quot;: &quot;11-02-2016&quot;
# }

head(value(data_future))
# crim zn indus chas   nox    rm  age    dis rad tax ptratio  black lstat medv
# 1 0.0063 18  2.31    0 0.538 6.575 65.2 4.0900   1 296    15.3 396.90  4.98 24.0
# 2 0.0273  0  7.07    0 0.469 6.421 78.9 4.9671   2 242    17.8 396.90  9.14 21.6
# 3 0.0273  0  7.07    0 0.469 7.185 61.1 4.9671   2 242    17.8 392.83  4.03 34.7
# 4 0.0324  0  2.18    0 0.458 6.998 45.8 6.0622   3 222    18.7 394.63  2.94 33.4
# 5 0.0690  0  2.18    0 0.458 7.147 54.2 6.0622   3 222    18.7 396.90  5.33 36.2
# 6 0.0298  0  2.18    0 0.458 6.430 58.7 6.0622   3 222    18.7 394.12  5.21 28.7
</pre>
<p>The same logic applies to accessing databases and executing SQL queries via <a title="Wikipedia on ODBC" target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Open_Database_Connectivity">ODBC</a> or <a title="Wikipedia on JDBC" target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Java_Database_Connectivity">JDBC</a>. For example, large complex queries can be split into ‘chunks’ and sent asynchronously to the database server in order to have them executed on multiple server threads. The output can then be unified once the server has sent back the chunks, using R (e.g. with <a title="dplyr on GitHub" target="_blank" rel="nofollow" href="https://github.com/hadley/dplyr">dplyr</a>). This is a strategy that I have been using with Apache Spark, but I could now implement it within R. Similarly, multiple database tables can be accessed concurrently, and so on.</p>
<h1>Final Thoughts</h1>
<p>I have only really scratched the surface of what is possible with futures. For example, <a title="future package in GitHub" target="_blank" rel="nofollow" href="https://github.com/HenrikBengtsson/future">future</a> supports multiple execution plans including <code>lazy</code> and <code>cluster</code> (for multiple machines/nodes) – I have only focused on increasing performance on a single machine with multiple cores. If this post has provided some inspiration or left you curious, then head over to the official <a title="future package in GitHub" target="_blank" rel="nofollow" href="https://github.com/HenrikBengtsson/future">future docs</a> for the full details (which are a joy to read and work-through).</p>
<p> <a target="_blank" rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/alexioannides.wordpress.com/320/"><img alt="" src="http://feeds.wordpress.com/1.0/comments/alexioannides.wordpress.com/320/" border="0"></a> <img alt="" src="https://i1.wp.com/pixel.wp.com/b.gif?resize=1%2C1&ssl=1" border="0" data-recalc-dims="1"></p>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/"></div></div><div><a data-url="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/" data-counturl="https://www.r-bloggers.com/asynchronous-and-distributed-programming-in-r-with-the-future-package/" data-count="vertical" data-text="Asynchronous and Distributed Programming in R with the Future Package" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://alexioannides.com/2016/11/02/asynchronous-and-distributed-programming-in-r-with-the-future-package/"> R – When Localhost Isn't Enough</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 title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/?s=Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/Stz-bTSQO_o"></a></div>