CS333 Lab C-3:
Dataflow Communication
Goals of this lab:
- Learn about dataflow graphs.
- Understand dataflow synchronization.
- Construct modular components for a distributed dataflow programs.
- Use your components to create simple dataflow programs.
Introduction:
Dataflow is both a programming concept and implementation technique.
A dataflow program can be represented as a directed graph, where an
edge between two vertices represents the flow of data tokens between
those vertices along the direction of the edge. Each vertex in the
graph represents a dataflow element that can fire when there
is data waiting at each of its inputs. When an element fires, it
consumes one input token waiting at each input edge and may produce
one or more output tokens to be sent along the output edges to other
elements. Useful dataflow programs can be constructed from simple
elements that perform calculations and comparisons. Dataflow programs
allow for maximum concurrency because tokens flowing along different
parts of the dataflow graph may proceed safely in parallel.
The dataflow technique is amenable to visual programming because
dataflow graphs are easily visualized. In addition, standard procedural
programs can be compiled into dataflow graphs. Often this is done in order
to determine where one might be able to expoit concurrency.
In fact, special-purpose multiprocessors have been built to
execute dataflow graphs that are compiled from procedural languages.
In this project, you will construct several types of dataflow elements and
then put them together (visually) to construct distributed dataflow programs.
Each element will have three functions that it will perform repeatedly.
- match -- manage input queues; when there is a data token at each input, call fire
- fire -- consume one data token at each input and call produce with those arguments
- produce -- perform the calculation and generate data tokens at the outputs
Match and fire can be generic. Produce will vary according to the particular calculation
being performed by the dataflow element.
You will use ordinary Playground data values as tokens. Concurrency,
when possible, will be achieved by running dataflow elements on different
workstations.
Directions:
Read over the entire assignment before starting.
- Design: Invent a design that can be used as a general
framework for all of your dataflow elements. Your design should
handle match, fire, and produce. Since each Playground data value
will be treated as a separate token, you will need to use reaction
functions at your inputs to be sure that you don't miss any input
tokens. Keep in mind that it is possible for two inputs to arrive at
one input before any arrive at another, so multiple input tokens may
be waiting at a given input port. Your design should include queues
of data tokens (type PGvariable*) waiting to be processed. You will need
one queue per input port. Use a reaction function to perform the
enqueue operation. An element should fire only when all of its input
queues are non-empty. At that time, the head element of each queue
should be dequeued and used in the calculation. Finally, new data
tokens should be produced at the outputs, according to the results of
the calculation.
- Build 10 different dataflow elements: Use your general
design to build the following dataflow elements. Use EUPHORIA to test
each one. Be sure to test with multiple waiting inputs. (Don't be
scared by the number of elements. These elements are more alike than
they are different. Use inheritance.)
After you've created these, be sure to use
"strip" the executables to take up less disk space.
Even better, create a single executable that behaves like
different kinds of dataflow elements based on command-line
arguments or terminal input given when you start up the module.
Hint: You may want to set up your dataflow elements so
that constant values can be specified on startup. (For example, to
create a box that increments or decrements.) This will avoid the
problem of feeding in constants repeatedly to be matched with the
variable data.
- Mathematical elements:
Build dataflow elements for addition, subtraction, multiplication, and
division of floating point numbers. Each should take two inputs.
- Equality:
Build a dataflow element that compares two numbers.
It should produce a boolean result of true or false, depending on whether
the numbers are equal.
- Inequality:
Build another dataflow element that compares two numbers.
It should produce a true value when the first number is greater than the
second.
- Logic elements:
Build dataflow elements for AND, OR, and NOT, taking boolean inputs and
producing a boolean result.
- Switch: Build a dataflow element with two inputs (a boolean
and a real number) and two real number outputs. When the element
fires, it should pass its real number input to one of the two outputs,
depending on the value of the boolean input. This element will allow
you to construct dataflow graphs for looping computations.
- Create some dataflow programs:
Using dataflow elements you have constructed, use the PGcmgui to construct
the following dataflow programs. Be aware that the PGcmgui uses module
names to save configurations.
Use EUPHORIA to generate the input and consume the output from each program.
- Temperature conversion:
Create a dataflow program that converts between Fahrenheit and Celcius.
This is a classic dataflow example.
- Fibonacci:
Create a dataflow program that computes Fib(n) for n>0.
Recall that Fib(0) = 0, Fib(1) = 1, and Fib(n>1) = Fib(n-1) + Fib(n-2).
This one is tricky. Think about it carefully on paper before starting.
Hint:
Think about it in two parts. One part computes the fibonacci series with
an adder and a switch that feeds back into the adder. Proper
initialization is the key.
The other part implements has a loop counter that controls the number
of iterations of the fibonacci series part of the dataflow graph by
controlling its switch. For the loop counter, try using
an increment module, an inequality, and a switch.
Use EUPHORIA for initialization.
If you want to be really clever, make it reentrant.
- Create an original distributed dataflow program:
You can instantiate your elements many times
and connect them in arbitrary ways.
Think of an interesting calculation and create a dataflow
program for it using the components you have built.
Requirements:
Your original dataflow program must use concurrent computation
(different parts of the computation proceeding in parallel)
in a useful and interesting way, and it must take advantage
of dataflow semantics. For example, if you modules have only
one input, then you haven't taken advantage of the "match and fire"
concept in the dataflow model.
To receive credit for this lab, you should:
- Clean up and print out your code. (Don't turn it in, but
save it for your code/design review.)
- Turn in a
Project Evaluation Form near the beginning of
class on the day you want to do your demonstration and code/design
review. You should be
prepared to demonstrate your working application, explain your
design and code, and answer questions.