2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
6 <chapter id="manual.ext.parallel_mode" xreflabel="Parallel Mode">
7 <?dbhtml filename="parallel_mode.html"?>
23 <title>Parallel Mode</title>
25 <para> The libstdc++ parallel mode is an experimental parallel
26 implementation of many algorithms the C++ Standard Library.
30 Several of the standard algorithms, for instance
31 <function>std::sort</function>, are made parallel using OpenMP
32 annotations. These parallel mode constructs and can be invoked by
33 explicit source declaration or by compiling existing sources with a
34 specific compiler flag.
38 <sect1 id="manual.ext.parallel_mode.intro" xreflabel="Intro">
41 <para>The following library components in the include
42 <filename class="headerfile">numeric</filename> are included in the parallel mode:</para>
44 <listitem><para><function>std::accumulate</function></para></listitem>
45 <listitem><para><function>std::adjacent_difference</function></para></listitem>
46 <listitem><para><function>std::inner_product</function></para></listitem>
47 <listitem><para><function>std::partial_sum</function></para></listitem>
50 <para>The following library components in the include
51 <filename class="headerfile">algorithm</filename> are included in the parallel mode:</para>
53 <listitem><para><function>std::adjacent_find</function></para></listitem>
54 <listitem><para><function>std::count</function></para></listitem>
55 <listitem><para><function>std::count_if</function></para></listitem>
56 <listitem><para><function>std::equal</function></para></listitem>
57 <listitem><para><function>std::find</function></para></listitem>
58 <listitem><para><function>std::find_if</function></para></listitem>
59 <listitem><para><function>std::find_first_of</function></para></listitem>
60 <listitem><para><function>std::for_each</function></para></listitem>
61 <listitem><para><function>std::generate</function></para></listitem>
62 <listitem><para><function>std::generate_n</function></para></listitem>
63 <listitem><para><function>std::lexicographical_compare</function></para></listitem>
64 <listitem><para><function>std::mismatch</function></para></listitem>
65 <listitem><para><function>std::search</function></para></listitem>
66 <listitem><para><function>std::search_n</function></para></listitem>
67 <listitem><para><function>std::transform</function></para></listitem>
68 <listitem><para><function>std::replace</function></para></listitem>
69 <listitem><para><function>std::replace_if</function></para></listitem>
70 <listitem><para><function>std::max_element</function></para></listitem>
71 <listitem><para><function>std::merge</function></para></listitem>
72 <listitem><para><function>std::min_element</function></para></listitem>
73 <listitem><para><function>std::nth_element</function></para></listitem>
74 <listitem><para><function>std::partial_sort</function></para></listitem>
75 <listitem><para><function>std::partition</function></para></listitem>
76 <listitem><para><function>std::random_shuffle</function></para></listitem>
77 <listitem><para><function>std::set_union</function></para></listitem>
78 <listitem><para><function>std::set_intersection</function></para></listitem>
79 <listitem><para><function>std::set_symmetric_difference</function></para></listitem>
80 <listitem><para><function>std::set_difference</function></para></listitem>
81 <listitem><para><function>std::sort</function></para></listitem>
82 <listitem><para><function>std::stable_sort</function></para></listitem>
83 <listitem><para><function>std::unique_copy</function></para></listitem>
88 <sect1 id="manual.ext.parallel_mode.semantics" xreflabel="Semantics">
89 <title>Semantics</title>
91 <para> The parallel mode STL algorithms are currently not exception-safe,
92 i.e. user-defined functors must not throw exceptions.
93 Also, the order of execution is not guaranteed for some functions, of course.
94 Therefore, user-defined functors should not have any concurrent side effects.
97 <para> Since the current GCC OpenMP implementation does not support
98 OpenMP parallel regions in concurrent threads,
99 it is not possible to call parallel STL algorithm in
100 concurrent threads, either.
101 It might work with other compilers, though.</para>
105 <sect1 id="manual.ext.parallel_mode.using" xreflabel="Using">
108 <sect2 id="parallel_mode.using.parallel_mode" xreflabel="using.parallel_mode">
109 <title>Using Parallel Mode</title>
112 To use the libstdc++ parallel mode, compile your application with
113 the compiler flag <constant>-D_GLIBCXX_PARALLEL -fopenmp</constant>. This
114 will link in <code>libgomp</code>, the GNU OpenMP <ulink url="http://gcc.gnu.org/onlinedocs/libgomp/">implementation</ulink>,
115 whose presence is mandatory. In addition, hardware capable of atomic
116 operations is mandatory. Actually activating these atomic
117 operations may require explicit compiler flags on some targets
118 (like sparc and x86), such as <literal>-march=i686</literal>,
119 <literal>-march=native</literal> or <literal>-mcpu=v9</literal>.
122 <para>Note that the <constant>_GLIBCXX_PARALLEL</constant> define may change the
123 sizes and behavior of standard class templates such as
124 <function>std::search</function>, and therefore one can only link code
125 compiled with parallel mode and code compiled without parallel mode
126 if no instantiation of a container is passed between the two
127 translation units. Parallel mode functionality has distinct linkage,
128 and cannot be confused with normal mode symbols.
132 <sect2 id="manual.ext.parallel_mode.usings" xreflabel="using.specific">
133 <title>Using Specific Parallel Components</title>
135 <para>When it is not feasible to recompile your entire application, or
136 only specific algorithms need to be parallel-aware, individual
137 parallel algorithms can be made available explicitly. These
138 parallel algorithms are functionally equivalent to the standard
139 drop-in algorithms used in parallel mode, but they are available in
140 a separate namespace as GNU extensions and may be used in programs
141 compiled with either release mode or with parallel mode. The
142 following table provides the names and headers of the parallel
147 <title>Parallel Algorithms</title>
148 <tgroup cols='4' align='left' colsep='1' rowsep='1'>
149 <colspec colname='c1'></colspec>
150 <colspec colname='c2'></colspec>
151 <colspec colname='c3'></colspec>
152 <colspec colname='c4'></colspec>
156 <entry>Algorithm</entry>
157 <entry>Header</entry>
158 <entry>Parallel algorithm</entry>
159 <entry>Parallel header</entry>
165 <entry><function>std::accumulate</function></entry>
166 <entry><filename class="headerfile">numeric</filename></entry>
167 <entry><function>__gnu_parallel::accumulate</function></entry>
168 <entry><filename class="headerfile">parallel/numeric</filename></entry>
171 <entry><function>std::adjacent_difference</function></entry>
172 <entry><filename class="headerfile">numeric</filename></entry>
173 <entry><function>__gnu_parallel::adjacent_difference</function></entry>
174 <entry><filename class="headerfile">parallel/numeric</filename></entry>
177 <entry><function>std::inner_product</function></entry>
178 <entry><filename class="headerfile">numeric</filename></entry>
179 <entry><function>__gnu_parallel::inner_product</function></entry>
180 <entry><filename class="headerfile">parallel/numeric</filename></entry>
183 <entry><function>std::partial_sum</function></entry>
184 <entry><filename class="headerfile">numeric</filename></entry>
185 <entry><function>__gnu_parallel::partial_sum</function></entry>
186 <entry><filename class="headerfile">parallel/numeric</filename></entry>
189 <entry><function>std::adjacent_find</function></entry>
190 <entry><filename class="headerfile">algorithm</filename></entry>
191 <entry><function>__gnu_parallel::adjacent_find</function></entry>
192 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
196 <entry><function>std::count</function></entry>
197 <entry><filename class="headerfile">algorithm</filename></entry>
198 <entry><function>__gnu_parallel::count</function></entry>
199 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
203 <entry><function>std::count_if</function></entry>
204 <entry><filename class="headerfile">algorithm</filename></entry>
205 <entry><function>__gnu_parallel::count_if</function></entry>
206 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
210 <entry><function>std::equal</function></entry>
211 <entry><filename class="headerfile">algorithm</filename></entry>
212 <entry><function>__gnu_parallel::equal</function></entry>
213 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
217 <entry><function>std::find</function></entry>
218 <entry><filename class="headerfile">algorithm</filename></entry>
219 <entry><function>__gnu_parallel::find</function></entry>
220 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
224 <entry><function>std::find_if</function></entry>
225 <entry><filename class="headerfile">algorithm</filename></entry>
226 <entry><function>__gnu_parallel::find_if</function></entry>
227 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
231 <entry><function>std::find_first_of</function></entry>
232 <entry><filename class="headerfile">algorithm</filename></entry>
233 <entry><function>__gnu_parallel::find_first_of</function></entry>
234 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
238 <entry><function>std::for_each</function></entry>
239 <entry><filename class="headerfile">algorithm</filename></entry>
240 <entry><function>__gnu_parallel::for_each</function></entry>
241 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
245 <entry><function>std::generate</function></entry>
246 <entry><filename class="headerfile">algorithm</filename></entry>
247 <entry><function>__gnu_parallel::generate</function></entry>
248 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
252 <entry><function>std::generate_n</function></entry>
253 <entry><filename class="headerfile">algorithm</filename></entry>
254 <entry><function>__gnu_parallel::generate_n</function></entry>
255 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
259 <entry><function>std::lexicographical_compare</function></entry>
260 <entry><filename class="headerfile">algorithm</filename></entry>
261 <entry><function>__gnu_parallel::lexicographical_compare</function></entry>
262 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
266 <entry><function>std::mismatch</function></entry>
267 <entry><filename class="headerfile">algorithm</filename></entry>
268 <entry><function>__gnu_parallel::mismatch</function></entry>
269 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
273 <entry><function>std::search</function></entry>
274 <entry><filename class="headerfile">algorithm</filename></entry>
275 <entry><function>__gnu_parallel::search</function></entry>
276 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
280 <entry><function>std::search_n</function></entry>
281 <entry><filename class="headerfile">algorithm</filename></entry>
282 <entry><function>__gnu_parallel::search_n</function></entry>
283 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
287 <entry><function>std::transform</function></entry>
288 <entry><filename class="headerfile">algorithm</filename></entry>
289 <entry><function>__gnu_parallel::transform</function></entry>
290 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
294 <entry><function>std::replace</function></entry>
295 <entry><filename class="headerfile">algorithm</filename></entry>
296 <entry><function>__gnu_parallel::replace</function></entry>
297 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
301 <entry><function>std::replace_if</function></entry>
302 <entry><filename class="headerfile">algorithm</filename></entry>
303 <entry><function>__gnu_parallel::replace_if</function></entry>
304 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
308 <entry><function>std::max_element</function></entry>
309 <entry><filename class="headerfile">algorithm</filename></entry>
310 <entry><function>__gnu_parallel::max_element</function></entry>
311 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
315 <entry><function>std::merge</function></entry>
316 <entry><filename class="headerfile">algorithm</filename></entry>
317 <entry><function>__gnu_parallel::merge</function></entry>
318 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
322 <entry><function>std::min_element</function></entry>
323 <entry><filename class="headerfile">algorithm</filename></entry>
324 <entry><function>__gnu_parallel::min_element</function></entry>
325 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
329 <entry><function>std::nth_element</function></entry>
330 <entry><filename class="headerfile">algorithm</filename></entry>
331 <entry><function>__gnu_parallel::nth_element</function></entry>
332 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
336 <entry><function>std::partial_sort</function></entry>
337 <entry><filename class="headerfile">algorithm</filename></entry>
338 <entry><function>__gnu_parallel::partial_sort</function></entry>
339 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
343 <entry><function>std::partition</function></entry>
344 <entry><filename class="headerfile">algorithm</filename></entry>
345 <entry><function>__gnu_parallel::partition</function></entry>
346 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
350 <entry><function>std::random_shuffle</function></entry>
351 <entry><filename class="headerfile">algorithm</filename></entry>
352 <entry><function>__gnu_parallel::random_shuffle</function></entry>
353 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
357 <entry><function>std::set_union</function></entry>
358 <entry><filename class="headerfile">algorithm</filename></entry>
359 <entry><function>__gnu_parallel::set_union</function></entry>
360 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
364 <entry><function>std::set_intersection</function></entry>
365 <entry><filename class="headerfile">algorithm</filename></entry>
366 <entry><function>__gnu_parallel::set_intersection</function></entry>
367 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
371 <entry><function>std::set_symmetric_difference</function></entry>
372 <entry><filename class="headerfile">algorithm</filename></entry>
373 <entry><function>__gnu_parallel::set_symmetric_difference</function></entry>
374 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
378 <entry><function>std::set_difference</function></entry>
379 <entry><filename class="headerfile">algorithm</filename></entry>
380 <entry><function>__gnu_parallel::set_difference</function></entry>
381 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
385 <entry><function>std::sort</function></entry>
386 <entry><filename class="headerfile">algorithm</filename></entry>
387 <entry><function>__gnu_parallel::sort</function></entry>
388 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
392 <entry><function>std::stable_sort</function></entry>
393 <entry><filename class="headerfile">algorithm</filename></entry>
394 <entry><function>__gnu_parallel::stable_sort</function></entry>
395 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
399 <entry><function>std::unique_copy</function></entry>
400 <entry><filename class="headerfile">algorithm</filename></entry>
401 <entry><function>__gnu_parallel::unique_copy</function></entry>
402 <entry><filename class="headerfile">parallel/algorithm</filename></entry>
412 <sect1 id="manual.ext.parallel_mode.design" xreflabel="Design">
413 <title>Design</title>
416 <sect2 id="manual.ext.parallel_mode.design.intro" xreflabel="Intro">
417 <title>Interface Basics</title>
421 All parallel algorithms are intended to have signatures that are
422 equivalent to the ISO C++ algorithms replaced. For instance, the
423 <function>std::adjacent_find</function> function is declared as:
428 template<typename _FIter>
430 adjacent_find(_FIter, _FIter);
435 Which means that there should be something equivalent for the parallel
436 version. Indeed, this is the case:
444 template<typename _FIter>
446 adjacent_find(_FIter, _FIter);
453 <para>But.... why the ellipses?
456 <para> The ellipses in the example above represent additional overloads
457 required for the parallel version of the function. These additional
458 overloads are used to dispatch calls from the ISO C++ function
459 signature to the appropriate parallel function (or sequential
460 function, if no parallel functions are deemed worthy), based on either
461 compile-time or run-time conditions.
464 <para> The available signature options are specific for the different
465 algorithms/algorithm classes.</para>
467 <para> The general view of overloads for the parallel algorithms look like this:
470 <listitem><para>ISO C++ signature</para></listitem>
471 <listitem><para>ISO C++ signature + sequential_tag argument</para></listitem>
472 <listitem><para>ISO C++ signature + algorithm-specific tag type
473 (several signatures)</para></listitem>
476 <para> Please note that the implementation may use additional functions
477 (designated with the <code>_switch</code> suffix) to dispatch from the
478 ISO C++ signature to the correct parallel version. Also, some of the
479 algorithms do not have support for run-time conditions, so the last
480 overload is therefore missing.
486 <sect2 id="manual.ext.parallel_mode.design.tuning" xreflabel="Tuning">
487 <title>Configuration and Tuning</title>
490 <sect3 id="parallel_mode.design.tuning.omp" xreflabel="OpenMP Environment">
491 <title>Setting up the OpenMP Environment</title>
494 Several aspects of the overall runtime environment can be manipulated
495 by standard OpenMP function calls.
499 To specify the number of threads to be used for the algorithms globally,
500 use the function <function>omp_set_num_threads</function>. An example:
504 #include <stdlib.h>
505 #include <omp.h>
509 // Explicitly set number of threads.
510 const int threads_wanted = 20;
511 omp_set_dynamic(false);
512 omp_set_num_threads(threads_wanted);
514 // Call parallel mode algorithms.
521 Some algorithms allow the number of threads being set for a particular call,
522 by augmenting the algorithm variant.
523 See the next section for further information.
527 Other parts of the runtime environment able to be manipulated include
528 nested parallelism (<function>omp_set_nested</function>), schedule kind
529 (<function>omp_set_schedule</function>), and others. See the OpenMP
530 documentation for more information.
535 <sect3 id="parallel_mode.design.tuning.compile" xreflabel="Compile Switches">
536 <title>Compile Time Switches</title>
539 To force an algorithm to execute sequentially, even though parallelism
540 is switched on in general via the macro <constant>_GLIBCXX_PARALLEL</constant>,
541 add <classname>__gnu_parallel::sequential_tag()</classname> to the end
542 of the algorithm's argument list.
550 std::sort(v.begin(), v.end(), __gnu_parallel::sequential_tag());
554 Some parallel algorithm variants can be excluded from compilation by
555 preprocessor defines. See the doxygen documentation on
556 <code>compiletime_settings.h</code> and <code>features.h</code> for details.
560 For some algorithms, the desired variant can be chosen at compile-time by
561 appending a tag object. The available options are specific to the particular
566 For the "embarrassingly parallel" algorithms, there is only one "tag object
567 type", the enum _Parallelism.
568 It takes one of the following values,
569 <code>__gnu_parallel::parallel_tag</code>,
570 <code>__gnu_parallel::balanced_tag</code>,
571 <code>__gnu_parallel::unbalanced_tag</code>,
572 <code>__gnu_parallel::omp_loop_tag</code>,
573 <code>__gnu_parallel::omp_loop_static_tag</code>.
574 This means that the actual parallelization strategy is chosen at run-time.
575 (Choosing the variants at compile-time will come soon.)
580 <sect3 id="parallel_mode.design.tuning.settings" xreflabel="_Settings">
581 <title>Run Time Settings and Defaults</title>
584 The default parallelization strategy, the choice of specific algorithm
585 strategy, the minimum threshold limits for individual parallel
586 algorithms, and aspects of the underlying hardware can be specified as
587 desired via manipulation
588 of <classname>__gnu_parallel::_Settings</classname> member data.
592 First off, the choice of parallelization strategy: serial, parallel,
593 or heuristically deduced. This corresponds
594 to <code>__gnu_parallel::_Settings::algorithm_strategy</code> and is a
595 value of enum <type>__gnu_parallel::_AlgorithmStrategy</type>
597 include: <type>heuristic</type>, <type>force_sequential</type>,
598 and <type>force_parallel</type>. The default is <type>heuristic</type>.
603 Next, the sub-choices for algorithm variant, if not fixed at compile-time.
604 Specific algorithms like <function>find</function> or <function>sort</function>
605 can be implemented in multiple ways: when this is the case,
606 a <classname>__gnu_parallel::_Settings</classname> member exists to
607 pick the default strategy. For
608 example, <code>__gnu_parallel::_Settings::sort_algorithm</code> can
610 enum <type>__gnu_parallel::_SortAlgorithm</type>: <type>MWMS</type>, <type>QS</type>,
611 or <type>QS_BALANCED</type>.
615 Likewise for setting the minimal threshold for algorithm
616 parallelization. Parallelism always incurs some overhead. Thus, it is
617 not helpful to parallelize operations on very small sets of
618 data. Because of this, measures are taken to avoid parallelizing below
619 a certain, pre-determined threshold. For each algorithm, a minimum
620 problem size is encoded as a variable in the
621 active <classname>__gnu_parallel::_Settings</classname> object. This
622 threshold variable follows the following naming scheme:
623 <code>__gnu_parallel::_Settings::[algorithm]_minimal_n</code>. So,
624 for <function>fill</function>, the threshold variable
625 is <code>__gnu_parallel::_Settings::fill_minimal_n</code>,
629 Finally, hardware details like L1/L2 cache size can be hardwired
630 via <code>__gnu_parallel::_Settings::L1_cache_size</code> and friends.
637 All these configuration variables can be changed by the user, if
639 There exists one global instance of the class <classname>_Settings</classname>,
640 i. e. it is a singleton. It can be read and written by calling
641 <code>__gnu_parallel::_Settings::get</code> and
642 <code>__gnu_parallel::_Settings::set</code>, respectively.
643 Please note that the first call return a const object, so direct manipulation
645 See <ulink url="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00640.html">
646 <filename class="headerfile">settings.h</filename></ulink>
647 for complete details.
651 A small example of tuning the default:
655 #include <parallel/algorithm>
656 #include <parallel/settings.h>
660 __gnu_parallel::_Settings s;
661 s.algorithm_strategy = __gnu_parallel::force_parallel;
662 __gnu_parallel::_Settings::set(s);
664 // Do work... all algorithms will be parallelized, always.
674 <sect2 id="manual.ext.parallel_mode.design.impl" xreflabel="Impl">
675 <title>Implementation Namespaces</title>
677 <para> One namespace contain versions of code that are always
678 explicitly sequential:
679 <code>__gnu_serial</code>.
682 <para> Two namespaces contain the parallel mode:
683 <code>std::__parallel</code> and <code>__gnu_parallel</code>.
686 <para> Parallel implementations of standard components, including
687 template helpers to select parallelism, are defined in <code>namespace
688 std::__parallel</code>. For instance, <function>std::transform</function> from <filename class="headerfile">algorithm</filename> has a parallel counterpart in
689 <function>std::__parallel::transform</function> from <filename class="headerfile">parallel/algorithm</filename>. In addition, these parallel
690 implementations are injected into <code>namespace
691 __gnu_parallel</code> with using declarations.
694 <para> Support and general infrastructure is in <code>namespace
695 __gnu_parallel</code>.
698 <para> More information, and an organized index of types and functions
699 related to the parallel mode on a per-namespace basis, can be found in
700 the generated source documentation.
707 <sect1 id="manual.ext.parallel_mode.test" xreflabel="Testing">
708 <title>Testing</title>
711 Both the normal conformance and regression tests and the
712 supplemental performance tests work.
716 To run the conformance and regression tests with the parallel mode
721 <userinput>make check-parallel</userinput>
725 The log and summary files for conformance testing are in the
726 <filename class="directory">testsuite/parallel</filename> directory.
730 To run the performance tests with the parallel mode active,
734 <userinput>make check-performance-parallel</userinput>
738 The result file for performance testing are in the
739 <filename class="directory">testsuite</filename> directory, in the file
740 <filename>libstdc++_performance.sum</filename>. In addition, the
741 policy-based containers have their own visualizations, which have
742 additional software dependencies than the usual bare-boned text
743 file, and can be generated by using the <code>make
744 doc-performance</code> rule in the testsuite's Makefile.
748 <bibliography id="parallel_mode.biblio" xreflabel="parallel_mode.biblio">
749 <title>Bibliography</title>
753 Parallelization of Bulk Operations for STL Dictionaries
757 <firstname>Johannes</firstname>
758 <surname>Singler</surname>
761 <firstname>Leonor</firstname>
762 <surname>Frias</surname>
772 Workshop on Highly Parallel Processing on a Chip (HPPC) 2007. (LNCS)
779 The Multi-Core Standard Template Library
783 <firstname>Johannes</firstname>
784 <surname>Singler</surname>
787 <firstname>Peter</firstname>
788 <surname>Sanders</surname>
791 <firstname>Felix</firstname>
792 <surname>Putze</surname>
802 Euro-Par 2007: Parallel Processing. (LNCS 4641)