Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Because of all the trouble with merging the previous PR ("19398"), this PR is comprehensive, including both the stories sc/19398 and the stories sc/19399.
Apologies for the size of the PR, but this (hopefully) should merge much more easily than sc/19398.
There are several substantial changes to the library as part of this PR (the
Edge
class itself is quite small in fact).PortStateMachine
class can now support two-stage and three-stage data transfer. The former is when aSource
is directly connected to aSink
. The latter is when aSource
is connected to aSink
via anEdge
.PortStateMachine
is parameterized by the type of the states (two_stage
orthree_stage
) as well as the policy class that implements the actions for the state transitions. A policy class inherits from thePortStateMachine
class using CRTP, making its implementation of the state transition actions directly available to thePortStateMachine
class.Mover
and by aPortState
(one of two_stage or three_stage). TheMover
inherits from the policy class, again via CRTP. TheMover
class provides the actual data movement actions for the policy class (the policy class implements the synchronization between threads running theSource
and threads running theSink
.AsyncPolicy
and theUnifiedAsyncPolicy
. These policy classes implement the wait and notify functions using condition variables. Other policies are in place primarily for testing other parts of the task graph library.Source
toSink
is managed by anItemMover
class, defined in item_mover.h. TheItemMover
inherits from a policy class using CRTP.ItemMover
class inherits from a specialized base classBaseMover
, one specialized for two_stage on one for three_stage. TheBaseMover
maintains pointers to the data items from theSource
,Sink
, and in the case of three_stage data movement, theEdge
. Data movement is effected by swapping the data being pointed to in order to move it along the pipeline.Source
s andSink
s inherit from a DataMover class and use its API for sending data from aSource
to aSink
.Source
andSink
are class templates the take anMover
as a parameter (actually as a template template, along with the type of data being moved. TheMover
instantiated with theSource
or theSink
is expected to take a single parameter, the type being moved.DataBlock
s.Edge
inherits from bothSource
andSink
. TheEdge
constructor takes aSource
and aSink
and connects its internalSink
to passedSource
and its internalSource
to the passedSink
.Edge
s are also parameterized byMover
type and the type being passed.Source
to aSink
and verifying that all numbers were sent correctly (as well as verifying that all intermediate states of the state machine are correct). This kind of test is repeated for the finite state machine,Source
andSink
ports, and for pseudo graph nodes containingSource
s andSink
s. The tests are conducted for directly-connectedSource
s andSink
s as well as forSource
s andSink
s connected byEdge
s.Example:
The following is an example of instantiating a
Source
and aSink
. Note that in practice, many of these will be predefined so that users will not need to define the whole stack of types. Note that all of the classes in this stack are parameterized simply by the type being passed.An
Edge
requires a three stage Mover and would be used as follows:The code related to
sc/19399
contains implementations of simple node classes:ProducerNode
a class that invokes a function to create an item and puts it into the associated item moverConsumerNode
a class that extracts an item from the item mover and applies a function to itFunctionNode
a class that extracts an item from the item mover, applies a function to it, and puts the result into the associated item mover.An example of connecting a
SourceNode
,FunctionNode
, andSinkNode
looks likeAn
Edge
requires a three stage Mover and would be used as follows:(Note that upcoming PRs will make more effective use of CTAD for
Edge
creation so that the type arguments for theMover
and the datatype being moved will not have to be specified.Simple function object classes for composing with
ProducerNode
andConsumerNode
have been created in generator.h and consumer.h. The former just generates integers starting with some initial value, while the latter puts the items it consumes onto a specified output iterator.The following is an example of a
ProducerNode
,FunctionNode
, andConsumerNode
connected to each other linearly:Here we create
source_node
usinggenerator
andsink_node
using a consumer. TheFunctionNode
is constructed with a lambda. (The nodes can be constructed with any invocable: function, function object, bind object, etc.)Nodes are activated with a
run
member function, which invokes the associated function one time, or with afun_for
member function, which invokes it a specified number of times.There are extensive unit tests for the nodes, many of which include the basic testing from the ports. However, since we can connect nodes in a chain, we tested two-node, three-node, and four-node chains, using two-stage movers and three-stage movers. We also created a unit test for just the stop functionality.
To support these classes, as well as in anticipation of schedulers, a stop state was added to the
PortFiniteStateMachine
. The updated documented proof outline for thePortFiniteStateMachine
(along with updated diagrams) is included in the state_machine subdirectory. Stopping propagates fromSource
toSink
in an item mover and from theSink
to theSource
in a FunctionNode. Once aSource
is stopped, it signals the item mover to enter "stopping" states, immediately ceases creating any more items and returns from execution. When the item mover is in the stopping state, the associatedSink
will continue to retrieve items until the item mover is empty, then it will also finish execution.A nodes_sieve executable was added to the nodes test subdirectory. This program executes the sieve of Eratosthenes using
ProducerNode
,FunctionNode
, andConsumerNode
. It uses very crude scheduling but has performance approaching that of TBB et al.Since sc/19393, the
Edge
class has been greatly simplified (it basically just establishes anItemMover
between aSource
and aSink
. TheEdge
no longer stores an item, but rather theItemMover
does.TYPE: FEATURE
DESC: Adds Edge and simple Node classes to the TileDB task graph library.