# Nodes Priorities

[flow_graph.node_priorities]

Flow graph provides interface for setting relative priorities at construction of flow graph functional nodes, guiding threads that execute the graph to prefer nodes with higher priority.

    namespace oneapi {
    namespace tbb {
    namespace flow {

        typedef unsigned int node_priority_t;

        const node_priority_t no_priority = node_priority_t(0);

    } // namespace flow
    } // namespace tbb
    } // namespace oneapi

`function_node`, `multifunction_node`, `async_node` and `continue_node` has a constructor with parameter of `node_priority_t` type, which sets the node priority in the graph: the larger the specified value for the parameter, the higher the priority. The special constant value `no_priority`, which is also the default value of the parameter, switches priority off for a particular node.

For a particular graph, tasks to execute the nodes whose priority is specified have precedence over tasks for the nodes with lower or no priority value set. When looking for a task to execute, a thread chooses the one with the highest priority from those in the graph that are available for execution.

## Example

The following basic example demonstrates prioritization of one path in the graph over the other, which may help to improve overall performance of the graph.

Dependency flow graph with a critical path.

Consider executing the graph from the picture above using two threads. Assume that the nodes `f1` and `f3` take equal time to execute, while the node `f2` takes longer. That makes the nodes `bs`, `f2`, and `fe` constitute the critical path in this graph. Due to the non-deterministic behavior in selection of the tasks, oneTBB might execute nodes `f1` and `f3` in parallel first, which would make the whole graph execution time last longer than the case when one of the threads chooses the node `f2` just after the broadcast node. By setting a higher priority on node `f2`, threads are guided to take the critical path task earlier, thus reducing overall execution time.

    #include <iostream>
    #include <cmath>

    #include "oneapi/tbb/tick_count.h"
    #include "oneapi/tbb/global_control.h"

    #include "oneapi/tbb/flow_graph.h"

    void spin_for( double delta_seconds ) {
        oneapi::tbb::tick_count start = oneapi::tbb::tick_count::now();
        while( (oneapi::tbb::tick_count::now() - start).seconds() < delta_seconds ) ;
    }

    static const double unit_of_time = 0.1;

    struct Body {
        unsigned factor;
        Body( unsigned times ) : factor( times ) {}
        void operator()( const oneapi::tbb::flow::continue_msg& ) {
            // body execution takes 'factor' units of time
            spin_for( factor * unit_of_time );
        }
    };

    int main() {
        using namespace oneapi::tbb::flow;

        const int max_threads = 2;
         oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, max_threads);

        graph g;

        broadcast_node<continue_msg> bs(g);

        continue_node<continue_msg> f1(g, Body(5));

        // f2 is a heavy one and takes the most execution time as compared to the other nodes in the
        // graph. Therefore, let the graph start this node as soon as possible by prioritizing it over
        // the other nodes.
        continue_node<continue_msg> f2(g, Body(10), node_priority_t(1));

        continue_node<continue_msg> f3(g, Body(5));

        continue_node<continue_msg> fe(g, Body(7));

        make_edge( bs, f1 );
        make_edge( bs, f2 );
        make_edge( bs, f3 );

        make_edge( f1, fe );
        make_edge( f2, fe );
        make_edge( f3, fe );

        oneapi::tbb::tick_count start = oneapi::tbb::tick_count::now();

        bs.try_put( continue_msg() );
        g.wait_for_all();

        double elapsed = std::floor((oneapi::tbb::tick_count::now() - start).seconds() / unit_of_time);

        std::cout << "Elapsed approximately " << elapsed << " units of time" << std::endl;

        return 0;
    }