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