Skip to content

Commit

Permalink
Add Mermaid dump support
Browse files Browse the repository at this point in the history
  • Loading branch information
IceflowRE committed Jan 18, 2021
1 parent 33a15b3 commit 8493fd1
Show file tree
Hide file tree
Showing 28 changed files with 260 additions and 66 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,14 @@ in an easy-to-use web-based interface.
# paste the profiling json data to https://taskflow.github.io/tfprof/
```

In addition to execution diagram, you can dump the graph to a DOT format
and visualize it using a number of free [GraphViz][GraphViz] tools.
In addition to execution diagram, you can dump the graph to a DOT or Mermaid format
and visualize it using a number of free [GraphViz][GraphViz] or [Mermaid][Mermaid] tools.

```
// dump the taskflow graph to a DOT format through std::cout
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::GraphViz);
// or Mermaid
taskflow.dump(std::cout, tf::DumpFormat::Mermaid);
```

<p align="center"><img src="doxygen/images/simple.svg"></p>
Expand Down Expand Up @@ -198,6 +200,7 @@ You are completely free to re-distribute your work derived from Taskflow.
[GitHub insights]: https://github.com/taskflow/taskflow/pulse
[GitHub pull requests]: https://github.com/taskflow/taskflow/pulls
[GraphViz]: https://www.graphviz.org/
[Mermaid]: http://mermaid-js.github.io/mermaid/
[Project Website]: https://taskflow.github.io/
[cppcon20 talk]: https://www.youtube.com/watch?v=MX15huP5DsM
[contributors]: https://taskflow.github.io/taskflow/contributors.html
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/matrix_multiplication/taskflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void matrix_multiplication_taskflow(unsigned num_threads) {
executor.run(taskflow).get();

//std::cout << reduce_sum() << std::endl;
//taskflow.dump(std::cout);
//taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
}

std::chrono::microseconds measure_time_taskflow(unsigned num_threads) {
Expand Down
11 changes: 7 additions & 4 deletions doxygen/QuickStart.dox
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ executor.wait_for_all();

@section QuickStartVisualizeATaskflow Visualize Taskflow Graphs

You can dump a taskflow graph to a DOT format and visualize it
using a number of free GraphViz tools such as @GraphVizOnline.
You can dump a taskflow graph to a DOT or Mermaid format and visualize it
using a number of free GraphViz tools such as @GraphVizOnline or Mermaid tools
such as @MermaidOnline.


@code{.cpp}
Expand All @@ -226,8 +227,10 @@ A.precede(B, C, E);
C.precede(D);
B.precede(D, E);

// dump the graph to a DOT file through std::cout
taskflow.dump(std::cout);
// dump the graph to a DOT format through std::cout
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
// dump the graph to a Mermaid format through std::cout
taskflow.dump(std::cout, tf::DumpFormat::Mermaid);
@endcode

@dotfile images/graphviz.dot
Expand Down
2 changes: 1 addition & 1 deletion doxygen/cookbook/composable_tasking.dox
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ This largely facilitates the @em modularity of writing a parallel task program.
33: f2C.precede(f1_module_task);
34: f1_module_task.precede(f2D);
35:
36: f2.dump(std::cout);
36: f2.dump(std::cout, tf::DumpFormat::Graphviz);
@endcode

<!-- @image html images/composition_static_1.svg width=40% -->
Expand Down
2 changes: 1 addition & 1 deletion doxygen/cookbook/conditional_tasking.dox
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ cond_1.precede(B, E); // return 0 to 'B' or 1 to 'E'
cond_2.precede(G, H); // return 0 to 'G' or 1 to 'H'
cond_3.precede(cond_3, L); // return 0 to 'cond_3' or 1 to 'L'

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
@endcode

The above code creates three condition tasks:
Expand Down
8 changes: 4 additions & 4 deletions doxygen/cookbook/dynamic_tasking.dox
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ All methods you find in tf::Taskflow are applicable for tf::Subflow.
19: C.precede(D); // D runs after C
20:
21: executor.run(taskflow).get(); // execute the graph to spawn the subflow
22: taskflow.dump(std::cout); // dump the taskflow to a DOT format
22: taskflow.dump(std::cout, tf::DumpFormat::Graphviz); // dump the taskflow to a DOT format
@endcode

<!--@image html images/subflow_join.svg width=35%-->
Expand Down Expand Up @@ -135,7 +135,7 @@ you can detach a subflow from its parent task, allowing its execution to flow in
20:
21: tf::Executor executor;
22: executor.run(taskflow).wait(); // execute the graph to spawn the subflow
22: taskflow.dump(std::cout); // dump the taskflow to DOT format
22: taskflow.dump(std::cout, tf::DumpFormat::Graphviz); // dump the taskflow to DOT format
@endcode

The figure below demonstrates a detached subflow based on the previous example.
Expand All @@ -152,7 +152,7 @@ For example, running the above taskflow 5 times results in a total of 19 tasks.
@code{.cpp}
executor.run_n(taskflow, 5).wait();
assert(taskflow.num_tasks() == 19);
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
@endcode

The dumped graph is shown as follows:
Expand Down Expand Up @@ -189,7 +189,7 @@ You can create another subflow from the execution of a subflow and so on.
21:
22: // execute the graph to spawn the subflow
23: tf::Executor().run(taskflow).get();
24: taskflow.dump(std::cout);
24: taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
@endcode

<!-- @image html images/nested_subflow.svg -->
Expand Down
2 changes: 1 addition & 1 deletion doxygen/cookbook/gpu_tasking_cudaflow.dox
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The following example implements the canonical saxpy (A·X Plus Y) task graph.
50:
51: executor.run(taskflow).wait();
52:
53: taskflow.dump(std::cout); // dump the taskflow
53: taskflow.dump(std::cout, tf::DumpFormat::Graphviz); // dump the taskflow
54: }
@endcode

Expand Down
2 changes: 1 addition & 1 deletion doxygen/cookbook/gpu_tasking_cudaflow_capturer.dox
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main() {

executor.run(taskflow).wait();

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions doxygen/cookbook/static_tasking.dox
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ You need to follow its contract to create a task.
@section VisualizeATaskDependencyGraph Visualize a Task Dependency Graph

You can dump a taskflow to a DOT format and visualize the graph using free online tools such as <a href="https://dreampuf.github.io/GraphvizOnline/">GraphvizOnline</a> and <a href="http://www.webgraphviz.com/">WebGraphviz</a>.
Alternative you can dump it a Mermaid format and visualize it with the free online tool such as <a href="https://mermaid-js.github.io/mermaid-live-editor">Mermaid Live Editor</a>.

@code{.cpp}
1: #include <taskflow/taskflow.hpp>
Expand All @@ -93,7 +94,7 @@ You can dump a taskflow to a DOT format and visualize the graph using free onlin
16: B.precede(D);
17: C.precede(D);
18:
19: taskflow.dump(std::cout);
19: taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
20: }
@endcode

Expand Down Expand Up @@ -134,7 +135,7 @@ the task handler.
19: << "num_successors=" << task.num_successors() << '\n';
20: }
21:
22: taskflow.dump(std::cout); // dump the taskflow graph
22: taskflow.dump(std::cout, tf::DumpFormat::Graphviz); // dump the taskflow graph
23:
24: tasks[0].work([](){ std::cout << "got a new work!\n"; });
25: tasks[1].work([](){ std::cout << "got a new work!\n"; });
Expand Down
2 changes: 1 addition & 1 deletion doxygen/examples/fibonacci.dox
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int main(int argc, char* argv[]) {

executor.run(taskflow).wait();

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

std::cout << "Fib[" << N << "]: " << res << std::endl;

Expand Down
4 changes: 2 additions & 2 deletions doxygen/examples/kmeans.dox
Original file line number Diff line number Diff line change
Expand Up @@ -424,13 +424,13 @@ void kmeans_gpu(
stop.precede(free);

// dump the taskflow without expanding GPU task graphs
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

// run the taskflow
executor.run(taskflow).wait();

// dump the entire taskflow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
}
@endcode

Expand Down
4 changes: 2 additions & 2 deletions doxygen/examples/matrix_multiplication.dox
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ void matrix_multiplication(int* A, int* B, int* C, int M, int K, int N) {
.precede(free);

// dump the graph without unfolding the cudaFlow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

// run the taskflow
executor.run(taskflow).wait();

// dump the entire execution graph including unfolded cudaFlow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
}
@endcode

Expand Down
2 changes: 1 addition & 1 deletion doxygen/examples/wavefront.dox
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void wavefront() {
executor.run(taskflow).wait();

// dump the taskflow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
}
@endcode

Expand Down
2 changes: 1 addition & 1 deletion doxygen/gpu_algorithms/cublas/cublas_flow_capturer.dox
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ int main() {

executor.run(taskflow).wait();

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

assert(hres == 32);
}
Expand Down
4 changes: 2 additions & 2 deletions examples/composition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void composition_example_1() {
f2C.precede(f1_module_task);
f1_module_task.precede(f2D);

f2.dump(std::cout);
f2.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run_n(f2, 3).get();
}
Expand Down Expand Up @@ -86,7 +86,7 @@ void composition_example_2() {
auto f2_module_task = f4.composed_of(f2);
f3_module_task.precede(f2_module_task);

f4.dump(std::cout);
f4.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run_until(
f4,
Expand Down
2 changes: 1 addition & 1 deletion examples/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int main() {
C.precede(D);

// visualizes the taskflow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

// executes the taskflow
executor.run(taskflow).wait();
Expand Down
2 changes: 1 addition & 1 deletion examples/do_while.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ int main() {
body.precede(cond);
cond.precede(body, done);

//taskflow.dump(std::cout);
//taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run(taskflow).wait();

Expand Down
2 changes: 1 addition & 1 deletion examples/dsl/condition_dsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int main() {
tasks.get_task<D>().name("D");

// visualizes the taskflow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

// executes the taskflow
executor.run(taskflow).wait();
Expand Down
2 changes: 1 addition & 1 deletion examples/fibonacci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) {

executor.run(taskflow).wait();

//taskflow.dump(std::cout);
//taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

std::cout << "Fib[" << N << "]: " << res << std::endl;

Expand Down
2 changes: 1 addition & 1 deletion examples/if_else.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main() {
cond.precede(yes, no);

// dump the conditioned flow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run(taskflow).wait();

Expand Down
2 changes: 1 addition & 1 deletion examples/nested_if_else.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ int main() {
cond3.precede(equl3, grtr3);

// dump the conditioned flow
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run(taskflow).wait();

Expand Down
2 changes: 1 addition & 1 deletion examples/reduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void reduce() {
std::cout << "result is incorrect: " << smin << " != " << tmin << std::endl;
}

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
}

// Procedure: transform_reduce
Expand Down
8 changes: 4 additions & 4 deletions examples/run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ int main(){

// dumpping a taskflow before execution won't visualize subflow tasks
std::cout << "Dump the taskflow before execution:\n";
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

std::cout << "Run the taskflow once without callback\n" << std::endl;
executor.run(taskflow).get();
std::cout << std::endl;

// after execution, we can visualize subflow tasks
std::cout << "Dump the taskflow after execution:\n";
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
std::cout << std::endl;

std::cout << "Use wait_for_all to wait for the execution to finish\n";
Expand All @@ -46,7 +46,7 @@ int main(){
std::cout << "Execute the taskflow two times without a callback\n";
executor.run_n(taskflow, 2).get();
std::cout << "Dump after two executions:\n";
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
std::cout << std::endl;

std::cout << "Execute the taskflow four times with a callback\n";
Expand All @@ -60,7 +60,7 @@ int main(){
return counter -- == 0;
}).get();

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

return 0;
}
2 changes: 1 addition & 1 deletion examples/subflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ int main(int argc, char* argv[]) {
executor.run(taskflow).get(); // block until finished

// examine the graph
taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

return 0;
}
Expand Down
23 changes: 15 additions & 8 deletions examples/visualization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,24 @@ int main(){
C.precede(D);
B.precede(D, E);

std::cout << "[dump without name assignment]\n";
taskflow.dump(std::cout);
std::cout << "[GraphViz dump without name assignment]\n";
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
std::cout << "[Mermaid dump without name assignment]\n";
taskflow.dump(std::cout, tf::DumpFormat::Mermaid);

std::cout << "[dump with name assignment]\n";
A.name("A");
B.name("B");
C.name("C");
D.name("D");
E.name("E");

// if the graph contains solely static tasks, you can simpley dump them
std::cout << "[GraphViz dump with name assignment]\n";
// if the graph contains solely static tasks, you can simply dump them
// without running the graph
taskflow.dump(std::cout);

taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
std::cout << "[Mermaid dump with name assignment]\n";
taskflow.dump(std::cout, tf::DumpFormat::Mermaid);

// ------------------------------------------------------
// Dynamic Tasking
// ------------------------------------------------------
Expand All @@ -46,10 +50,13 @@ int main(){
// in order to visualize subflow tasks, you need to run the taskflow
// to spawn the dynamic tasks first
tf::Executor executor;
std::cout << "[Run flow]\n";
executor.run(taskflow).wait();

taskflow.dump(std::cout);

std::cout << "[GraphViz dump with name assignment and subflow]\n";
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);
std::cout << "[Mermaid dump with name assignment and subflow]\n";
taskflow.dump(std::cout, tf::DumpFormat::Mermaid);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/while.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main() {
body.precede(back);
back.precede(cond);

taskflow.dump(std::cout);
taskflow.dump(std::cout, tf::DumpFormat::Graphviz);

executor.run(taskflow).wait();

Expand Down

0 comments on commit 8493fd1

Please sign in to comment.