<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Towards a Characterisation of Parallel Functional Applications</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Evgenij Belikov</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Hans-Wolfgang Loidl</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Greg Michaelson</string-name>
          <email>G.Michaelsong@hw.ac.uk</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>School of Mathematical and Computer Sciences Heriot-Watt University</institution>
          ,
          <addr-line>Edinburgh</addr-line>
          ,
          <country country="UK">UK</country>
        </aff>
      </contrib-group>
      <fpage>146</fpage>
      <lpage>153</lpage>
      <abstract>
        <p>To devise novel parallelism control mechanisms further insights into dynamic behaviour of parallel functional programs and run-time systems (RTS) are needed. We use pro ling to characterise eight applications on a multi-core and on a multi-core cluster. We focus on thread granularity, memory management and communication. Our results con rm that parallel Haskell implementations cope well with large numbers of potential threads, identify memory management overhead as a key limiting factor in a shared-memory RTS, whilst in the distributed RTS, the amount of sharing determines the dominant communication overhead.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
      <p>This work is partly supported by the Scottish Informatics and Computer Science Alliance (SICSA).</p>
    </sec>
    <sec id="sec-2">
      <title>Parallel Applications</title>
      <p>
        Most applications1 were adopted from [
        <xref ref-type="bibr" rid="ref11 ref14">14, 11</xref>
        ] and grouped by the used parallelism pattern. We investigate how
program characteristics change across di erent run-time systems and architectures with varying number of PEs.
      </p>
      <p>Five applications use the Divide-an-Conquer (D&amp;C) pattern, where a problem is recursively split into
subproblems that are solved and the results combined to form the nal result. A threshold value can be used to
restrict the depth of a tree to a certain level from which on the problem is solved sequentially.</p>
      <p>The regular and at (i.e. not nested) parfib computes the number of function calls for computation of
the N th Fibonacci number using arbitrary-length integers (input: N = 50, threshold of 23); the naive
exponential implementation is primarily aimed at assessing thread subsumption capabilities of the RTS.
The worpitzky program, from the domain of symbolic computation, checks the Worpitzky identity for two
given arbitrary-length integers (19 to the exponent of 27, threshold 10).</p>
      <p>The queens program determines the number of solutions for placement of N queens on an N N board
without attacking each other (N = 16); a solution is a list of integers generated by discarding unsafe
positions, which results in sharing of data structures at RTS level.</p>
      <p>The coins program computes ways to pay out a speci ed amount (5777) from a given set of coins.
The minimax application calculates winning positions for a Noughts-vs-Crosses game on a N N board up
to a speci ed depth using alpha-beta search and lazyness to prune unpromising sub-trees (N = 4, depth 8).</p>
      <p>Three applications are data parallel, i.e. the parallelism is exploited by simultaneously applying a function to
the elements of a data structure. Explicit chunking can be used for explicit granularity tuning.</p>
      <p>The sumeuler program computes the sum over Euler Totient numbers in a given integer interval and is
fairly irregular ([0..100000], chunk 500); all the parallelism is generated in the beginning of the execution.
The mandelbrot application computes the fairly irregular Mandelbrot fractal set for a given range and image
size as well as number of iterations (range [-2:0..2:0], 4096x4096 image size, 3046 iterations).</p>
      <p>The maze program is a nested data-parallel AI application which searches for a path in a maze (of size 29).</p>
      <p>
        The benchmarks are implemented in Glasgow parallel Haskell [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ], a dialect of Haskell [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ], which implements
semi-explicit annotation-based model of parallelism where most of parallelism management is implicit. Although
similar benchmarks have been used in the past, we run measurements on con gurations with signi cantly larger
number of PEs which enables us to better assess scalability, in particular on a distributed-memory platform.
We show that where previously almost linear scaling has been reported on few cores, scalability often reaches a
plateau well before all PEs are fully utilised on modern server-class multi-cores and multi-core clusters.
      </p>
      <p>
        Additionally, we use larger input sizes and obtain more detailed pro les. We have extended the pro ling
