|
Peano
|
Functions | |
| bool | propagate_use_statements (List[List["peano4.api.solversteps.Step"]] sequences, Optional[List[Tuple[List["peano4.api.solversteps.Step"], List["peano4.api.solversteps.Step"]]]] edges=None) |
| Derive whichever further use_cell()/use_face()/use_vertex() declarations a set of compiled step sequences need so that every submodel they write is safely handed on to whoever reads it next. | |
| bool | _create_submodels_read_before_written (Dict[int, List] steps_of_sequence, List[Tuple[int, int]] edges, str attribute_name, str access_attribute_name, str use_method_name) |
| Add a WRITE declaration to the last step of an entry sequence for every submodel that can be read before it is ever written -. | |
| bool | _upgrade_discards_followed_by_reads (Dict[int, List] steps_of_sequence, List[Tuple[int, int]] edges, str attribute_name, str access_attribute_name) |
| Upgrade every READ_AND_DISCARD declaration to READ_AND_WRITE if a later step still reads the submodel before any step writes it again -. | |
| _step_backward (sequence, index, steps_of_sequence, predecessors_of_sequence) | |
| The exact reverse of _step_forward(): yield every (sequence, index) that can immediately reach (sequence, index) - the previous step in the same sequence if there is one, or otherwise the last step of every sequence declared (via edges) to lead into this one. | |
| bool | _upgrade_writes_immediately_following_read_and_write (Dict[int, List] steps_of_sequence, List[Tuple[int, int]] edges, str attribute_name, str access_attribute_name) |
| A plain WRITE is normally treated as a fresh, independent production that supersedes whatever came before (. | |
| bool | _propagate_use_statements_for_one_kind (Dict[int, List] steps_of_sequence, List[Tuple[int, int]] edges, str attribute_name, str access_attribute_name, str use_method_name) |
| _step_forward (sequence, index, steps_of_sequence, successors_of_sequence) | |
| Yield every (sequence, index) immediately reachable from (sequence, index) - the next step in the same sequence if there is one, or otherwise the first step of every declared successor sequence (several, if a sequence may be followed by more than one other). | |
| _find_next_consecutive_uses (origin_sequence, origin_index, submodel, attribute_name, access_attribute_name, steps_of_sequence, successors_of_sequence) | |
| Breadth-first search forward from (origin_sequence, origin_index), stopping each path the moment it reaches a step that declares a READ_AND_DISCARD, WRITE or READ_AND_WRITE use of submodel (a TEMPORARY declaration is transparent to this search -. | |
| bool | _fix_forward_gap (origin_sequence, origin_index, submodel, steps_of_sequence, successors_of_sequence, attribute_name, access_attribute_name, use_method_name) |
|
protected |
Add a WRITE declaration to the last step of an entry sequence for every submodel that can be read before it is ever written -.
| steps_of_sequence | Dict[int, [peano4.api.solversteps.Step]] The sequences handed over to propagate_use_statements(), each sequence identified by its index. |
| edges | [(int, int)] The edges handed over to propagate_use_statements(), translated into pairs of sequence indices. |
| attribute_name | str Which kind of submodel (cell_data, face_data or vertex_data) to analyse. |
| access_attribute_name | str The access dictionary matching attribute_name (cell_data_access, face_data_access or vertex_data_access). |
| use_method_name | str The Step method that declares a submodel of this kind (use_cell, use_face or use_vertex). |
Definition at line 255 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._step_forward().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements().


|
protected |
Breadth-first search forward from (origin_sequence, origin_index), stopping each path the moment it reaches a step that declares a READ_AND_DISCARD, WRITE or READ_AND_WRITE use of submodel (a TEMPORARY declaration is transparent to this search -.
Definition at line 595 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._step_forward().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements._fix_forward_gap(), and peano4.api.taskgraph.compiler.PropagateUseStatements._upgrade_discards_followed_by_reads().


|
protected |
Definition at line 649 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._find_next_consecutive_uses().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements._propagate_use_statements_for_one_kind().


|
protected |
Definition at line 541 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._fix_forward_gap().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements().


|
protected |
The exact reverse of _step_forward(): yield every (sequence, index) that can immediately reach (sequence, index) - the previous step in the same sequence if there is one, or otherwise the last step of every sequence declared (via edges) to lead into this one.
Definition at line 425 of file PropagateUseStatements.py.
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements._upgrade_writes_immediately_following_read_and_write().

|
protected |
Yield every (sequence, index) immediately reachable from (sequence, index) - the next step in the same sequence if there is one, or otherwise the first step of every declared successor sequence (several, if a sequence may be followed by more than one other).
Definition at line 577 of file PropagateUseStatements.py.
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements._create_submodels_read_before_written(), and peano4.api.taskgraph.compiler.PropagateUseStatements._find_next_consecutive_uses().

|
protected |
Upgrade every READ_AND_DISCARD declaration to READ_AND_WRITE if a later step still reads the submodel before any step writes it again -.
| steps_of_sequence | Dict[int, [peano4.api.solversteps.Step]] The sequences handed over to propagate_use_statements(), each sequence identified by its index. |
| edges | [(int, int)] The edges handed over to propagate_use_statements(), translated into pairs of sequence indices. |
| attribute_name | str Which kind of submodel (cell_data, face_data or vertex_data) to analyse. |
| access_attribute_name | str The access dictionary matching attribute_name (cell_data_access, face_data_access or vertex_data_access). |
Definition at line 352 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._find_next_consecutive_uses().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements().


|
protected |
A plain WRITE is normally treated as a fresh, independent production that supersedes whatever came before (.
This is therefore auto-corrected rather than merely reported: every step whose own declaration of a submodel is WRITE, and that has at least one immediate predecessor (
This is deliberately narrower than "any WRITE reachable from an earlier WRITE/READ_AND_WRITE": a WRITE immediately after another WRITE of the same submodel is left alone, since that is exactly the legitimate "recompute this fresh every time" pattern _fix_forward_gap() already has to support (
| steps_of_sequence | Dict[int, [peano4.api.solversteps.Step]] The sequences handed over to propagate_use_statements(), each sequence identified by its index. |
| edges | [(int, int)] The edges handed over to propagate_use_statements(), translated into pairs of sequence indices. |
| attribute_name | str Which kind of submodel (cell_data, face_data or vertex_data) to analyse. |
| access_attribute_name | str The access dictionary matching attribute_name (cell_data_access, face_data_access or vertex_data_access). |
Definition at line 443 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._step_backward().
Referenced by peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements().


| bool peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements | ( | List[List["peano4.api.solversteps.Step"]] | sequences, |
| Optional[List[Tuple[List["peano4.api.solversteps.Step"], List["peano4.api.solversteps.Step"]]]] | edges = None |
||
| ) |
Derive whichever further use_cell()/use_face()/use_vertex() declarations a set of compiled step sequences need so that every submodel they write is safely handed on to whoever reads it next.
This is a postprocessing step that runs on the output of a task graph compiler (peano4.api.taskgraph.compiler), i.e. on the sequences of peano4.api.solversteps.Step instances (Observers, aka mesh traversals) a compiler such as peano4.api.taskgraph.compiler.Sequential.translate() or peano4.api.taskgraph.compiler.FuseSteps.translate() yields - one sequence per task graph. All distances below therefore count mesh traversals, not tasks: a compiler that fuses several tasks into one Step changes these distances, and only the compiled Steps know them.
Every Step carries the Task.DataAccess qualifier of each submodel it declares in its cell_data_access/face_data_access/vertex_data_access (populated by the compiler). This function reads and amends these qualifiers, and it adds use_cell()/use_face()/use_vertex() declarations to the Steps where required.
The very first pass looks for submodels that a step loads (READ_AND_DISCARD or READ_AND_WRITE) before any step has ever written them. Peano would then try to load data that does not exist yet and stop with an assertion on its stacks. A sequence without any incoming edge (from another sequence or itself) is an entry sequence, i.e. it runs first, such as a setup phase. The pass searches forward from the first step of every entry sequence, following edges, and stops each path at the first step that declares the submodel (TEMPORARY is transparent). If this step reads the submodel, the pass adds a WRITE declaration of the submodel to the last step of the entry sequence: this step then creates the submodel and stores it, and the passes below make it reach the reader. The created submodel holds whatever its default constructor yields, i.e. the steps reading it have to cope with uninitialised values - typically through guards that ensure that they only read it once a "real" WRITE has happened. The WRITE goes into the entry sequence, as this one runs only once: a WRITE within a repeating sequence would overwrite the submodel's value every time the sequence runs. A read within the entry sequence itself cannot be fixed this way and is only logged.
The second pass looks for READ_AND_DISCARD declarations after which another step still reads the submodel (READ_AND_DISCARD or READ_AND_WRITE) before any step writes it again. This happens, for example, if two sibling tasks both consume the same submodel and the compiler maps them onto two subsequent mesh traversals: each task is done with the submodel, but only the latter traversal may discard it. The pass searches forward from every READ_AND_DISCARD, following edges, and stops each path at the first step that declares the submodel (TEMPORARY is transparent). If this step reads the submodel, the READ_AND_DISCARD is upgraded to READ_AND_WRITE, i.e. the submodel is stored again. The pass runs to a fixed point, and the passes below treat the upgraded declaration like any other one.
Before any of the below runs, a narrower, separate pass first upgrades every WRITE declaration that sits immediately (distance 1, following edges the same way as everything else here) after a READ_AND_WRITE declaration of the same submodel into a READ_AND_WRITE of its own -
Every use_cell()/use_face()/use_vertex() declaration carries a Task.DataAccess qualifier - READ_AND_DISCARD, WRITE, READ_AND_WRITE or TEMPORARY. Peano only relays a submodel from one Observer to the next through its stacks if both declare it, so a submodel a step WRITEs is lost unless some later step actually reads it, and every step in between has to relay it there. Precisely:
Only a READ_AND_DISCARD or READ_AND_WRITE ever "picks up" a submodel a WRITE produced; a WRITE or READ_AND_WRITE is what obliges anything downstream in the first place (a plain READ_AND_DISCARD, or leaving the submodel alone entirely, imposes no obligation of its own). Two other qualifiers get special treatment when they turn up downstream of such an obligation:
The freshly-inserted READ_AND_WRITE is itself fed back through the very same check (it is, for this purpose, exactly as much of an origin as a plain WRITE), so a single call already iterates this to a fixed point
Within one sequence, "the next step" is simply the next one in the list. Once a sequence's own steps run out, "the next step" continues into whichever sequence(s) edges declares reachable from it - a sequence can have several such successors (e.g. a time-stepping sequence that may be followed by either another time step or a plot, decided only at runtime), in which case the rule is checked, and fixed if need be, independently along every such continuation, since we cannot know which one will actually be taken. Two different continuations can legitimately reach the very same later step at distances of different parity (e.g. straight from setup into time-stepping versus via a plot detour first, if plotting happens to be due immediately) - both are checked and, if need be, independently fixed; a silent step is only ever revisited once per parity of how far away it was reached, which is all this rule ever cares about, so a cyclic edge structure (e.g. time-stepping and plotting following one another indefinitely) is still only walked a bounded number of times, not indefinitely. A sequence that is meant to repeat itself declares a (sequence, sequence) self-edge - the successor of its own last step is (among others, if it is also reachable from elsewhere) its own first step. A sequence with no outgoing edges at all simply ends there - whatever it last wrote and never got read is not this function's concern (it might be handed to a caller entirely outside the task-graph machinery, e.g. plotted from C++ code this Python layer does not see).
| sequences | [[peano4.api.solversteps.Step]] Every step sequence to consider, typically the outcome of one compiler call per task graph. A sequence has to be listed here to be analysed at all, whether or not it appears in edges (a sequence with no edges is simply analysed on its own). The steps are modified in place. |
| edges | [([peano4.api.solversteps.Step], [peano4.api.solversteps.Step])] Declares which sequences may run immediately after which other ones - each (predecessor, successor) pair means "successor's first step may immediately follow predecessor's last step". Sequences are identified by identity, i.e. pass the very list objects that are also handed over through sequences. Defaults to none (every sequence analysed purely on its own). |
Definition at line 10 of file PropagateUseStatements.py.
References peano4.api.taskgraph.compiler.PropagateUseStatements._create_submodels_read_before_written(), peano4.api.taskgraph.compiler.PropagateUseStatements._propagate_use_statements_for_one_kind(), peano4.api.taskgraph.compiler.PropagateUseStatements._upgrade_discards_followed_by_reads(), and peano4.api.taskgraph.compiler.PropagateUseStatements._upgrade_writes_immediately_following_read_and_write().
