Add selection mechanism in graph
The main feature of this MR is to introduce the Select
operator, allowing conditionnal graph execution.
The condition can be data dependent, yet the graph scheduling remains fully static!
As per Aidge's philosophy, sub-graph hierarchy is an optional feature, not a mandatory workaround, contrary to ONNX's If
operator or PyTorch torch.cond
method. The Select
operator has the following advantages over them:
- Allow interleaved and hierarchical conditions;
- Allow pre-execution of conditional branches or not.
Two scheduling behaviors are possible, depending on wether Scheduler::tagConditionalNodes()
was called or not:
- Without tag: the graph is scheduled and run as is, meaning every conditional branch is run before selection. Of course, this may lead to lots of unnecessary computation. However, branches can be run in parallel, as well as in parallel with the condition determination path;
- With tags: only the selected conditional branch is run. To achieve this, the condition determination path has to be scheduled and run entirely before any conditional branch.
This MR adds the following:
- Operator
Mod
(modulus), conformant to ONNX; - Operator
CryptoHash
, for computing SHA256 (using OpenSSL, now an optional dependency toaidge_backend_cpu
); - Operator
Select
, which selects one of its inputs; - The
Scheduler::tagConditionalNodes()
method that tags nodes with their conditions in theschedule.cond
attribute; - Adaptation of the Scheduler to take into account the
schedule.cond
nodes tag; - Addition of
analysis/
sub-folder with theStaticAnalysis
andOperatorStats
now in separate source files; - Addition of
DynamicAnalysis
class that has the same functions asStaticAnalysis
but on the scheduled graph. TheDynamicAnalysis
will therefore report stats for the actual graph execution, which may differ from the static graph if for example some nodes are run multiple time (in recurrent/cyclic graphs) or never run (conditional node); - Add unit tests for
GraphView::replace()
from !281 (closed); -
Registrar
now also displays the list of available keys when a key is not found; - Solves #240 (closed).
Example
In the following example, we implement a conditional graph where the condition depends on the input data.
%%{init: {'flowchart': { 'curve': 'monotoneY'}, 'fontFamily': 'Verdana' } }%%
flowchart TB
Producer_0("input<br/><sub><em>(Producer#0)</em></sub>"):::producerCls_rootCls
CryptoHash_0("hash<br/><sub><em>(CryptoHash#0)</em></sub>")
Mod_0("mod<br/><sub><em>(Mod#0)</em></sub>")
ReLU_0("relu fa:fa-circle-question<br/><sub><em>(ReLU#0)</em></sub>")
Tanh_0("tanh fa:fa-circle-question<br/><sub><em>(Tanh#0)</em></sub>"):::conditionCls
Sqrt_0("sqrt fa:fa-circle-question<br/><sub><em>(Sqrt#0)</em></sub>"):::conditionCls
Select_0("select<br/><sub><em>(Select#0)</em></sub>")
Producer_1(<em>Producer#1</em>):::producerCls
Producer_0-->|"0 [2, 3] Float32<br/>↓<br/>0"|CryptoHash_0
Producer_0-->|"0 [2, 3] Float32<br/>↓<br/>0"|ReLU_0
Producer_0-->|"0 [2, 3] Float32<br/>↓<br/>0"|Tanh_0
Producer_0-->|"0 [2, 3] Float32<br/>↓<br/>0"|Sqrt_0
CryptoHash_0-->|"0 [4] UInt64<br/>↓<br/>0"|Mod_0
Mod_0-->|"0 [4] UInt64<br/>↓<br/>0"|Select_0
ReLU_0-->|"0 [2, 3] Float32<br/>↓<br/>1"|Select_0
Tanh_0-->|"0 [2, 3] Float32<br/>↓<br/>2"|Select_0
Sqrt_0-->|"0 [2, 3] Float32<br/>↓<br/>3"|Select_0
Producer_1-->|"0 [1] UInt64<br/>↓<br/>1"|Mod_0
Select_0--->|"0 [2, 3] Float32<br/>↓"|output0((out#0)):::outputCls
classDef inputCls fill:#afa
classDef outputCls fill:#ffa
classDef externalCls fill:#ccc
classDef producerCls fill:#ccf
classDef genericCls fill:#f9f9ff,stroke-width:1px,stroke-dasharray: 5 5
classDef metaCls stroke-width:5px
classDef rootCls stroke:#f00
classDef producerCls_rootCls stroke:#f00,fill:#ccf
classDef genericCls_rootCls stroke:#f00,fill:#f9f9ff,stroke-width:1px,stroke-dasharray: 5 5
classDef metaCls_rootCls stroke:#f00,stroke-width:5px
TODO later
-
Add support of conditions in node exports;
Merge request reports
Activity
assigned to @olivierbichler
mentioned in merge request aidge_backend_cpu!136 (merged)
added Feature 🚀 label
added 1 commit
- 19f7e435 - Working concept of with tagConditionalNodes()
added 27 commits
Toggle commit list@cguillon This MR introduces a PoC of a possible mechanism we discussed at the MLIR workshop! What do you think about it?
Great.
I'm not sure to understand whether it's the user responsibility to request/put the sched.cond tag or the scheduler's implementation responsibility. I did not identify code in the current MR state which would schedule first the path which compute the condition value, and then schedule the corresponding conditional path.
Can you add an example on how the scheduler and/or tag should be used in the example above?
Edited by Christophe GuillonYes, for now, it's the user responsibility to request
schedule.cond
tags insertion by callingScheduler::tagConditionalNodes()
, leading to the two possible scheduling behaviors described in the MR.The code that schedules first the path which compute the condition value (in case of tagged nodes) is spread in the
Scheduler.cpp
file: just look for conditions containinghasAttr("schedule.cond")
in the file. The implementation principle is simple: the node outputing the condition is considered as an extra parent (input) node for all conditional nodes in the graph, and the conditional nodes are all considered as extra childs to the condition node, from the scheduler perspective.Edited by Olivier BICHLER
changed milestone to %aidge v0.6.0
added 23 commits
-
0d3d9853...ee77d3c4 - 16 commits from branch
dev
- c1294d9b - Add Select, Mod and CryptoHash operators
- 2e3763db - Adjust output size w.r.t datatype
- f071055b - Working concept of with tagConditionalNodes()
- 3aaa08ef - Added conditional execution
- 0f2a76a0 - Improved doc
- b5d2e213 - Minor changes
- 069bb401 - Imrpoved display
Toggle commit list-
0d3d9853...ee77d3c4 - 16 commits from branch
added 8 commits
-
fcc408cd - 1 commit from branch
dev
- 72f0848d - Add Select, Mod and CryptoHash operators
- 602fe5a5 - Adjust output size w.r.t datatype
- 170d5931 - Working concept of with tagConditionalNodes()
- 13024908 - Added conditional execution
- daac3b18 - Improved doc
- 2a162962 - Minor changes
- 0cad06ff - Imrpoved display
Toggle commit list-
fcc408cd - 1 commit from branch
added 56 commits
-
aa722795...03de25a0 - 48 commits from branch
dev
- d39f04f3 - Add Select, Mod and CryptoHash operators
- 2512f855 - Adjust output size w.r.t datatype
- c3318428 - Working concept of with tagConditionalNodes()
- a1b31cdc - Added conditional execution
- a74fcf7c - Improved doc
- 5460accb - Minor changes
- 4f8f27b8 - Imrpoved display
- 7a9b48f4 - Integrate a small fix for @raphaelmillet
Toggle commit list-
aa722795...03de25a0 - 48 commits from branch
added 1 commit
- d453aa1d - Added hint in generateMemory() error message about forward dims
added StatusReview Ready label
mentioned in merge request aidge_quantization!44 (merged)
mentioned in merge request aidge!104 (merged)
mentioned in merge request !281 (closed)
added 1 commit
- 316bf5ca - Add working tests from !281 (closed) on GraphView::replace()
added 26 commits
-
d1ac46b2...374b93b9 - 25 commits from branch
dev
- 3c4e6838 - Merged with dev
-
d1ac46b2...374b93b9 - 25 commits from branch
mentioned in issue #240 (closed)
added 5 commits
-
51a9ebe6...76ccc349 - 4 commits from branch
dev
- d365b0d6 - Merge branch 'dev' into select
-
51a9ebe6...76ccc349 - 4 commits from branch
added 8 commits
-
d365b0d6...fd3f8a3b - 7 commits from branch
dev
- c5492e23 - Merged with dev
-
d365b0d6...fd3f8a3b - 7 commits from branch
enabled an automatic merge when all merge checks for c5492e23 pass