In order to prevent operators from calculating the same fields multiple times, one can set variables and input these into the operator tree.
The variables are set via a FieldAdapter
. This has been used in !417 (merged).
An operator tree takes as an input a Field and outputs a Field. Cutting out equal subtrees and using their output as the new input for the pruned operator tree is one way to achieve more performance. This is done by optimize_subtrees
.
There are some more improvements one has to make: _OpChain
operators make the tree very complex and they have to be unpacked.
In op2(op1) + op1
the first Summand has to be checked for whether it contains parts of the second Summand.
optimize_node
does this, while optimize_all_nodes
traverses the tree and applies it to (usually, see Problem 1) every node.
Some Problems:
-
Currently only searching for nodes at the end of operator chains, but
optimize_all_nodes( (op + op)(op + op) )
can happen -
Subtrees are only replaced at node points, but one should also compare the vertices above and replace it
-
Only comparing by ids is done, one might add a cache to prevent same operators from going unnoticed (similar to the
DomainTuple
cache -
op = optimize_subtrees(optimize_all_nodes(op))
generates better results thanop = optimize_all_nodes(optimize_subtrees(op))
.
As of now I'm unsure in how far changing the way the operator trees are stored could be improved to make this optimisation easier and/or faster.