Hi all,<br><br>I&#39;ve played a bit with Intel&#39;s Manycore Testing Lab (<a href="http://software.intel.com/en-us/articles/intel-many-core-testing-lab/">http://software.intel.com/en-us/articles/intel-many-core-testing-lab/</a>). Part of the agreement to use it requires that you report back your experiences, which I did in an Intel forum post (<a href="http://software.intel.com/en-us/forums/showthread.php?t=81396">http://software.intel.com/en-us/forums/showthread.php?t=81396</a>). I thought this could be interesting to the Haskell community in general as well, so I&#39;m reposting here, and pasting the text below for convenience. I&#39;ve replaced the images with links.<br>
<br><br>Cheers,<br>Pedro<br><br><blockquote style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class="gmail_quote">As per the agreement with Intel, I am reporting my experiences with the Intel Manycore Testing Lab (Linux). This was my first time in the lab, and I wanted to test GHC&#39;s [1] SMP parallelism [2] features.<br>
 <br>The first challenge was to actually get GHC to work on the lab. There was a working version of ghc under /opt/ghc6.13/bin/ghc, but I really needed GHC 7. So first I built GHC 7.0.2-rc2, which worked without much trouble.<br>
<br>Next step was to get all the necessary libraries in place. Since the lab has no direct internet access, cabal-install [3] wouldn&#39;t be of much use. Instead, I downloaded a snapshot of hackage [4] with the latest version of every package and manually installed the packages I needed. A bit boring, but doable.<br>
<br>Finally I was ready to compile my programs and test. First thing I tried was an existing algorithm I had which, at some point, takes a list of about 500 trees and, for each tree, computes a measure which is expressed as a floating point number. This is basically a map over a list transforming each tree into a float. Each operation is independent of the others, and all require the same input, so it seems ideal for parallelisation. A quick benchmark revealed the following running times:<br>
<br><a href="http://dreixel.net/images/perm/ParList.png">http://dreixel.net/images/perm/ParList.png</a><br><br>(Note the non-linear number of cores at the end of the x-axis.) Apparently there are performance gains with up to 6 cores; adding more cores after this makes the total running time worse.<br>
<br>While this might sound bad, do note that all that was necessary to parallelise this algorithm was a one line change: basically, at the point where the list of floats @l@ is generated, it is replaced with @l `using` parList rdeepseq@. This change, together with recompilation using -threaded, is all that is necessary to parallelise this program.<br>
<br>Later I performed a more accurate benchmark, this time using the equality function (take two elements and compare them for equality). The first step was to parallelise the equality function, which, again, is a very simple task:<br>
<br><span style="font-family: courier new,monospace;">-- Tree datatype</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">data Tree a = Leaf | Bin a (Tree a) (Tree a)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">-- Parallel equality</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">eqTreePar :: Tree Int -&gt; Tree Int -&gt; Bool</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">eqTreePar Leaf Leaf = True</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">eqTreePar (Bin x1 l1 r1) (Bin x2 l2 r2) = x1 == x2 &amp;&amp; par l (pseq r (l &amp;&amp; r))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">                                            where l = eqTreePar l1 l2</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">                                                  r = eqTreePar r1 r2</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">eqTreePar _ _ = False</span><br><br>`par` and `pseq` are the two primitives for parallelisation in GHC [5]. The performance graph follows:<br><br><a href="http://dreixel.net/images/perm/ParEq.png">http://dreixel.net/images/perm/ParEq.png</a><br>
<br>(This time I ran the benchmark several times; the error bars on the graph are the standard deviations.) Again we get performance improvements with up to 6 cores, and after that performance decreases. What I find really nice is the improvement with two cores, which is almost a 50% decrease in running time. The ratios for 2 to 4 cores wrt. the running time with 1 core are 0.52, 0.39, and 0.35, respectively. This is really good for such a simple change in the source code, and most people only have up to 4 cores anyway. In any case, the results of this (very preliminary) experiment seem to indicate that GHC&#39;s SMP parallelism is not particularly optimized for a high number of cores (yet).<br>
<br>I&#39;m planning to explore this line of research further, and I&#39;m hoping to be able to conduct more experiments in the near future. Feel free to contact me if you want more information on what I&#39;ve done.<br><br>
<br>Cheers,<br>Pedro<br><br>[1] <a href="http://www.haskell.org/ghc/">http://www.haskell.org/ghc/</a><br>[2] <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/using-smp.html">http://www.haskell.org/ghc/docs/latest/html/users_guide/using-smp.html</a><br>
[3] <a href="http://hackage.haskell.org/package/cabal-install">http://hackage.haskell.org/package/cabal-install</a><br>[4] <a href="http://hackage.haskell.org">http://hackage.haskell.org</a><br>[5] <a href="http://hackage.haskell.org/packages/archive/parallel/latest/doc/html/Control-Parallel.html">http://hackage.haskell.org/packages/archive/parallel/latest/doc/html/Control-Parallel.html</a><br>
</blockquote>