Peano
Loading...
Searching...
No Matches
peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag Namespace Reference

Functions

None derive_load_store_compute_flag (List["peano4.api.solversteps.Step"] steps)
 For every submodel used anywhere in steps, derive a peano4::grid::constructLoadStoreComputeFlag(...) expression from which of its using Steps are active, and assign it to that submodel's generator.load_store_compute_flag - the runtime counterpart to peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements(), which has to run before whichever compiler produces these steps: it decides which tasks have to declare a submodel at all; this function decides, for every Step that does, what its generated Observer should actually do with the data once the submodel's stack storage puts it there (load a real value, or start from a fresh dummy; store the result back, or discard it) - by asking, at runtime, which Step is presently executing.
 
str _step_active_expression ("peano4.api.solversteps.Step" step)
 
 _load_store_compute_flag_holder (submodel)
 The object holding the submodel's load_store_compute_flag: The peano4_mpi_and_storage_aspect for DaStGen2 data, the generator otherwise.
 
None _ensure_step_repository_includes (holder)
 
None _derive_load_store_compute_flag_for_one_kind (List["peano4.api.solversteps.Step"] steps, str attribute_name, str access_attribute_name, str guard_routine_name)
 

Variables

tuple _DEFAULT_LOAD_STORE_COMPUTE_FLAG
 
tuple _STEP_REPOSITORY_INCLUDES
 

Function Documentation

◆ _derive_load_store_compute_flag_for_one_kind()

None peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._derive_load_store_compute_flag_for_one_kind ( List["peano4.api.solversteps.Step"]  steps,
str  attribute_name,
str  access_attribute_name,
str  guard_routine_name 
)
protected

◆ _ensure_step_repository_includes()

None peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._ensure_step_repository_includes (   holder)
protected

Definition at line 221 of file DeriveLoadStoreComputeFlag.py.

Referenced by peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._derive_load_store_compute_flag_for_one_kind().

Here is the caller graph for this function:

◆ _load_store_compute_flag_holder()

peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._load_store_compute_flag_holder (   submodel)
protected

The object holding the submodel's load_store_compute_flag: The peano4_mpi_and_storage_aspect for DaStGen2 data, the generator otherwise.

Definition at line 210 of file DeriveLoadStoreComputeFlag.py.

Referenced by peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._derive_load_store_compute_flag_for_one_kind().

Here is the caller graph for this function:

◆ _step_active_expression()

str peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._step_active_expression ( "peano4.api.solversteps.Step"  step)
protected

Definition at line 183 of file DeriveLoadStoreComputeFlag.py.

Referenced by peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._derive_load_store_compute_flag_for_one_kind().

Here is the caller graph for this function:

◆ derive_load_store_compute_flag()

None peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag.derive_load_store_compute_flag ( List["peano4.api.solversteps.Step"]  steps)

For every submodel used anywhere in steps, derive a peano4::grid::constructLoadStoreComputeFlag(...) expression from which of its using Steps are active, and assign it to that submodel's generator.load_store_compute_flag - the runtime counterpart to peano4.api.taskgraph.compiler.PropagateUseStatements.propagate_use_statements(), which has to run before whichever compiler produces these steps: it decides which tasks have to declare a submodel at all; this function decides, for every Step that does, what its generated Observer should actually do with the data once the submodel's stack storage puts it there (load a real value, or start from a fresh dummy; store the result back, or discard it) - by asking, at runtime, which Step is presently executing.

This has to run after every algorithmic phase has actually been compiled (

See also
peano4.api.taskgraph.compiler.Sequential.translate(), or whichever compiler a caller configured instead), not before: a compiled Step's name, and which submodels it ends up using with which qualifier, are the compiler's call to make - Sequential.translate() happens to map one Task to one identically-qualified Step today, but it explicitly documents itself as the naive "no fusion, no reordering" baseline that smarter compilers (task fusion, dead-task elimination, reordering) are meant to be measured against and eventually replace. Reasoning about Tasks before compilation - e.g. by predicting a future Step's name from a Task's - would silently assume every such compiler keeps that 1:1 mapping, which is exactly what they need not do. Working from the compiled Steps themselves keeps this function correct no matter which compiler produced them.

Unlike propagate_use_statements(), this needs no notion of order, distance or edges between graphs - it only has to know, per submodel, which Steps touch it and how; a flat scan over every Step given is enough.

Building the three predicates

peano4::grid::constructLoadStoreComputeFlag(predicateToUseData, predicateForLoad, predicateForStore) takes three C++ boolean expressions and combines them into the 5-way peano4::grid::LoadStoreComputeFlag enum (

See also
src/peano4/grid/LoadStoreComputeFlag.h/.cpp). For a given submodel, each predicate is an "or"-chain of
peano4::parallel::Node::getInstance().getCurrentProgramStep() == repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::<name>)

terms - one per Step that qualifies, <name> being that Step's own .name (exactly as the compiler set it -

