<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/a-guide-to-parallelism-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://privefl.github.io/blog/a-guide-to-parallelism-in-r/"> blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<section>
<p>In this post, I will talk about parallelism in R. This post will likely be biased towards the solutions I use. For example, I never use <code>mcapply</code> nor <code>clusterApply</code>. I prefer to always use <code>foreach</code>. In this post, we will focus on <strong>how to parallelize R code on your computer</strong>.</p>
<p>I will use mainly silly examples, just to show one point at a time.</p>
<div>
<h2>Basics of foreach</h2>
<p>You can install the <strong>foreach</strong> package with <code>install.packages(&quot;foreach&quot;)</code>.</p>
<div>
<pre><code><span>library</span>(foreach)

<span>foreach</span>(<span>i =</span> <span>1</span>:<span>3</span>) %do%<span> </span>{
  <span>sqrt</span>(i)
}</code></pre>
</div>
<pre><code>## [[1]]
## [1] 1
## 
## [[2]]
## [1] 1.414214
## 
## [[3]]
## [1] 1.732051</code></pre>
<p>So, in the example above, you iterate on <code>i</code> and apply the expression <code>sqrt(i)</code>. <code>foreach</code> returns a list by default. A common mistake is to think that <code>foreach</code> is like a for-loop. Actually, <strong><code>foreach</code> is more like <code>lapply</code></strong>.</p>
<div>
<pre><code><span>lapply</span>(<span>1</span>:<span>3</span>, function(i) {
  <span>sqrt</span>(i)
})</code></pre>
</div>
<pre><code>## [[1]]
## [1] 1
## 
## [[2]]
## [1] 1.414214
## 
## [[3]]
## [1] 1.732051</code></pre>
<p>Parameter <code>.combine</code> is very useful.</p>
<div>
<pre><code><span>foreach</span>(<span>i =</span> <span>1</span>:<span>3</span>, <span>.combine =</span> <span>'c'</span>) %do%<span> </span>{
  <span>sqrt</span>(i)
}</code></pre>
</div>
<pre><code>## [1] 1.000000 1.414214 1.732051</code></pre>
<p>With <code>lapply</code>, we would do</p>
<div>
<pre><code>res &lt;-<span> </span><span>lapply</span>(<span>1</span>:<span>3</span>, function(i) {
  <span>sqrt</span>(i)
})
<span>do.call</span>(<span>'c'</span>, res)</code></pre>
</div>
<pre><code>## [1] 1.000000 1.414214 1.732051</code></pre>
</div>
<div>
<h2>Parallelize with foreach</h2>
<p>You need to do at least two things:</p>
<ul>
<li>replace <code>%do%</code> by <code>%dopar%</code>. Basically, always use <code>%dopar%</code> because you can use <code>registerDoSEQ()</code> is you really want to run the <code>foreach</code> sequentially.</li>
<li>register a parallel backend using one of the packages that begin with <em>do</em> (such as <code>doParallel</code>, <code>doMC</code>, <code>doMPI</code> and more). I will list only the two main parallel backends because there are too many of them.</li>
</ul>
<div>
<h3>Using clusters</h3>
<div>
<pre><code><span># Example registering clusters</span>
cl &lt;-<span> </span>parallel::<span>makeCluster</span>(<span>2</span>)
doParallel::<span>registerDoParallel</span>(cl)
<span>foreach</span>(<span>i =</span> <span>1</span>:<span>3</span>, <span>.combine =</span> <span>'c'</span>) %dopar%<span> </span>{
  <span>sqrt</span>(i)
}</code></pre>
</div>
<pre><code>## [1] 1.000000 1.414214 1.732051</code></pre>
<div>
<pre><code>parallel::<span>stopCluster</span>(cl)</code></pre>
</div>
<p>In this situation, all the data and packages used must be exported (copied) to the clusters, which can add some overhead. Yet, at least, you know what you do.</p>
</div>
<div>
<h3>Using forking</h3>
<div>
<pre><code>cl &lt;-<span> </span>parallel::<span>makeForkCluster</span>(<span>2</span>)
doParallel::<span>registerDoParallel</span>(cl)
<span>foreach</span>(<span>i =</span> <span>1</span>:<span>3</span>, <span>.combine =</span> <span>'c'</span>) %dopar%<span> </span>{
  <span>sqrt</span>(i)
}</code></pre>
</div>
<pre><code>## [1] 1.000000 1.414214 1.732051</code></pre>
<div>
<pre><code>parallel::<span>stopCluster</span>(cl)</code></pre>
</div>
<p>Forking just copy the R session at its current state. This is very fast because it copies objects only it they are modified. Moreover, you don’t need to export variables nor packages because they are already in the session. However, this can’t be used on Windows. This is why I use the <em>clusters</em> option in my packages. Also, I don’t trust forking to always work.</p>
</div>
</div>
<div>
<h2>Common problems/mistakes/questions</h2>
<div>
<h3>Exporting variables and packages</h3>
<blockquote>
<p>object xxx not found or function xxx not found.</p>
</blockquote>
<div>
<pre><code><span># Some data and function</span>
<span>library</span>(dplyr)
dfs &lt;-<span> </span><span>rep</span>(<span>list</span>(iris), <span>3</span>)
<span>count</span>(dfs[[<span>1</span>]], Species)</code></pre>
</div>
<pre><code>## # A tibble: 3 x 2
##      Species     n
##       </code></pre></div></div></section>