1.. _use_nested_algorithms:
2
3Use Nested Algorithms to Increase Scalability
4=============================================
5
6
7One powerful way to increase the scalability of a flow graph is to nest
8other parallel algorithms inside of node bodies. Doing so, you can use a
9flow graph as a coordination language, expressing the most
10coarse-grained parallelism at the level of the graph, with finer grained
11parallelism nested within.
12
13
14In the example below, five nodes are created: an ``input_node``,
15``matrix_source``, that reads a sequence of matrices from a file, two
16``function_nodes``, ``n1`` and ``n2``, that receive these matrices and generate two
17new matrices by applying a function to each element, and two final
18``function_nodes``, ``n1_sink`` and ``n2_sink``, that process these resulting
19matrices. The ``matrix_source`` is connected to both ``n1`` and ``n2``. The node ``n1``
20is connected to ``n1_sink``, and ``n2`` is connected to ``n2_sink``. In the lambda
21expressions for ``n1`` and ``n2``, a ``parallel_for`` is used to apply the functions
22to the elements of the matrix in parallel. The functions
23``read_next_matrix``, ``f1``, ``f2``, ``consume_f1`` and ``consume_f2`` are not provided
24below.
25
26
27::
28
29
30       graph g;
31       input_node< double * > matrix_source( g, [&]( oneapi::tbb::flow_control &fc ) -> double* {
32         double *a = read_next_matrix();
33         if ( a ) {
34           return a;
35         } else {
36           fc.stop();
37           return nullptr;
38         }
39       } );
40       function_node< double *, double * > n1( g, unlimited, [&]( double *a ) -> double * {
41         double *b = new double[N];
42         parallel_for( 0, N, [&](int i) {
43           b[i] = f1(a[i]);
44         } );
45         return b;
46       } );
47       function_node< double *, double * > n2( g, unlimited, [&]( double *a ) -> double * {
48         double *b = new double[N];
49         parallel_for( 0, N, [&](int i) {
50           b[i] = f2(a[i]);
51         } );
52         return b;
53       } );
54       function_node< double *, double * > n1_sink( g, unlimited,
55         []( double *b ) -> double * {
56           return consume_f1(b);
57       } );
58       function_node< double *, double * > n2_sink( g, unlimited,
59         []( double *b ) -> double * {
60           return consume_f2(b);
61       } );
62       make_edge( matrix_source, n1 );
63       make_edge( matrix_source, n2 );
64       make_edge( n1, n1_sink );
65       make_edge( n2, n2_sink );
66       matrix_source.activate();
67       g.wait_for_all();
68
69