infrastructure to record per-lightweight-thread granularity information as well as to collect more detailed summary
statistics on protocol messages and sizes (speci c to the distributed RTS). Relevant background information on
high-level programming models and RTS-level policies can be found in [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. Both run-time systems [
        <xref ref-type="bibr" rid="ref12 ref18">18, 12</xref>
        ]
implement a variant of work-stealing for load balancing, where idle PEs ask randomly chosen PEs for work [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ].
3
      </p>
    </sec>
    <sec id="sec-3">
      <title>Application Characterisation</title>
      <p>We report relative speedups and pro les from a median run out of three on a dedicated multi-core and on a lightly
loaded cluster of multi-cores as as we are primarily interested in the parallelism behaviour of the applications.</p>
      <p>The 48-core machine (cantor) consists of four AMD Opteron processors with two NUMA nodes with six
2.8GHz cores each. Every two cores share 2MB L2 cache and all six cores on a NUMA-node share 6MB L3
cache and 64GB RAM (512GB in sum). Average memory latency is 16ns with up to 3x di erence depending on
the NUMA regions. The beowulf cluster comprises of 8-core Xeon 5504 nodes with two sockets with four 2GHz
cores each, using 256 KB L2 cache, and 4MB shared L3 cache and 12GB RAM, and 8-core Xeon 5450 nodes
with two sockets with four 3GHz cores each, using 6MB shared L2 cache and 16GB RAM, connected via Gigabit
Ethernet with average latency of 150ns. We use CentOS 6.5, GHC 6.12.32, gcc 4.4.7, and PVM 3.4.6.
1Application source code can be obtained from http://www.macs.hw.ac.uk/~eb96/atps15benchmarks.tar.gz or via email.
2Some experiments using GHC 7.6.3 show similar trends for SMP; GUM has not yet been ported to more recent GHC versions.
3.1</p>
      <sec id="sec-3-1">
        <title>Performance and Scalability</title>
        <p>We x the input size and increase the number of PEs to assess scalability. Run time decreases as the applications
are able to pro tably exploit parallelism resulting in an order of magnitude reduction in execution time for 5
programs. The exceptions are queens due to excessive memory use, maze which generates more work with
increasing PE numbers, and GHC-SMP3 runs on higher numbers of PEs which indicates a scalability issue.</p>
        <p>In Figure 1 we observe strong scaling for parfib and coins for GUM and good scaling for sumeuler with load
balancing issues on high numbers of PEs. GUM scales up to 64 PEs in most cases, although often the bene t
of adding PEs decreases with PE number due to increasing overhead and reduced work per PE. SMP shows
best performance for relatively low number of PEs, whilst on 48 cores a memory management issue discussed in
Section 3.3 leads to a slowdown for 5 out of 8 programs. Moreover, queens, mandelbrot, and minimax exhibit
limited scalability due to excessive communication and heap residency, which hints at improvement potential
at application level. Increasing granularity for worpitzky is deemed likely to improve performance as currently
median thread size is very small and the number of threads very high compared to programs that scale better.
3.2</p>
      </sec>
      <sec id="sec-3-2">
        <title>Granularity</title>
        <p>We have extended run-time pro ling capabilities of GUM and SMP to record thread granularity information4.
Unlike SMP, GUM RTS instances maintain private heaps and thus avoid GC-related synchronisation overhead.
In Figure 2 we present application granularity pro les5, grouped by the RTS and architecture. A log-log scale is
used for comparability due to orders of magnitude di erences in thread sizes (x-axis) and numbers (y-axis).</p>
        <p>
          For parfib, coins, and worpitzky, we observe an order of magnitude less and larger threads for GUM than
for SMP, which demonstrates e ectiveness of GUM's thread subsumption mechanism and the aggressiveness of
SMP's thread creation for D&amp;C applications. Subsumption allows to implement advisory parallelism where the
RTS decides whether to inline child threads into the parent or execute them in parallel, similar to lazy futures [
          <xref ref-type="bibr" rid="ref13">13</xref>
          ].
The shapes of the pro les for GUM on cantor are to a large extent similar to the shape of the pro le on beowulf,
but di ers distinctively from SMP pro les, suggesting that RTS-level parallelism management policies have a
strong in uence on granularity, especially if the architectural features are not explicitly taken into account.
3We use SMP and GUM as a shorthand for GHC-SMP (shared-memory RTS) and GHC-GUM (distributed RTS), respectively.
4Pro ling overhead is negligible as it involves mostly counters and is amortised by other dominant overheads (e.g. GC).
5Application names are found in the upper right corner of each histogram, so that three rows in a column represent an application.
        </p>
        <p>Parallelism is often over-abundant and ne-grained in functional programs, leaving considerable parallel
slackness and requiring an e ective thread subsumption mechanism. We observe a wide range of actual and potential
parallelism degrees across applications. For instance, sumeuler only has 200 potential threads which is insu
cient to keep all PEs busy, whereas for coins and worpitzky there are four orders of magnitude more potential
threads, most of which are pruned at run time. GUM appears well-suited for D&amp;C applications and is able to
subsume threads to a larger extent than SMP which creates threads more aggressively. The systems automatically
adapt the degree of actual parallelism to the number of the available PEs.</p>
        <p>By contrast, thread subsumption is ine ective in at data-parallel applications, where parallelism is created at
the start of the computation. Hence, to exploit the subsumption mechanism, data-parallel applications appear
to require nested parallelism. We observe optimisation potential for D&amp;C applications: recognising and inlining
smaller threads as well as reducing the spread of the granularity distribution and the number of threads whilst
preserving larger threads.
3.3</p>
      </sec>
      <sec id="sec-3-3">
        <title>Memory Use and Garbage Collection</title>
        <p>Many parallel functional programs are memory-bound as they perform graph reduction. Figure 3 depicts GC
overhead { a reason for scalability issues for SMP. The GC% increases consistently across all applications for
SMP and results in severe contention on the rst generation heap. By contrast, GUM starts o with higher
GC% which then drops or remains constant in most cases. This highlights the bene t of a distributed-memory
design on shared-memory architectures by avoiding some of the synchronisation, which pays o particularly for
applications with low communication rate. In addition to GC%, allocation rate signi es computational intensity
of each application and can be used to compare aggressiveness of work allocation across run-time systems. In
Figure 4 we observe initially higher allocation rates for SMP that are then dropping faster than for GUM.</p>
        <p>Application working sets are represented by heap residency. We observe roughly constant or decreasing
residency for GUM on both distributed- and shared-memory architectures (except for minimax), whilst for SMP
the residency is growing in most cases, as due to contention some heap-allocated objects are retained for longer.
3.4</p>
      </sec>
      <sec id="sec-3-4">
        <title>Sharing and Communication</title>
        <p>GUM uses virtual shared memory, so each RTS instance maintains a Global Address (GA) table of stable
inter-processor pointers which are used as roots for GC. Fragmentation of the shared heap can lead to decreased
performance since excessive sharing results in higher GA residency and reduced locality, which leads to additional
communication overhead. Thus GA residency can be used as an indicator of the degree of virtual shared heap
fragmentation. Based on this metric, our application set can be partitioned into two classes: most of the
applications shown in Figure 5, exhibit a moderate GA residency of at most 600 per PE; in contrast to this
behaviour, worpitzky reaches a value of 2500 for a large number of PEs, and even worse mandelbrot (not
shown) reaches a GA residency of 8000, and queens (not shown) of over 250000. This points to a high degree
of sharing in the program due to poor data distribution and locality, which incurs a lot of communication and
becomes a bottleneck for parallel performance, hinting at potential for application-level optimisation.</p>
        <p>As shown in Figure 6, for parfib, coins, maze, and to lesser extent minimax and sumeuler we observe modest
linear increase in communication rate with less than 40% of work request messages. The median of the graph sent
usually increases slightly, but only for queens it is excessive with over 14MB median graph sent per mutation
second on 48 cores, as communication rate skyrockets (840k messages on 48 cores with frequent very long fetches
(when a light-weight thread blocks waiting for another), with only 15% of the messages being work requests).</p>
        <p>We are currently investigating ways to eliminate these overheads. Next highest communication rate is for
worpitzky with over 100k messages sent on 48 cores, almost 50% of which are work requests, due to very ne
thread granularity. Then sumeuler follows, illustrating another issue | lack of inherent parallelism for the given
chunk size leads to load imbalance on higher number of PEs demonstrated by over 95% of sent messages being
requests for work, which also coincides with decreasing memory residency and low allocation rate.</p>
        <p>For most applications the number of packets sent increases linearly and re ects the size of shared graph, whilst
packet size is mostly very small and constant (in the range between 5 and 50 bytes), except for queens (4k) and
mandelbrot (ca. 9k). Due to space limitation we present no graphs on these metrics. We nd that in general
packets are smallest for integer-based programs and data-parallel programs often have larger packets than D&amp;C
programs. Communication rate appears to correlate with heap fragmentation (GA residency) and the percentage
of work requests of the total number of messages seems to indicate the degree of load imbalance.</p>
        <p>Careful parallelisation is required to avoid pitfalls that result in excessive overhead and limit scalability. We
have found that semi-explicit parallel functional programs have the potential to scale, provided there is enough
work on the one hand, but that the granularity and sharing are adequately controlled, on the other.
4</p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>Conclusions</title>
      <p>We have characterised a set of small and medium-sized parallel functional applications run on a multi-core and on
a cluster of multi-cores in terms of scalability, granularity, GC overhead, global address table residency, allocation
rate and communication rate, among other metrics. We have found that pro ling reveals diverse bottlenecks and
helps gain insight into dynamic application behaviour. In particular, the results indicate that:
Subsumption works well across architectures and D&amp;C applications, as the RTS is able to handle a large
number of potential light-weight threads and prune super uous parallelism by subsuming computations into
the parent thread. For data-parallel programs nesting appears to be necessary to bene t from subsumption.
Compared to SMP, GUM is less aggressive in instantiating parallelism, i.e. generates fewer threads of larger
granularity, adapting to the number of PEs and to system latency (the higher the latency, the lazier the
instantiation). Additionally, granularity varies across run-time systems but seems relatively similar for the
same RTS across di erent architectures.</p>
      <p>High GA residency is a good indicator of heap fragmentation due to sharing, which in turn causes a high
degree of communication, limiting the scalability of the application.</p>
      <p>Communication rate and GA residency vary considerably across applications and have a high, direct impact
on parallel performance.</p>
      <p>System-level information (e.g. granularity pro les, GA residency representing heap fragmentation and the
fraction of work requests in relation to the total number of messages) appears promising for improving
dynamic policy control decisions at RTS level.</p>
      <p>
        Increased memory residency and GC-percentage in a shared-memory design point to a scalability issue due
to contention on the rst generation heap, in contrast to a distributed-memory design, con rming the results
from [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. This suggests higher scalability potential of the RTS design that uses private heaps.
      </p>
      <p>
        The insights from this characterisation inform the design of a dynamic adaptation mechanism, based on
monitoring a set of relevant parameters and dynamically tuning related policies. For instance, we are currently
implementing a co-location mechanism for potential threads that leverages ancestry information to encourage
stealing work from the nearby sources to improve locality and reduce fragmentation of the shared heap for
applications with multiple sources of parallelism. Additionally, architectural information on communication
latency and computational power of di erent PEs could be used to further improve co-location decisions [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ].
      </p>
      <p>Ultimately, we envision a growing set of representative parallel functional benchmark applications that could
be used (similar to mainstream languages) to compare di erent novel parallelism management policies and
mechanisms, aiming at high performance portability across heterogeneous architectures whilst retaining productivity.</p>
      <sec id="sec-4-1">
        <title>Acknowledgements</title>
        <p>We are grateful to Natalia Chechina, Julian Godesa, Rob Stewart, and Prabhat Totoo for inspiring discussions
and to the anonymous reviewers who helped improve the presentation and the discussion of the results.</p>
      </sec>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>M.</given-names>
            <surname>Aljabri</surname>
          </string-name>
          , H.-W. Loidl, and
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          .
          <article-title>Distributed vs. shared heap, parallel Haskell implementations on shared memory machines</article-title>
          .
          <source>In Proc. of Symp. on Trends in Functional Programming</source>
          , University of Utrecht, The Netherlands,
          <year>2014</year>
          . To appear.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>K.</given-names>
            <surname>Asanovic</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Bodik</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Demmel</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Keaveny</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Keutzer</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Kubiatowicz</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N.</given-names>
            <surname>Morgan</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Patterson</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Sen</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Wawrzynek</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Wessel</surname>
          </string-name>
          , and
          <string-name>
            <given-names>K.</given-names>
            <surname>Yelick</surname>
          </string-name>
          .
          <article-title>A view of the parallel computing landscape</article-title>
          .
          <source>CACM</source>
          ,
          <volume>52</volume>
          :
          <fpage>56</fpage>
          {
          <fpage>67</fpage>
          ,
          <year>October 2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>E.</given-names>
            <surname>Belikov</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Deligiannis</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Totoo</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Aljabri</surname>
          </string-name>
          , and
          <string-name>
            <given-names>H.-W.</given-names>
            <surname>Loidl</surname>
          </string-name>
          .
          <article-title>A survey of high-level parallel programming models</article-title>
          .
          <source>Technical Report HW-MACS-TR-0103</source>
          , Heriot-Watt University,
          <year>December 2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>R.</given-names>
            <surname>Blumofe</surname>
          </string-name>
          and
          <string-name>
            <given-names>C.</given-names>
            <surname>Leiserson</surname>
          </string-name>
          .
          <article-title>Scheduling multithreaded computations by work stealing</article-title>
          .
          <source>Journal of the ACM</source>
          ,
          <volume>46</volume>
          (
          <issue>5</issue>
          ):
          <volume>720</volume>
          {
          <fpage>748</fpage>
          ,
          <year>September 1999</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>A.</given-names>
            <surname>Brodtkorb</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            <surname>Dyken</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Hagen</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Hjelmervik</surname>
          </string-name>
          , and
          <string-name>
            <given-names>O.</given-names>
            <surname>Storaasli</surname>
          </string-name>
          .
          <article-title>State-of-the-art in heterogeneous computing</article-title>
          .
          <source>Scienti c Programming</source>
          ,
          <volume>18</volume>
          (
          <issue>1</issue>
          ):1{
          <fpage>33</fpage>
          , May
          <year>2010</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>K.</given-names>
            <surname>Hammond</surname>
          </string-name>
          .
          <article-title>Why parallel functional programming matters: Panel statement</article-title>
          . In A. Romanovsky and T. Vardanega, editors,
          <source>Ada-Europe</source>
          <year>2011</year>
          , volume
          <volume>6652</volume>
          <source>of LNCS</source>
          , pages
          <volume>201</volume>
          {
          <fpage>205</fpage>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>P.</given-names>
            <surname>Hudak</surname>
          </string-name>
          . Conception, evolution, and
          <article-title>application of functional programming languages</article-title>
          .
          <source>ACM Computing Surveys</source>
          ,
          <volume>21</volume>
          (
          <issue>3</issue>
          ):
          <volume>359</volume>
          {
          <fpage>411</fpage>
          ,
          <year>September 1989</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>P.</given-names>
            <surname>Hudak</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Hughes</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S. Peyton</given-names>
            <surname>Jones</surname>
          </string-name>
          , and
          <string-name>
            <given-names>P.</given-names>
            <surname>Wadler</surname>
          </string-name>
          .
          <article-title>A history of Haskell: being lazy with class</article-title>
          .
          <source>In Proc. of the 3rd ACM SIGPLAN History of Programming Languages Conference</source>
          , pages
          <volume>1</volume>
          {
          <fpage>55</fpage>
          ,
          <year>June 2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>J.</given-names>
            <surname>Hughes</surname>
          </string-name>
          .
          <article-title>Why functional programming matters</article-title>
          .
          <source>Research Directions in Functional Programming</source>
          , pages
          <volume>17</volume>
          {
          <fpage>42</fpage>
          ,
          <year>1990</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <surname>H.-W. Loidl</surname>
            ,
            <given-names>P.</given-names>
          </string-name>
          <string-name>
            <surname>Trinder</surname>
            ,
            <given-names>K.</given-names>
          </string-name>
          <string-name>
            <surname>Hammond</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          <string-name>
            <surname>Junaidu</surname>
            , R. Morgan, and
            <given-names>S. Peyton</given-names>
          </string-name>
          <string-name>
            <surname>Jones</surname>
          </string-name>
          .
          <article-title>Engineering Parallel Symbolic Programs in GpH</article-title>
          .
          <source>Concurrency: Practice and Experience</source>
          ,
          <volume>11</volume>
          :
          <fpage>701</fpage>
          {
          <fpage>752</fpage>
          ,
          <year>1999</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>S.</given-names>
            <surname>Marlow</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Maier</surname>
          </string-name>
          , H.-W. Loidl,
          <string-name>
            <given-names>M.</given-names>
            <surname>Aswad</surname>
          </string-name>
          , and
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          .
          <article-title>Seq no more: better Strategies for parallel Haskell</article-title>
          .
          <source>In Proc. of the 3rd Symposium on Haskell, Haskell '10</source>
          , pages
          <fpage>91</fpage>
          {
          <fpage>102</fpage>
          . ACM,
          <year>2010</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>S.</given-names>
            <surname>Marlow</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S. Peyton</given-names>
            <surname>Jones</surname>
          </string-name>
          , and
          <string-name>
            <given-names>S.</given-names>
            <surname>Singh</surname>
          </string-name>
          .
          <article-title>Runtime support for multicore Haskell</article-title>
          .
          <source>In ACM SIGPLAN Notices</source>
          , volume
          <volume>44</volume>
          , pages
          <fpage>65</fpage>
          {
          <fpage>78</fpage>
          ,
          <year>2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>E.</given-names>
            <surname>Mohr</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.A.</given-names>
            <surname>Kranz</surname>
          </string-name>
          , and
          <string-name>
            <given-names>R.H. Halstead</given-names>
            <surname>Jr</surname>
          </string-name>
          .
          <article-title>Lazy task creation: A technique for increasing the granularity of parallel programs</article-title>
          .
          <source>IEEE Transactions on Parallel and Distributed Systems</source>
          ,
          <volume>2</volume>
          (
          <issue>3</issue>
          ):
          <volume>264</volume>
          {
          <fpage>280</fpage>
          ,
          <year>July 1991</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>W.</given-names>
            <surname>Partain</surname>
          </string-name>
          .
          <article-title>The no b benchmark suite of Haskell programs</article-title>
          .
          <source>In Functional Programming</source>
          ,
          <year>Glasgow 1992</year>
          , pages
          <fpage>195</fpage>
          {
          <fpage>202</fpage>
          . Springer,
          <year>1993</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <given-names>H.</given-names>
            <surname>Sutter</surname>
          </string-name>
          and
          <string-name>
            <given-names>J.</given-names>
            <surname>Larus</surname>
          </string-name>
          .
          <article-title>Software and the concurrency revolution</article-title>
          .
          <source>ACM Queue</source>
          ,
          <volume>3</volume>
          (
          <issue>7</issue>
          ):
          <volume>54</volume>
          {
          <fpage>62</fpage>
          ,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          [16]
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          ,
          <string-name>
            <given-names>E. Barry</given-names>
            <surname>Jr.</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Davis</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Hammond</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Junaidu</surname>
          </string-name>
          , U. Klusik, H.-W. Loidl, and
          <string-name>
            <given-names>S. Peyton</given-names>
            <surname>Jones</surname>
          </string-name>
          .
          <article-title>GpH: An architecture-independent functional language</article-title>
          .
          <source>IEEE Transactions on Software Engineering</source>
          ,
          <year>1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          [17]
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Cole</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Hammond</surname>
          </string-name>
          , H.-W. Loidl, and
          <string-name>
            <given-names>G.</given-names>
            <surname>Michaelson</surname>
          </string-name>
          .
          <article-title>Resource analyses for parallel and distributed coordination</article-title>
          .
          <source>Concurrency and Computation: Practice and Experience</source>
          ,
          <volume>25</volume>
          (
          <issue>3</issue>
          ):
          <volume>309</volume>
          {
          <fpage>348</fpage>
          ,
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          [18]
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Hammond</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J. Mattson</given-names>
            <surname>Jr.</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Partridge</surname>
          </string-name>
          , and
          <string-name>
            <given-names>S. Peyton</given-names>
            <surname>Jones</surname>
          </string-name>
          .
          <article-title>GUM: a portable parallel implementation of Haskell</article-title>
          .
          <source>In Proc. of PLDI'96 Conf.</source>
          ,
          <year>1996</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          [19]
          <string-name>
            <given-names>P.</given-names>
            <surname>Trinder</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Hammond</surname>
          </string-name>
          ,
          <string-name>
            <surname>H-W. Loidl</surname>
            , and
            <given-names>S. Peyton</given-names>
          </string-name>
          <string-name>
            <surname>Jones</surname>
          </string-name>
          .
          <source>Algorithm + Strategy = Parallelism. Journal of Functional Programming</source>
          ,
          <volume>8</volume>
          (
          <issue>1</issue>
          ):
          <volume>23</volume>
          {
          <fpage>60</fpage>
          ,
          <year>January 1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref20">
        <mixed-citation>
          [20]
          <string-name>
            <given-names>S.</given-names>
            <surname>Vegdahl</surname>
          </string-name>
          .
          <article-title>A survey of proposed architectures for the execution of functional languages</article-title>
          .
          <source>IEEE Transactions on Computers</source>
          ,
          <volume>33</volume>
          (
          <issue>12</issue>
          ):
          <volume>1050</volume>
          {
          <fpage>1071</fpage>
          ,
          <year>December 1984</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>