See also
peano4.api.solversteps.Step, src/peano4/api/solversteps/StepsToStepRepository.py for how a Step's name turns into a repositories::StepRepository::Steps enumerator):
  • predicateToUseData: every Step that declares the submodel at all, whichever Task.DataAccess qualifier it carries - all four qualifiers (including TEMPORARY) contribute here, since all of them mean the Step needs the submodel to be considered "in play" while it runs, even if - as for TEMPORARY - it never actually looks at the value.
  • predicateForLoad: only Steps qualified READ_AND_DISCARD or READ_AND_WRITE - the ones that actually need the real, previously stored value.
  • predicateForStore: only Steps qualified WRITE or READ_AND_WRITE - the ones that produce a value worth keeping.

TEMPORARY therefore only ever contributes to predicateToUseData -

See also
Task.DataAccess.TEMPORARY. A predicate with no contributing Step at all becomes the literal "false".

Grid selector

If a submodel carries a grid_selector (

See also
peano4.api.datamodel.DoF, peano4.api.toolbox.GridSelector), the selector's guard for the submodel's kind (createCellGuard(), createFaceGuard() or createVertexGuard()) is AND-combined with each of the three predicates:
::peano4::grid::constructLoadStoreComputeFlag((guard) and (use), (guard) and (load), (store guard) and (store))

That is, data are only used, loaded or stored if the selector holds and the steps above conclude that they are needed. The guards are evaluated within the generated loadStoreComputeFlag(marker), i.e. they can query the marker.

Peano's stacks require that a datum stored in one mesh sweep is loaded in the next one. The store predicate hence uses the selector's store guard (createCellStoreGuard(), createFaceStoreGuard() or createVertexStoreGuard()). It anticipates the guard's value in the next sweep. For a selector which depends on the refinement state, such as peano4.api.toolbox.FineGridSelector, it differs from the guard if the mesh changes. This keeps stores and loads consistent on dynamically adaptive meshes.

This does not touch generator.send_condition/receive_and_merge_condition - those are a separate, MPI rank-boundary concern this function has nothing to say about.

Includes

Every submodel this function touches gets 'include "repositories/StepRepository.h"', 'include "repositories/SolverRepository.h"' and 'include "peano4/parallel/Node.h"' appended to its generator.includes (skipped if already present) - the generated constructLoadStoreComputeFlag(...) expression references repositories::StepRepository::toProgramStep/Steps (declared in the first header) and peano4::parallel::Node::getInstance() (declared in the third); the second is added alongside the first to match this codebase's existing convention of always pairing the two (

See also
exahype2.api.generators.DefaultSimulationMain, mghype.matrixfree.api.MatrixFreeMain.template.cpp, mghype.petsc.api.PETScMain.template.cpp).

DaStGen2 data

Submodels modelled via DaStGen2 (peano4.api.datamodel.DaStGen2.DaStGen2) do not hold the load/store/compute flag in their generator but in their peano4_mpi_and_storage_aspect (peano4.api.dastgen2.MPIAndStorageAspect.MPIAndStorageAspect). For these, the function writes the flag into the aspect, and appends the includes above to the aspect's implementation_file_includes, as the aspect evaluates the flag within the implementation file. Adding them to the header might yield cyclic includes.

Combining with a pre-existing expression

If a submodel's generator.load_store_compute_flag already holds something other than its factory default (

See also
_DEFAULT_LOAD_STORE_COMPUTE_FLAG) - because a task graph author set it explicitly, or an earlier call to this very function already ran - the newly derived constructLoadStoreComputeFlag(...) call is not allowed to simply overwrite it. Instead the two are AND-combined, existing expression first, new one parenthesised: "existing and (new)". This makes repeated calls (e.g. once per algorithmic phase, if a caller preferred that over passing every phase's steps at once) accumulate rather than clobber each other.
Note
peano4::grid::LoadStoreComputeFlag is a plain enum class with no operator&& (or any other combining function) defined anywhere in the C++ sources as of this writing - an "existing and (new)" expression built from two such enum-valued sub-expressions will not type-check until such an operator is added on the C++ side. This function produces exactly that string regardless, since the string-level behaviour is what was asked for; the missing operator is a separate, outstanding C++-side gap.
Parameters
steps[peano4.api.solversteps.Step] Every compiled Step to consider, across every algorithmic phase (e.g. setup_simulation_steps + time_step_steps + plot_steps) - has to be the full set the surrounding project will actually run, so every submodel's predicates see every Step that might touch it.

Definition at line 20 of file DeriveLoadStoreComputeFlag.py.

References peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._derive_load_store_compute_flag_for_one_kind().

Here is the call graph for this function:

Variable Documentation

◆ _DEFAULT_LOAD_STORE_COMPUTE_FLAG

tuple peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._DEFAULT_LOAD_STORE_COMPUTE_FLAG
protected
Initial value:
1= (
2 "::peano4::grid::LoadStoreComputeFlag::LoadFromInputStream_ProvideToCalculations_StoreToOutputStream"
3)

Definition at line 15 of file DeriveLoadStoreComputeFlag.py.

◆ _STEP_REPOSITORY_INCLUDES

tuple peano4.api.taskgraph.compiler.DeriveLoadStoreComputeFlag._STEP_REPOSITORY_INCLUDES
protected
Initial value:
1= (
2 '#include "repositories/StepRepository.h"\n',
3 '#include "repositories/SolverRepository.h"\n',
4 '#include "peano4/parallel/Node.h"\n',
5)

Definition at line 203 of file DeriveLoadStoreComputeFlag.py.