Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Implementing a Synchronous DataFlow Graph using Intel Flow Graph

Salah_Eddine_S_
Beginner
281 Views

Hello,

I started investigating Intel TBB recently and was thinking of the possibility of implementing an application specified as a Synchronous DataFlow Graph using function and queue nodes. I seems to me doable in a straightforward manner. Could someone confirm? Any thoughts?

0 Kudos
4 Replies
Nikita_P_Intel
Employee
281 Views

Hi Salah,

It seems doable overall. In Flow Graph generally, for one message (set of tokens) that is produced, there is one message (same set of tokens) that is consumed, but it can be customized with nodes like queue and buffer node.
Could you, please, tell exactly what problem are you solving? Maybe we can help.

Thanks,

Nikita

0 Kudos
Salah_Eddine_S_
Beginner
281 Views

Hello Nikita,

Thank you for your reply. I am working on a numerical simulation code. I have a physical system described by ODEs (Ordinary Differential Equations). These equations are provided in the form of DLLs and the source code is not available. Information about dependencies between the different functions of the DLLs is also provided. As such, I am able to construct the dependency graph of the code. I am now investigating different possible solutions to parallelize this code. I've already tried some approaches and currently am interested in using Intel TBB flow graph.

An important feature of this application is that for a pair of dependent functions, one function may execute several times against one execution of the other function. This is why I find it interesting to model such an application using Synchronous DataFlow Graphs, where such feature can be modeled by different amounts of produced and consumed tokens.

To give an example,  consider the following flow graph with two functional nodes and one queue node:

|f1(x)|---->||||||---->|f2(x)|

Here, f1(x) must be executed once to produce 5 pieces of data, than f2(x) is executed 5 times consuming one item at a time.

 

Salah

0 Kudos
Nikita_P_Intel
Employee
281 Views

You can use multifunction_node here, that acts as a splitter of your tokens producer:

con int tokens_to_consume = 5;
tbb::flow::source_node< std::vector<int> > tokens_producer(g, [](std::vector<int>& tokens) -> bool {
        if (!endOfTokensGenerator()) {
            genereateTokens(tokens);
            return true;
        }
        return false;
});

typedef multifunction_node < std::vector<int>, std::tuple< std::vector<int> > > multinode;
multinode tokens_splitter( g, tbb::flow::serial, [&tokens_to_consume]( const std::vector<int>& tokens, multinode::output_ports_type& op ) {
	for (int i = 0; i < tokens_to_consume; )
		std::get<0>( op ).try_put( tokens );
});

tbb::flow::function_node< std::vector<int> > tokens_consumer(g, tbb::flow::unlimited, [](const std::vector<int>& tokens) {
	consume(tokens);
});

make_edge(tokens_producer, tokens_splitter);
make_edge(output_port<0>(tokens_splitter), tokens_consumer);

 

0 Kudos
Salah_Eddine_S_
Beginner
281 Views

Thank you Nikita. I have been trying to wrok around another solution using continue messages. Not working so far. I will give your suggestion a try.

Salah

0 Kudos
Reply