forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParallelPipeline.html
1292 lines (1283 loc) · 143 KB
/
ParallelPipeline.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Taskflow Algorithms » Parallel Pipeline | Taskflow QuickStart</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
<link rel="icon" href="favicon.ico" type="image/vnd.microsoft.icon" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#22272e" />
</head>
<body>
<header><nav id="navigation">
<div class="m-container">
<div class="m-row">
<span id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">
<a href="https://taskflow.github.io"><img src="taskflow_logo.png" alt="" />Taskflow</a> <span class="m-breadcrumb">|</span> <a href="index.html" class="m-thin">QuickStart</a>
</span>
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
</svg></a>
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
</div>
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
<div class="m-row">
<ol class="m-col-t-6 m-col-m-none">
<li><a href="pages.html">Handbook</a></li>
<li><a href="namespaces.html">Namespaces</a></li>
</ol>
<ol class="m-col-t-6 m-col-m-none" start="3">
<li><a href="annotated.html">Classes</a></li>
<li><a href="files.html">Files</a></li>
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
<use href="#m-doc-search-icon-path" />
</svg></a></li>
</ol>
</div>
</div>
</div>
</div>
</nav></header>
<main><article>
<div class="m-container m-container-inflatable">
<div class="m-row">
<div class="m-col-l-10 m-push-l-1">
<h1>
<span class="m-breadcrumb"><a href="Algorithms.html">Taskflow Algorithms</a> »</span>
Parallel Pipeline
</h1>
<div class="m-block m-default">
<h3>Contents</h3>
<ul>
<li><a href="#ParallelPipelineIncludeHeaderFile">Include the Header</a></li>
<li><a href="#UnderstandPipelineScheduling">Understand the Pipeline Scheduling Framework</a></li>
<li><a href="#CreatePipeline">Create a Pipeline Module Task</a></li>
<li>
<a href="#ConnectWithTasks">Connect Pipeline with Other Tasks</a>
<ul>
<li><a href="#IterateAPipeline">Example 1: Iterate a Pipeline</a></li>
<li><a href="#ConcatenateTwoPipelines">Example 2: Concatenate Two Pipelines</a></li>
<li><a href="#DefineMultipleParallelPipelines">Example 3: Define Multiple Parallel Pipelines</a></li>
</ul>
</li>
<li><a href="#ResetPipeline">Reset a Pipeline</a></li>
<li><a href="#ParallelPipelineLearnMore">Learn More about Taskflow Pipeline</a></li>
</ul>
</div>
<p>Taskflow provides a <em>task-parallel</em> pipeline programming framework for you to create a <em>pipeline scheduling framework</em> to implement pipeline algorithms. Pipeline parallelism refers to a parallel execution of multiple data tokens through a linear chain of pipes or stages. Each stage processes the data token sent from the previous stage, applies the given callable to that data token, and then sends the result to the next stage. Multiple data tokens can be processed simultaneously across different stages.</p><section id="ParallelPipelineIncludeHeaderFile"><h2><a href="#ParallelPipelineIncludeHeaderFile">Include the Header</a></h2><p>You need to include the header file, <code>taskflow/algorithm/pipeline.hpp</code>, for creating a pipeline scheduling framework.</p><pre class="m-code"><span class="cp">#include</span> <span class="cpf"><taskflow/algorithm/pipeline.hpp></span><span class="cp"></span></pre></section><section id="UnderstandPipelineScheduling"><h2><a href="#UnderstandPipelineScheduling">Understand the Pipeline Scheduling Framework</a></h2><p>A <a href="classtf_1_1Pipeline.html" class="m-doc">tf::<wbr />Pipeline</a> object is a <em>composable</em> graph to create a <em>pipeline scheduling framework</em> through a module task in a taskflow (see <a href="ComposableTasking.html" class="m-doc">Composable Tasking</a>). Unlike the conventional pipeline programming frameworks (e.g., Intel TBB Parallel <a href="classtf_1_1Pipeline.html" class="m-doc">Pipeline</a>), Taskflow's pipeline algorithm does not provide any data abstraction, which often restricts users from optimizing data layouts in their applications, but a flexible framework for users to customize their application data atop an efficient pipeline scheduling framework.</p><div class="m-graph"><svg style="width: 22.250rem; height: 22.688rem;" viewBox="0.00 0.00 356.00 363.08">
<g transform="scale(1 1) rotate(0) translate(4 359.0782)">
<title>Taskflow</title>
<g class="m-cluster">
<title>cluster0</title>
<polygon stroke-dasharray="5,2" points="8,-268.3087 8,-347.0782 340,-347.0782 340,-268.3087 8,-268.3087"/>
<text text-anchor="middle" x="174" y="-330.2782">line 0</text>
</g>
<g class="m-cluster">
<title>cluster1</title>
<polygon stroke-dasharray="5,2" points="8,-181.5391 8,-260.3087 340,-260.3087 340,-181.5391 8,-181.5391"/>
<text text-anchor="middle" x="174" y="-243.5087">line 1</text>
</g>
<g class="m-cluster">
<title>cluster2</title>
<polygon stroke-dasharray="5,2" points="8,-94.7696 8,-173.5391 340,-173.5391 340,-94.7696 8,-94.7696"/>
<text text-anchor="middle" x="174" y="-156.7391">line 2</text>
</g>
<g class="m-cluster">
<title>cluster3</title>
<polygon stroke-dasharray="5,2" points="8,-8 8,-86.7696 340,-86.7696 340,-8 8,-8"/>
<text text-anchor="middle" x="174" y="-69.9696">line 3</text>
</g>
<g class="m-node m-flat">
<title>p00</title>
<ellipse cx="63" cy="-294.6934" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="63" y="-290.8934">pipe-0</text>
</g>
<g class="m-node m-flat">
<title>p10</title>
<ellipse cx="63" cy="-207.9239" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="63" y="-204.1239">pipe-0</text>
</g>
<g class="m-edge">
<title>p00->p10</title>
<path d="M63,-276.2918C63,-264.8656 63,-249.9322 63,-236.9378"/>
<polygon points="66.5001,-236.598 63,-226.5981 59.5001,-236.5981 66.5001,-236.598"/>
</g>
<g class="m-node m-flat">
<title>p01</title>
<ellipse cx="174" cy="-294.6934" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="174" y="-290.8934">pipe-1</text>
</g>
<g class="m-edge">
<title>p00->p01</title>
<path d="M109.8281,-294.6934C112.1703,-294.6934 114.5125,-294.6934 116.8548,-294.6934"/>
<polygon points="117.1245,-298.1935 127.1245,-294.6934 117.1244,-291.1935 117.1245,-298.1935"/>
</g>
<g class="m-node m-flat">
<title>p20</title>
<ellipse cx="63" cy="-121.1543" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="63" y="-117.3543">pipe-0</text>
</g>
<g class="m-edge">
<title>p10->p20</title>
<path d="M63,-189.5223C63,-178.096 63,-163.1626 63,-150.1682"/>
<polygon points="66.5001,-149.8285 63,-139.8285 59.5001,-149.8286 66.5001,-149.8285"/>
</g>
<g class="m-node m-flat">
<title>p11</title>
<ellipse cx="174" cy="-207.9239" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="174" y="-204.1239">pipe-1</text>
</g>
<g class="m-edge">
<title>p10->p11</title>
<path d="M109.8281,-207.9239C112.1703,-207.9239 114.5125,-207.9239 116.8548,-207.9239"/>
<polygon points="117.1245,-211.424 127.1245,-207.9239 117.1244,-204.424 117.1245,-211.424"/>
</g>
<g class="m-node m-flat">
<title>p30</title>
<ellipse cx="63" cy="-34.3848" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="63" y="-30.5848">pipe-0</text>
</g>
<g class="m-edge">
<title>p20->p30</title>
<path d="M63,-102.7527C63,-91.3265 63,-76.3931 63,-63.3987"/>
<polygon points="66.5001,-63.0589 63,-53.059 59.5001,-63.059 66.5001,-63.0589"/>
</g>
<g class="m-node m-flat">
<title>p21</title>
<ellipse cx="174" cy="-121.1543" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="174" y="-117.3543">pipe-1</text>
</g>
<g class="m-edge">
<title>p20->p21</title>
<path d="M109.8281,-121.1543C112.1703,-121.1543 114.5125,-121.1543 116.8548,-121.1543"/>
<polygon points="117.1245,-124.6544 127.1245,-121.1543 117.1244,-117.6544 117.1245,-124.6544"/>
</g>
<g class="m-node m-flat">
<title>p31</title>
<ellipse cx="174" cy="-34.3848" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="174" y="-30.5848">pipe-1</text>
</g>
<g class="m-edge">
<title>p30->p31</title>
<path d="M109.8281,-34.3848C112.1703,-34.3848 114.5125,-34.3848 116.8548,-34.3848"/>
<polygon points="117.1245,-37.8849 127.1245,-34.3848 117.1244,-30.8849 117.1245,-37.8849"/>
</g>
<g class="m-node m-flat">
<title>p02</title>
<ellipse cx="285" cy="-294.6934" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="285" y="-290.8934">pipe-2</text>
</g>
<g class="m-edge">
<title>p01->p02</title>
<path d="M220.8281,-294.6934C223.1703,-294.6934 225.5125,-294.6934 227.8548,-294.6934"/>
<polygon points="228.1245,-298.1935 238.1245,-294.6934 228.1244,-291.1935 228.1245,-298.1935"/>
</g>
<g class="m-node m-flat">
<title>p12</title>
<ellipse cx="285" cy="-207.9239" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="285" y="-204.1239">pipe-2</text>
</g>
<g class="m-edge">
<title>p11->p12</title>
<path d="M220.8281,-207.9239C223.1703,-207.9239 225.5125,-207.9239 227.8548,-207.9239"/>
<polygon points="228.1245,-211.424 238.1245,-207.9239 228.1244,-204.424 228.1245,-211.424"/>
</g>
<g class="m-node m-flat">
<title>p22</title>
<ellipse cx="285" cy="-121.1543" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="285" y="-117.3543">pipe-2</text>
</g>
<g class="m-edge">
<title>p21->p22</title>
<path d="M220.8281,-121.1543C223.1703,-121.1543 225.5125,-121.1543 227.8548,-121.1543"/>
<polygon points="228.1245,-124.6544 238.1245,-121.1543 228.1244,-117.6544 228.1245,-124.6544"/>
</g>
<g class="m-node m-flat">
<title>p32</title>
<ellipse cx="285" cy="-34.3848" rx="46.8387" ry="18.2703"/>
<text text-anchor="middle" x="285" y="-30.5848">pipe-2</text>
</g>
<g class="m-edge">
<title>p31->p32</title>
<path d="M220.8281,-34.3848C223.1703,-34.3848 225.5125,-34.3848 227.8548,-34.3848"/>
<polygon points="228.1245,-37.8849 238.1245,-34.3848 228.1244,-30.8849 228.1245,-37.8849"/>
</g>
<g class="m-edge">
<title>p02->p12</title>
<path d="M285,-276.2918C285,-264.8656 285,-249.9322 285,-236.9378"/>
<polygon points="288.5001,-236.598 285,-226.5981 281.5001,-236.5981 288.5001,-236.598"/>
</g>
<g class="m-edge">
<title>p12->p22</title>
<path d="M285,-189.5223C285,-178.096 285,-163.1626 285,-150.1682"/>
<polygon points="288.5001,-149.8285 285,-139.8285 281.5001,-149.8286 288.5001,-149.8285"/>
</g>
<g class="m-edge">
<title>p22->p32</title>
<path d="M285,-102.7527C285,-91.3265 285,-76.3931 285,-63.3987"/>
<polygon points="288.5001,-63.0589 285,-53.059 281.5001,-63.059 288.5001,-63.0589"/>
</g>
</g>
</svg>
</div><p>The figure above gives an example of our pipeline scheduling framework. The framework consists of three <em>pipes</em> (serial-parallel-serial stages) and four <em>lines</em> (maximum parallelism), where each line processes at most one data token. A pipeline of three pipes and four lines will propagate each data token through a sequential chain of three pipes and can simultaneously process up to four data tokens at the four lines. Each edge represents a task dependency. For example, the edge from <code>pipe-0</code> to <code>pipe-1</code> in line <code>0</code> represents the task dependency between the first and the second pipes in the first line; the edge from <code>pipe-0</code> in line <code>0</code> to <code>pipe-0</code> in line <code>1</code> represents the task dependency between two adjacent lines when processing two data tokens at the same pipe. Each pipe can be either a <em>serial</em> type or a <em>parallel</em> type, where a serial pipe processes data tokens sequentially and a parallel pipe processes different data tokens simultaneously.</p><aside class="m-note m-info"><h4>Note</h4><p>Due to the nature of pipeline, Taskflow requires the first pipe to be a serial type. The pipeline scheduling algorithm operates in a circular fashion with a factor of line count.</p></aside></section><section id="CreatePipeline"><h2><a href="#CreatePipeline">Create a Pipeline Module Task</a></h2><p>Taskflow leverages modern C++ and template techniques to strike a balance between the <em>expressiveness</em> and <em>generality</em> in designing the pipeline programming model. In general, there are three steps to create a pipeline application:</p><ol><li>Define the pipeline structure (e.g., pipe type, pipe callable, stopping rule, line count)</li><li>Define the data storage and layout, if needed for the application</li><li>Define the pipeline taskflow graph using composition</li></ol><p>The following code creates a pipeline scheduling framework using the example from the previous section. The framework schedules a total of five <em>scheduling tokens</em> labeled from 0 to 4. The first pipe stores the token identifier in a custom data storage, <code>buffer</code>, and each of the rest pipes adds one to the input data from the result of the previous pipe and stores the result into the corresponding line entry in the buffer.</p><pre class="m-code"> <span class="mi">1</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span> <span class="n">taskflow</span><span class="p">;</span>
<span class="mi">2</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Executor</span> <span class="n">executor</span><span class="p">;</span>
<span class="mi">3</span><span class="o">:</span>
<span class="mi">4</span><span class="o">:</span> <span class="c1">// maximum parallelism - each line processes one token at a time</span>
<span class="mi">5</span><span class="o">:</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_lines</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="mi">6</span><span class="o">:</span>
<span class="mi">7</span><span class="o">:</span> <span class="c1">// custom data storage</span>
<span class="mi">8</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer</span><span class="p">;</span>
<span class="mi">9</span><span class="o">:</span>
<span class="mi">10</span><span class="o">:</span> <span class="c1">// the pipeline consists of three pipes (serial-parallel-serial)</span>
<span class="mi">11</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">12</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">13</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">14</span><span class="o">:</span> <span class="c1">// generate only 5 scheduling tokens</span>
<span class="mi">15</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">()</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">16</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">17</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">18</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">19</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">20</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"pipe 0: input token = %zu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">());</span>
<span class="mi">21</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">();</span>
<span class="mi">22</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">23</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">24</span><span class="o">:</span>
<span class="mi">25</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">26</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">27</span><span class="o">:</span> <span class="s">"pipe 1: input buffer[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">28</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">29</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">30</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">31</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">32</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">33</span><span class="o">:</span>
<span class="mi">34</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">35</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">36</span><span class="o">:</span> <span class="s">"pipe 2: input buffer[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">37</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">38</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">39</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">40</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">41</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">42</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">43</span><span class="o">:</span>
<span class="mi">44</span><span class="o">:</span> <span class="c1">// build the pipeline graph using composition</span>
<span class="mi">45</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl</span><span class="p">).</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline"</span><span class="p">);</span>
<span class="mi">46</span><span class="o">:</span>
<span class="mi">47</span><span class="o">:</span> <span class="c1">// execute the taskflow</span>
<span class="mi">48</span><span class="o">:</span> <span class="n">executor</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">taskflow</span><span class="p">).</span><span class="n">wait</span><span class="p">();</span></pre><p>Debrief:</p><ul><li>Lines 4-5 define the structure of the pipeline scheduling framework</li><li>Line 8 defines the data storage as an one-dimensional array of <code>num_lines</code> integers</li><li>Line 12 defines the number of lines in the pipeline</li><li>Lines 13-23 define the first serial pipe, which will stop the pipeline scheduling at the fifth token</li><li>Lines 25-32 define the second parallel pipe</li><li>Lines 34-41 define the third serial pipe</li><li>Line 45 defines the pipeline taskflow graph using composition</li><li>Line 48 executes the taskflow</li></ul><p>Taskflow leverages <a href="RuntimeTasking.html" class="m-doc">Runtime Tasking</a> and <a href="ComposableTasking.html" class="m-doc">Composable Tasking</a> to implement the pipeline scheduling framework. The taskflow graph of this pipeline example is shown as follows, where 1) one condition task is used to decide which runtime task to run and 2) four runtime tasks is used to schedule tokens at four parallel lines, respectively.</p><div class="m-graph"><svg style="width: 28.500rem; height: 15.375rem;" viewBox="0.00 0.00 456.00 246.00">
<g transform="scale(1 1) rotate(0) translate(4 242)">
<title>Taskflow</title>
<g class="m-cluster">
<title>cluster_p0x7ffc47e53358</title>
<polygon points="8,-144 8,-222 146,-222 146,-144 8,-144"/>
<text text-anchor="middle" x="77" y="-205.2">Taskflow</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7ffc47e53220</title>
<polygon points="154,-8 154,-230 440,-230 440,-8 154,-8"/>
<text text-anchor="middle" x="297" y="-213.2">m1</text>
</g>
<g class="m-node m-flat">
<title>p0x1878a88</title>
<polygon points="137.5,-188 20.5,-188 16.5,-184 16.5,-152 133.5,-152 137.5,-156 137.5,-188"/>
<polyline points="133.5,-184 16.5,-184 "/>
<polyline points="133.5,-184 133.5,-152 "/>
<polyline points="133.5,-184 137.5,-188 "/>
<text text-anchor="middle" x="77" y="-166.2">pipeline [m1]</text>
</g>
<g class="m-node">
<title>p0x1878600</title>
<polygon points="297,-196 242,-170 297,-144 352,-170 297,-196"/>
<text text-anchor="middle" x="297" y="-166.2">cond</text>
</g>
<g class="m-node m-flat">
<title>p0x18786e8</title>
<polygon points="216,-52 162,-52 162,-48 158,-48 158,-44 162,-44 162,-24 158,-24 158,-20 162,-20 162,-16 216,-16 216,-52"/>
<polyline points="162,-48 166,-48 166,-44 162,-44 "/>
<polyline points="162,-24 166,-24 166,-20 162,-20 "/>
<text text-anchor="middle" x="189" y="-30.2">rt-0</text>
</g>
<g class="m-edge">
<title>p0x1878600->p0x18786e8</title>
<path stroke-dasharray="5,2" d="M281.9831,-151.0898C263.2598,-127.5123 231.1482,-87.0755 209.996,-60.4394"/>
<polygon points="212.5041,-57.9696 203.5443,-52.3151 207.0223,-62.3228 212.5041,-57.9696"/>
<text text-anchor="middle" x="251" y="-94.2">0</text>
</g>
<g class="m-node m-flat">
<title>p0x18787d0</title>
<polygon points="288,-52 234,-52 234,-48 230,-48 230,-44 234,-44 234,-24 230,-24 230,-20 234,-20 234,-16 288,-16 288,-52"/>
<polyline points="234,-48 238,-48 238,-44 234,-44 "/>
<polyline points="234,-24 238,-24 238,-20 234,-20 "/>
<text text-anchor="middle" x="261" y="-30.2">rt-1</text>
</g>
<g class="m-edge">
<title>p0x1878600->p0x18787d0</title>
<path stroke-dasharray="5,2" d="M290.8114,-146.6208C284.6195,-123.2294 275.0892,-87.2258 268.4777,-62.249"/>
<polygon points="271.7836,-61.06 265.8411,-52.2886 265.0166,-62.8513 271.7836,-61.06"/>
<text text-anchor="middle" x="285" y="-94.2">1</text>
</g>
<g class="m-node m-flat">
<title>p0x18788b8</title>
<polygon points="360,-52 306,-52 306,-48 302,-48 302,-44 306,-44 306,-24 302,-24 302,-20 306,-20 306,-16 360,-16 360,-52"/>
<polyline points="306,-48 310,-48 310,-44 306,-44 "/>
<polyline points="306,-24 310,-24 310,-20 306,-20 "/>
<text text-anchor="middle" x="333" y="-30.2">rt-2</text>
</g>
<g class="m-edge">
<title>p0x1878600->p0x18788b8</title>
<path stroke-dasharray="5,2" d="M303.1886,-146.6208C309.3805,-123.2294 318.9108,-87.2258 325.5223,-62.249"/>
<polygon points="328.9834,-62.8513 328.1589,-52.2886 322.2164,-61.06 328.9834,-62.8513"/>
<text text-anchor="middle" x="323" y="-94.2">2</text>
</g>
<g class="m-node m-flat">
<title>p0x18789a0</title>
<polygon points="432,-52 378,-52 378,-48 374,-48 374,-44 378,-44 378,-24 374,-24 374,-20 378,-20 378,-16 432,-16 432,-52"/>
<polyline points="378,-48 382,-48 382,-44 378,-44 "/>
<polyline points="378,-24 382,-24 382,-20 378,-20 "/>
<text text-anchor="middle" x="405" y="-30.2">rt-3</text>
</g>
<g class="m-edge">
<title>p0x1878600->p0x18789a0</title>
<path stroke-dasharray="5,2" d="M312.0169,-151.0898C330.7402,-127.5123 362.8518,-87.0755 384.004,-60.4394"/>
<polygon points="386.9777,-62.3228 390.4557,-52.3151 381.4959,-57.9696 386.9777,-62.3228"/>
<text text-anchor="middle" x="365" y="-94.2">3</text>
</g>
</g>
</svg>
</div><p>In this example, we customize the data storage, <code>buffer</code>, as an one-dimensional array of 4 integers, since the pipeline structure defines only four parallel lines. Each entry of <code>buffer</code> stores stores the data being processed in the corresponding line. For example, <code>buffer[1]</code> stores the processed data at line <code>1</code>. The following figure shows the data layout of <code>buffer</code>.</p><div class="m-graph"><svg style="width: 19.250rem; height: 7.062rem;" viewBox="0.00 0.00 308.00 113.00">
<g transform="scale(1 1) rotate(0) translate(4 109)">
<title>structs</title>
<g class="m-node m-flat">
<title>struct1</title>
<polygon points="0,-.5 0,-104.5 300,-104.5 300,-.5 0,-.5"/>
<text text-anchor="middle" x="150" y="-87.7">buffer[0] (processes token at line 0)</text>
<polyline points="0,-78.5 300,-78.5 "/>
<text text-anchor="middle" x="150" y="-61.7">buffer[1] (processes token at line 1)</text>
<polyline points="0,-52.5 300,-52.5 "/>
<text text-anchor="middle" x="150" y="-35.7">buffer[2] (processes token at line 2)</text>
<polyline points="0,-26.5 300,-26.5 "/>
<text text-anchor="middle" x="150" y="-9.7">buffer[3] (processes token at line 3)</text>
</g>
</g>
</svg>
</div><aside class="m-note m-info"><h4>Note</h4><p>In practice, you may need to add padding to the data type of the buffer or align it with the cacheline size to avoid false sharing. If the data type varies at different pipes, you can use <a href="https://en.cppreference.com/w/cpp/utility/variant">std::<wbr />variant</a> to store the data types in a uniform storage.</p></aside><p>For each scheduling token, you can use <a href="classtf_1_1Pipeflow.html#afee054e6a99965d4b3e36ff903227e6c" class="m-doc">tf::<wbr />Pipeflow::<wbr />line()</a> to get its line identifier and <a href="classtf_1_1Pipeflow.html#a4914c1f381a3016e98285b019cf60d6d" class="m-doc">tf::<wbr />Pipeflow::<wbr />pipe()</a> to get its pipe identifier. For example, if a scheduling token is at the third pipe of the forth line, <a href="classtf_1_1Pipeflow.html#afee054e6a99965d4b3e36ff903227e6c" class="m-doc">tf::<wbr />Pipeflow::<wbr />line()</a> will return <code>3</code> and <a href="classtf_1_1Pipeflow.html#a4914c1f381a3016e98285b019cf60d6d" class="m-doc">tf::<wbr />Pipeflow::<wbr />pipe()</a> will return <code>2</code> (index starts from 0). To stop the execution of the pipeline, you need to call <a href="classtf_1_1Pipeflow.html#a830b7f204cb87fff17e8d424918d9453" class="m-doc">tf::<wbr />Pipeflow::<wbr />stop()</a> at the first pipe. Once the stop signal has been triggered, the pipeline will stop scheduling any new tokens after the callable. As we can see from this example, <a href="classtf_1_1Pipeline.html" class="m-doc">tf::<wbr />Pipeline</a> gives you the full control to customize your application data on top of a pipeline scheduling framework.</p><aside class="m-note m-info"><h4>Note</h4><ol><li>Calling <a href="classtf_1_1Pipeflow.html#a830b7f204cb87fff17e8d424918d9453" class="m-doc">tf::<wbr />Pipeflow::<wbr />stop()</a> not at the first pipe has no effect on the pipeline scheduling.</li><li>In most cases, <a href="http://en.cppreference.com/w/cpp/thread/thread/hardware_concurrency.html" class="m-doc-external">std::<wbr />thread::<wbr />hardware_concurrency</a> is a good number for line count.</li></ol></aside><p>Our pipeline algorithm schedules tokens in a <em>circular</em> manner, with a factor of <code>num_lines</code>. That is, token <code>t</code> will be processed at line <code>t % num_lines</code>. The following snippet shows one of the possible outputs of this pipeline program:</p><pre class="m-code">pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">0</span>
pipe <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">0</span>
pipe <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">1</span>
pipe <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
pipe <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">2</span>
pipe <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
pipe <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">3</span>
pipe <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipe <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">4</span>
pipe <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
pipe <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">5</span></pre><p>There are a total of five tokens running through three pipes. Each pipes prints its input data value, except the first pipe that prints its token identifier. Since the second pipe is a parallel pipe, the output can interleave.</p></section><section id="ConnectWithTasks"><h2><a href="#ConnectWithTasks">Connect Pipeline with Other Tasks</a></h2><p>You can connect the pipeline module task with other tasks to create a taskflow application that embeds one or multiple pipeline algorithms. We describe three common examples below:</p><ul><li><a href="ParallelPipeline.html#IterateAPipeline" class="m-doc">Example 1: Iterate a Pipeline</a></li><li><a href="ParallelPipeline.html#ConcatenateTwoPipelines" class="m-doc">Example 2: Concatenate Two Pipelines</a></li><li><a href="ParallelPipeline.html#DefineMultipleParallelPipelines" class="m-doc">Example 3: Define Multiple Parallel Pipelines</a></li></ul><section id="IterateAPipeline"><h3><a href="#IterateAPipeline">Example 1: Iterate a Pipeline</a></h3><p>This example emulates a data streaming application that iteratively runs a stream of data through a pipeline using conditional tasking. The taskflow graph consists of one pipeline module task and one condition task. The pipeline module task processes a stream of data. The condition task decides the availability of data and reruns the pipeline when the next stream of data becomes available.<br /></p><pre class="m-code"> <span class="mi">1</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span> <span class="n">taskflow</span><span class="p">;</span>
<span class="mi">2</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Executor</span> <span class="n">executor</span><span class="p">;</span>
<span class="mi">3</span><span class="o">:</span>
<span class="mi">4</span><span class="o">:</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_lines</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// maximum parallelism of the pipeline</span>
<span class="mi">5</span><span class="o">:</span>
<span class="mi">6</span><span class="o">:</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">N</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="mi">7</span><span class="o">:</span> <span class="c1">// custom data storage</span>
<span class="mi">8</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer</span><span class="p">;</span>
<span class="mi">9</span><span class="o">:</span>
<span class="mi">10</span><span class="o">:</span> <span class="c1">// the pipeline consists of three pipes (serial-parallel-serial)</span>
<span class="mi">11</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">12</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">13</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">i</span><span class="p">,</span> <span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">14</span><span class="o">:</span> <span class="c1">// only 5 scheduling tokens are processed</span>
<span class="mi">15</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">i</span><span class="o">++</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">16</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">17</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">18</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">19</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">20</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"stage 0: input token = %zu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">());</span>
<span class="mi">21</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">();</span>
<span class="mi">22</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">23</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">24</span><span class="o">:</span>
<span class="mi">25</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">26</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">27</span><span class="o">:</span> <span class="s">"stage 1: input buffer[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">28</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">29</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">30</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">31</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">32</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">33</span><span class="o">:</span>
<span class="mi">34</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">35</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">36</span><span class="o">:</span> <span class="s">"stage 2: input buffer[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">37</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">38</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">39</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">40</span><span class="o">:</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">41</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">42</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">43</span><span class="o">:</span>
<span class="mi">44</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">conditional</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([</span><span class="o">&</span><span class="n">N</span><span class="p">,</span> <span class="o">&</span><span class="n">i</span><span class="p">](){</span>
<span class="mi">45</span><span class="o">:</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="mi">46</span><span class="o">:</span> <span class="k">if</span> <span class="p">(</span><span class="o">++</span><span class="n">N</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">47</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Rerun the pipeline</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="mi">48</span><span class="o">:</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="mi">49</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">50</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">51</span><span class="o">:</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">52</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">53</span><span class="o">:</span> <span class="p">}).</span><span class="n">name</span><span class="p">(</span><span class="s">"conditional"</span><span class="p">);</span>
<span class="mi">54</span><span class="o">:</span>
<span class="mi">55</span><span class="o">:</span> <span class="c1">// build the pipeline graph using composition</span>
<span class="mi">56</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl</span><span class="p">)</span>
<span class="mi">57</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline"</span><span class="p">);</span>
<span class="mi">58</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">initial</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"initial</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">})</span>
<span class="mi">59</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"initial"</span><span class="p">);</span>
<span class="mi">60</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">stop</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"stop</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">})</span>
<span class="mi">61</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"stop"</span><span class="p">);</span>
<span class="mi">62</span><span class="o">:</span>
<span class="mi">63</span><span class="o">:</span> <span class="c1">// specify the graph dependency</span>
<span class="mi">64</span><span class="o">:</span> <span class="n">initial</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pipeline</span><span class="p">);</span>
<span class="mi">65</span><span class="o">:</span> <span class="n">pipeline</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">conditional</span><span class="p">);</span>
<span class="mi">66</span><span class="o">:</span> <span class="n">conditional</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pipeline</span><span class="p">,</span> <span class="n">stop</span><span class="p">);</span>
<span class="mi">67</span><span class="o">:</span>
<span class="mi">68</span><span class="o">:</span> <span class="c1">// execute the taskflow</span>
<span class="mi">69</span><span class="o">:</span> <span class="n">executor</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">taskflow</span><span class="p">).</span><span class="n">wait</span><span class="p">();</span></pre><p>Debrief:</p><ul><li>Lines 4-5 define the structure of the pipeline scheduling framework</li><li>Line 8 defines the data storage as an one-dimensional array (<code>num_lines</code> integers)</li><li>Line 12 defines the number of lines in the pipeline</li><li>Lines 13-23 define the first serial pipe, which will stop the pipeline scheduling when <code>i</code> is <code>5</code><br /></li><li>Lines 25-32 define the second parallel pipe</li><li>Lines 34-41 define the third serial pipe</li><li>Lines 44-53 define a condition task which returns 0 when <code>N</code> is less than <code>2</code>, otherwise returns <code>1</code></li><li>Line 45 resets variable <code>i</code></li><li>Lines 56-57 define the pipeline graph using composition</li><li>Lines 58-61 define two static tasks</li><li>Line 64-66 define the task dependency</li><li>Line 69 executes the taskflow</li></ul><p>The taskflow graph of this pipeline example is illustrated as follows:</p><div class="m-graph"><svg style="width: 33.875rem; height: 32.438rem;" viewBox="0.00 0.00 542.00 518.77">
<g transform="scale(1 1) rotate(0) translate(4 514.7696)">
<title>Taskflow</title>
<g class="m-cluster">
<title>cluster_p0x7fff4f1276d8</title>
<polygon points="8,-8 8,-495.1543 232,-495.1543 232,-8 8,-8"/>
<text text-anchor="middle" x="120" y="-478.3543">Taskflow</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7fff4f127590</title>
<polygon points="240,-280.7696 240,-502.7696 526,-502.7696 526,-280.7696 240,-280.7696"/>
<text text-anchor="middle" x="383" y="-485.9696">m1</text>
</g>
<g class="m-node m-flat">
<title>p0xdf4c58</title>
<ellipse cx="119" cy="-442.7696" rx="42.3529" ry="18.2703"/>
<text text-anchor="middle" x="119" y="-438.9696">initial</text>
</g>
<g class="m-node m-flat">
<title>p0xdf4b70</title>
<polygon points="179.5,-324.7696 62.5,-324.7696 58.5,-320.7696 58.5,-288.7696 175.5,-288.7696 179.5,-292.7696 179.5,-324.7696"/>
<polyline points="175.5,-320.7696 58.5,-320.7696 "/>
<polyline points="175.5,-320.7696 175.5,-288.7696 "/>
<polyline points="175.5,-320.7696 179.5,-324.7696 "/>
<text text-anchor="middle" x="119" y="-302.9696">pipeline [m1]</text>
</g>
<g class="m-edge">
<title>p0xdf4c58->p0xdf4b70</title>
<path d="M119,-424.1445C119,-401.2544 119,-362.1696 119,-335.4397"/>
<polygon points="122.5001,-335.1696 119,-325.1697 115.5001,-335.1697 122.5001,-335.1696"/>
</g>
<g class="m-node">
<title>p0xdf4a88</title>
<polygon points="120,-196.7696 16,-170.7696 120,-144.7696 224,-170.7696 120,-196.7696"/>
<text text-anchor="middle" x="120" y="-166.9696">conditional</text>
</g>
<g class="m-edge">
<title>p0xdf4b70->p0xdf4a88</title>
<path d="M117.7501,-288.4464C117.0835,-277.7554 116.3335,-264.0054 116,-251.7696 115.5965,-236.965 116.2,-220.6513 117.0509,-206.5681"/>
<polygon points="120.5628,-206.5064 117.7374,-196.2953 113.5783,-206.0397 120.5628,-206.5064"/>
</g>
<g class="m-edge">
<title>p0xdf4a88->p0xdf4b70</title>
<path stroke-dasharray="5,2" d="M120.7949,-196.6738C121.2849,-216.865 121.6985,-245.6044 121,-270.7696 120.9326,-273.1981 120.8397,-275.7178 120.7305,-278.2451"/>
<polygon points="117.2233,-278.2997 120.214,-288.4636 124.2144,-278.6531 117.2233,-278.2997"/>
<text text-anchor="middle" x="126" y="-238.9696">0</text>
</g>
<g class="m-node m-flat">
<title>p0xdf4d40</title>
<ellipse cx="120" cy="-34.3848" rx="58.8803" ry="18.2703"/>
<text text-anchor="middle" x="120" y="-30.5848">terminal</text>
</g>
<g class="m-edge">
<title>p0xdf4a88->p0xdf4d40</title>
<path stroke-dasharray="5,2" d="M120,-144.4732C120,-121.2478 120,-87.4362 120,-63.4224"/>
<polygon points="123.5001,-63.1517 120,-53.1517 116.5001,-63.1517 123.5001,-63.1517"/>
<text text-anchor="middle" x="125" y="-94.9696">1</text>
</g>
<g class="m-node">
<title>p0xdf4600</title>
<polygon points="383,-468.7696 328,-442.7696 383,-416.7696 438,-442.7696 383,-468.7696"/>
<text text-anchor="middle" x="383" y="-438.9696">cond</text>
</g>
<g class="m-node m-flat">
<title>p0xdf46e8</title>
<polygon points="302,-324.7696 248,-324.7696 248,-320.7696 244,-320.7696 244,-316.7696 248,-316.7696 248,-296.7696 244,-296.7696 244,-292.7696 248,-292.7696 248,-288.7696 302,-288.7696 302,-324.7696"/>
<polyline points="248,-320.7696 252,-320.7696 252,-316.7696 248,-316.7696 "/>
<polyline points="248,-296.7696 252,-296.7696 252,-292.7696 248,-292.7696 "/>
<text text-anchor="middle" x="275" y="-302.9696">rt-0</text>
</g>
<g class="m-edge">
<title>p0xdf4600->p0xdf46e8</title>
<path stroke-dasharray="5,2" d="M367.9831,-423.8593C349.2598,-400.2819 317.1482,-359.845 295.996,-333.2089"/>
<polygon points="298.5041,-330.7392 289.5443,-325.0846 293.0223,-335.0924 298.5041,-330.7392"/>
<text text-anchor="middle" x="337" y="-366.9696">0</text>
</g>
<g class="m-node m-flat">
<title>p0xdf47d0</title>
<polygon points="374,-324.7696 320,-324.7696 320,-320.7696 316,-320.7696 316,-316.7696 320,-316.7696 320,-296.7696 316,-296.7696 316,-292.7696 320,-292.7696 320,-288.7696 374,-288.7696 374,-324.7696"/>
<polyline points="320,-320.7696 324,-320.7696 324,-316.7696 320,-316.7696 "/>
<polyline points="320,-296.7696 324,-296.7696 324,-292.7696 320,-292.7696 "/>
<text text-anchor="middle" x="347" y="-302.9696">rt-1</text>
</g>
<g class="m-edge">
<title>p0xdf4600->p0xdf47d0</title>
<path stroke-dasharray="5,2" d="M376.8114,-419.3903C370.6195,-395.9989 361.0892,-359.9954 354.4777,-335.0185"/>
<polygon points="357.7836,-333.8296 351.8411,-325.0581 351.0166,-335.6209 357.7836,-333.8296"/>
<text text-anchor="middle" x="371" y="-366.9696">1</text>
</g>
<g class="m-node m-flat">
<title>p0xdf48b8</title>
<polygon points="446,-324.7696 392,-324.7696 392,-320.7696 388,-320.7696 388,-316.7696 392,-316.7696 392,-296.7696 388,-296.7696 388,-292.7696 392,-292.7696 392,-288.7696 446,-288.7696 446,-324.7696"/>
<polyline points="392,-320.7696 396,-320.7696 396,-316.7696 392,-316.7696 "/>
<polyline points="392,-296.7696 396,-296.7696 396,-292.7696 392,-292.7696 "/>
<text text-anchor="middle" x="419" y="-302.9696">rt-2</text>
</g>
<g class="m-edge">
<title>p0xdf4600->p0xdf48b8</title>
<path stroke-dasharray="5,2" d="M389.1886,-419.3903C395.3805,-395.9989 404.9108,-359.9954 411.5223,-335.0185"/>
<polygon points="414.9834,-335.6209 414.1589,-325.0581 408.2164,-333.8296 414.9834,-335.6209"/>
<text text-anchor="middle" x="409" y="-366.9696">2</text>
</g>
<g class="m-node m-flat">
<title>p0xdf49a0</title>
<polygon points="518,-324.7696 464,-324.7696 464,-320.7696 460,-320.7696 460,-316.7696 464,-316.7696 464,-296.7696 460,-296.7696 460,-292.7696 464,-292.7696 464,-288.7696 518,-288.7696 518,-324.7696"/>
<polyline points="464,-320.7696 468,-320.7696 468,-316.7696 464,-316.7696 "/>
<polyline points="464,-296.7696 468,-296.7696 468,-292.7696 464,-292.7696 "/>
<text text-anchor="middle" x="491" y="-302.9696">rt-3</text>
</g>
<g class="m-edge">
<title>p0xdf4600->p0xdf49a0</title>
<path stroke-dasharray="5,2" d="M398.0169,-423.8593C416.7402,-400.2819 448.8518,-359.845 470.004,-333.2089"/>
<polygon points="472.9777,-335.0924 476.4557,-325.0846 467.4959,-330.7392 472.9777,-335.0924"/>
<text text-anchor="middle" x="451" y="-366.9696">3</text>
</g>
</g>
</svg>
</div><p>The following snippet shows one of the possible outputs:</p><pre class="m-code">initial
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">0</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">0</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">1</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">2</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">3</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">4</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">5</span>
Rerun the pipeline
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">5</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">5</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">6</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">6</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">6</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">7</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">7</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">7</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">8</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">8</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">8</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">9</span>
stage <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">9</span>
stage <span class="m">1</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">9</span>
stage <span class="m">2</span>: input buffer<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">10</span>
stop</pre><p>The pipeline runs twice as controlled by the condition task <code>conditional</code>. The starting token in the second run of the pipeline is <code>5</code> rather than <code>0</code> because the pipeline keeps a stateful number of tokens. The last token is <code>9</code>, which means the pipeline processes in total <code>10</code> scheduling tokens. The first five tokens (token <code>0</code> to <code>4</code>) are processed in the first run, and the remaining five tokens (token <code>5</code> to <code>9</code>) are processed in the second run. In the condition task, we use <code>N</code> as a decision-making counter to process the next stream of data.</p></section><section id="ConcatenateTwoPipelines"><h3><a href="#ConcatenateTwoPipelines">Example 2: Concatenate Two Pipelines</a></h3><p>This example demonstrates two concatenated pipelines where a sequence of data tokens run synchronously from one pipeline to another pipeline. The first pipeline task precedes the second pipeline task.</p><pre class="m-code"> <span class="mi">1</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span> <span class="n">taskflow</span><span class="p">(</span><span class="s">"pipeline"</span><span class="p">);</span>
<span class="mi">2</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Executor</span> <span class="n">executor</span><span class="p">;</span>
<span class="mi">3</span><span class="o">:</span>
<span class="mi">4</span><span class="o">:</span> <span class="c1">// define the maximum parallelism of the pipeline</span>
<span class="mi">5</span><span class="o">:</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_lines</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="mi">6</span><span class="o">:</span>
<span class="mi">7</span><span class="o">:</span> <span class="c1">// custom data storage</span>
<span class="mi">8</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer_1</span><span class="p">;</span>
<span class="mi">9</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer_2</span><span class="p">;</span>
<span class="mi">10</span><span class="o">:</span>
<span class="mi">11</span><span class="o">:</span> <span class="c1">// the pipeline_1 consists of three pipes (serial-parallel-serial)</span>
<span class="mi">12</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">13</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl_1</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">14</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="k">mutable</span><span class="p">{</span>
<span class="mi">15</span><span class="o">:</span> <span class="c1">// generate only 4 scheduling tokens</span>
<span class="mi">16</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">()</span> <span class="o">==</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">17</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">18</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">19</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">20</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">21</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"pipeline 1, pipe 0: input token = %zu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">());</span>
<span class="mi">22</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">();</span>
<span class="mi">23</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">24</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">25</span><span class="o">:</span>
<span class="mi">26</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">27</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">28</span><span class="o">:</span> <span class="s">"pipeline 1, pipe 1: input buffer_1[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">29</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">30</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">31</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">32</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">33</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">34</span><span class="o">:</span>
<span class="mi">35</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">36</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">37</span><span class="o">:</span> <span class="s">"pipeline 1, pipe 2: input buffer_1[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">38</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">39</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">40</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">41</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">42</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">43</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">44</span><span class="o">:</span>
<span class="mi">45</span><span class="o">:</span> <span class="c1">// the pipeline_2 consists of three pipes (serial-parallel-serial)</span>
<span class="mi">46</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">47</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl_2</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">48</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span>
<span class="mi">49</span><span class="o">:</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">,</span> <span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="k">mutable</span><span class="p">{</span>
<span class="mi">50</span><span class="o">:</span> <span class="c1">// generate only 4 scheduling tokens</span>
<span class="mi">51</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">()</span> <span class="o">==</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">52</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">53</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">54</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">55</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">56</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"pipeline 2, pipe 0: input value = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]);</span>
<span class="mi">57</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()];</span>
<span class="mi">58</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">59</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">60</span><span class="o">:</span>
<span class="mi">61</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">62</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">63</span><span class="o">:</span> <span class="s">"pipeline 2, pipe 1: input buffer_2[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">64</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">65</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">66</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding 1</span>
<span class="mi">67</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">68</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">69</span><span class="o">:</span>
<span class="mi">70</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">71</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">72</span><span class="o">:</span> <span class="s">"pipeline 2, pipe 2: input buffer_2[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">73</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">74</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">75</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding 1</span>
<span class="mi">76</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">77</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">78</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">79</span><span class="o">:</span>
<span class="mi">80</span><span class="o">:</span> <span class="c1">// build the pipeline graph using composition</span>
<span class="mi">81</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline_1</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl_1</span><span class="p">).</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline_1"</span><span class="p">);</span>
<span class="mi">82</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline_2</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl_2</span><span class="p">).</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline_2"</span><span class="p">);</span>
<span class="mi">83</span><span class="o">:</span>
<span class="mi">84</span><span class="o">:</span> <span class="c1">// specify the graph dependency</span>
<span class="mi">85</span><span class="o">:</span> <span class="n">pipeline_1</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pipeline_2</span><span class="p">);</span>
<span class="mi">86</span><span class="o">:</span>
<span class="mi">87</span><span class="o">:</span> <span class="c1">// execute the taskflow</span>
<span class="mi">88</span><span class="o">:</span> <span class="n">executor</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">taskflow</span><span class="p">).</span><span class="n">wait</span><span class="p">();</span></pre> <p><br />Debrief:</p><ul><li>Line 8 defines the data storage (<code>num_lines</code> integers) for pipeline <code>pl_1</code></li><li>Line 9 defines the data storage (<code>num_lines</code> integers) for pipeline <code>pl_2</code></li><li>Lines 14-24 define the first serial pipe in <code>pl_1</code></li><li>Lines 26-33 define the second parallel pipe in <code>pl_1</code></li><li>Lines 35-42 define the third serial pipe in <code>pl_1</code></li><li>Lines 48-59 define the first serial pipe in <code>pl_2</code> that takes the results of <code>pl_1</code> as inputs</li><li>Lines 61-68 define the second parallel pipe in <code>pl_2</code></li><li>Lines 70-77 define the third serial pipe in <code>pl_2</code></li><li>Lines 81-82 define the pipeline graphs using composition</li><li>Line 85 defines the task dependency</li><li>Line 88 runs the taskflow</li></ul><p>The taskflow graph of this pipeline example is illustrated as follows:</p><div class="m-graph"><svg style="width: 48.000rem; height: 15.375rem;" viewBox="0.00 0.00 768.00 246.00">
<g transform="scale(1 1) rotate(0) translate(4 242)">
<title>Taskflow</title>
<g class="m-cluster">
<title>cluster_p0x7ffeaf4d98d8</title>
<polygon points="8,-8 8,-222 164,-222 164,-8 8,-8"/>
<text text-anchor="middle" x="86" y="-205.2">Taskflow</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7ffeaf4d9510</title>
<polygon points="172,-8 172,-230 458,-230 458,-8 172,-8"/>
<text text-anchor="middle" x="315" y="-213.2">m2</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7ffeaf4d95b0</title>
<polygon points="466,-8 466,-230 752,-230 752,-8 466,-8"/>
<text text-anchor="middle" x="609" y="-213.2">m1</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4f10</title>
<polygon points="155.5,-188 20.5,-188 16.5,-184 16.5,-152 151.5,-152 155.5,-156 155.5,-188"/>
<polyline points="151.5,-184 16.5,-184 "/>
<polyline points="151.5,-184 151.5,-152 "/>
<polyline points="151.5,-184 155.5,-188 "/>
<text text-anchor="middle" x="86" y="-166.2">pipeline_1 [m1]</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4ff8</title>
<polygon points="155.5,-52 20.5,-52 16.5,-48 16.5,-16 151.5,-16 155.5,-20 155.5,-52"/>
<polyline points="151.5,-48 16.5,-48 "/>
<polyline points="151.5,-48 151.5,-16 "/>
<polyline points="151.5,-48 155.5,-52 "/>
<text text-anchor="middle" x="86" y="-30.2">pipeline_2 [m2]</text>
</g>
<g class="m-edge">
<title>p0x1da4f10->p0x1da4ff8</title>
<path d="M86,-151.9403C86,-129.0783 86,-89.4314 86,-62.4761"/>
<polygon points="89.5001,-62.1344 86,-52.1344 82.5001,-62.1345 89.5001,-62.1344"/>
</g>
<g class="m-node">
<title>p0x1da4a88</title>
<polygon points="315,-196 260,-170 315,-144 370,-170 315,-196"/>
<text text-anchor="middle" x="315" y="-166.2">cond</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4b70</title>
<polygon points="234,-52 180,-52 180,-48 176,-48 176,-44 180,-44 180,-24 176,-24 176,-20 180,-20 180,-16 234,-16 234,-52"/>
<polyline points="180,-48 184,-48 184,-44 180,-44 "/>
<polyline points="180,-24 184,-24 184,-20 180,-20 "/>
<text text-anchor="middle" x="207" y="-30.2">rt-0</text>
</g>
<g class="m-edge">
<title>p0x1da4a88->p0x1da4b70</title>
<path stroke-dasharray="5,2" d="M299.9831,-151.0898C281.2598,-127.5123 249.1482,-87.0755 227.996,-60.4394"/>
<polygon points="230.5041,-57.9696 221.5443,-52.3151 225.0223,-62.3228 230.5041,-57.9696"/>
<text text-anchor="middle" x="269" y="-94.2">0</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4c58</title>
<polygon points="306,-52 252,-52 252,-48 248,-48 248,-44 252,-44 252,-24 248,-24 248,-20 252,-20 252,-16 306,-16 306,-52"/>
<polyline points="252,-48 256,-48 256,-44 252,-44 "/>
<polyline points="252,-24 256,-24 256,-20 252,-20 "/>
<text text-anchor="middle" x="279" y="-30.2">rt-1</text>
</g>
<g class="m-edge">
<title>p0x1da4a88->p0x1da4c58</title>
<path stroke-dasharray="5,2" d="M308.8114,-146.6208C302.6195,-123.2294 293.0892,-87.2258 286.4777,-62.249"/>
<polygon points="289.7836,-61.06 283.8411,-52.2886 283.0166,-62.8513 289.7836,-61.06"/>
<text text-anchor="middle" x="303" y="-94.2">1</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4d40</title>
<polygon points="378,-52 324,-52 324,-48 320,-48 320,-44 324,-44 324,-24 320,-24 320,-20 324,-20 324,-16 378,-16 378,-52"/>
<polyline points="324,-48 328,-48 328,-44 324,-44 "/>
<polyline points="324,-24 328,-24 328,-20 324,-20 "/>
<text text-anchor="middle" x="351" y="-30.2">rt-2</text>
</g>
<g class="m-edge">
<title>p0x1da4a88->p0x1da4d40</title>
<path stroke-dasharray="5,2" d="M321.1886,-146.6208C327.3805,-123.2294 336.9108,-87.2258 343.5223,-62.249"/>
<polygon points="346.9834,-62.8513 346.1589,-52.2886 340.2164,-61.06 346.9834,-62.8513"/>
<text text-anchor="middle" x="341" y="-94.2">2</text>
</g>
<g class="m-node m-flat">
<title>p0x1da4e28</title>
<polygon points="450,-52 396,-52 396,-48 392,-48 392,-44 396,-44 396,-24 392,-24 392,-20 396,-20 396,-16 450,-16 450,-52"/>
<polyline points="396,-48 400,-48 400,-44 396,-44 "/>
<polyline points="396,-24 400,-24 400,-20 396,-20 "/>
<text text-anchor="middle" x="423" y="-30.2">rt-3</text>
</g>
<g class="m-edge">
<title>p0x1da4a88->p0x1da4e28</title>
<path stroke-dasharray="5,2" d="M330.0169,-151.0898C348.7402,-127.5123 380.8518,-87.0755 402.004,-60.4394"/>
<polygon points="404.9777,-62.3228 408.4557,-52.3151 399.4959,-57.9696 404.9777,-62.3228"/>
<text text-anchor="middle" x="383" y="-94.2">3</text>
</g>
<g class="m-node">
<title>p0x1da4600</title>
<polygon points="609,-196 554,-170 609,-144 664,-170 609,-196"/>
<text text-anchor="middle" x="609" y="-166.2">cond</text>
</g>
<g class="m-node m-flat">
<title>p0x1da46e8</title>
<polygon points="528,-52 474,-52 474,-48 470,-48 470,-44 474,-44 474,-24 470,-24 470,-20 474,-20 474,-16 528,-16 528,-52"/>
<polyline points="474,-48 478,-48 478,-44 474,-44 "/>
<polyline points="474,-24 478,-24 478,-20 474,-20 "/>
<text text-anchor="middle" x="501" y="-30.2">rt-0</text>
</g>
<g class="m-edge">
<title>p0x1da4600->p0x1da46e8</title>
<path stroke-dasharray="5,2" d="M593.9831,-151.0898C575.2598,-127.5123 543.1482,-87.0755 521.996,-60.4394"/>
<polygon points="524.5041,-57.9696 515.5443,-52.3151 519.0223,-62.3228 524.5041,-57.9696"/>
<text text-anchor="middle" x="563" y="-94.2">0</text>
</g>
<g class="m-node m-flat">
<title>p0x1da47d0</title>
<polygon points="600,-52 546,-52 546,-48 542,-48 542,-44 546,-44 546,-24 542,-24 542,-20 546,-20 546,-16 600,-16 600,-52"/>
<polyline points="546,-48 550,-48 550,-44 546,-44 "/>
<polyline points="546,-24 550,-24 550,-20 546,-20 "/>
<text text-anchor="middle" x="573" y="-30.2">rt-1</text>
</g>
<g class="m-edge">
<title>p0x1da4600->p0x1da47d0</title>
<path stroke-dasharray="5,2" d="M602.8114,-146.6208C596.6195,-123.2294 587.0892,-87.2258 580.4777,-62.249"/>
<polygon points="583.7836,-61.06 577.8411,-52.2886 577.0166,-62.8513 583.7836,-61.06"/>
<text text-anchor="middle" x="597" y="-94.2">1</text>
</g>
<g class="m-node m-flat">
<title>p0x1da48b8</title>
<polygon points="672,-52 618,-52 618,-48 614,-48 614,-44 618,-44 618,-24 614,-24 614,-20 618,-20 618,-16 672,-16 672,-52"/>
<polyline points="618,-48 622,-48 622,-44 618,-44 "/>
<polyline points="618,-24 622,-24 622,-20 618,-20 "/>
<text text-anchor="middle" x="645" y="-30.2">rt-2</text>
</g>
<g class="m-edge">
<title>p0x1da4600->p0x1da48b8</title>
<path stroke-dasharray="5,2" d="M615.1886,-146.6208C621.3805,-123.2294 630.9108,-87.2258 637.5223,-62.249"/>
<polygon points="640.9834,-62.8513 640.1589,-52.2886 634.2164,-61.06 640.9834,-62.8513"/>
<text text-anchor="middle" x="635" y="-94.2">2</text>
</g>
<g class="m-node m-flat">
<title>p0x1da49a0</title>
<polygon points="744,-52 690,-52 690,-48 686,-48 686,-44 690,-44 690,-24 686,-24 686,-20 690,-20 690,-16 744,-16 744,-52"/>
<polyline points="690,-48 694,-48 694,-44 690,-44 "/>
<polyline points="690,-24 694,-24 694,-20 690,-20 "/>
<text text-anchor="middle" x="717" y="-30.2">rt-3</text>
</g>
<g class="m-edge">
<title>p0x1da4600->p0x1da49a0</title>
<path stroke-dasharray="5,2" d="M624.0169,-151.0898C642.7402,-127.5123 674.8518,-87.0755 696.004,-60.4394"/>
<polygon points="698.9777,-62.3228 702.4557,-52.3151 693.4959,-57.9696 698.9777,-62.3228"/>
<text text-anchor="middle" x="677" y="-94.2">3</text>
</g>
</g>
</svg>
</div><p>The following snippet shows one of the possible outputs:</p><pre class="m-code">pipeline <span class="m">1</span>, pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">0</span>
pipeline <span class="m">1</span>, pipe <span class="m">1</span>: input buffer_1<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">0</span>
pipeline <span class="m">1</span>, pipe <span class="m">2</span>: input buffer_1<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
pipeline <span class="m">1</span>, pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">1</span>
pipeline <span class="m">1</span>, pipe <span class="m">1</span>: input buffer_1<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">1</span>
pipeline <span class="m">1</span>, pipe <span class="m">2</span>: input buffer_1<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
pipeline <span class="m">1</span>, pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">2</span>
pipeline <span class="m">1</span>, pipe <span class="m">1</span>: input buffer_1<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
pipeline <span class="m">1</span>, pipe <span class="m">2</span>: input buffer_1<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">1</span>, pipe <span class="m">0</span>: input <span class="nv">token</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">1</span>, pipe <span class="m">1</span>: input buffer_1<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">1</span>, pipe <span class="m">2</span>: input buffer_1<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
pipeline <span class="m">2</span>, pipe <span class="m">1</span>: input <span class="nv">value</span> <span class="o">=</span> <span class="m">2</span>
pipeline <span class="m">2</span>, pipe <span class="m">2</span>: input buffer_2<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">2</span>
pipeline <span class="m">2</span>, pipe <span class="m">3</span>: input buffer_2<span class="o">[</span><span class="m">0</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">2</span>, pipe <span class="m">1</span>: input <span class="nv">value</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">2</span>, pipe <span class="m">2</span>: input buffer_2<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">3</span>
pipeline <span class="m">2</span>, pipe <span class="m">3</span>: input buffer_2<span class="o">[</span><span class="m">1</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
pipeline <span class="m">2</span>, pipe <span class="m">1</span>: input <span class="nv">value</span> <span class="o">=</span> <span class="m">4</span>
pipeline <span class="m">2</span>, pipe <span class="m">2</span>: input buffer_2<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">4</span>
pipeline <span class="m">2</span>, pipe <span class="m">3</span>: input buffer_2<span class="o">[</span><span class="m">2</span><span class="o">]</span> <span class="o">=</span> <span class="m">5</span>
pipeline <span class="m">2</span>, pipe <span class="m">1</span>: input <span class="nv">value</span> <span class="o">=</span> <span class="m">5</span>
pipeline <span class="m">2</span>, pipe <span class="m">2</span>: input buffer_2<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">5</span>
pipeline <span class="m">2</span>, pipe <span class="m">3</span>: input buffer_2<span class="o">[</span><span class="m">3</span><span class="o">]</span> <span class="o">=</span> <span class="m">6</span></pre><p>The output of pipelines <code>pl_1</code> and <code>pl_2</code> can be different from run to run because their second pipes are both parallel types. Due to the task dependency between <code>pipeline_1</code> and <code>pipeline_2</code>, the output of <code>pl_1</code> precedes the output of <code>pl_2</code>.</p></section><section id="DefineMultipleParallelPipelines"><h3><a href="#DefineMultipleParallelPipelines">Example 3: Define Multiple Parallel Pipelines</a></h3><p>This example creates two independent pipelines that run in parallel on different data sets.</p><pre class="m-code"> <span class="mi">1</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Taskflow</span> <span class="n">taskflow</span><span class="p">(</span><span class="s">"pipeline"</span><span class="p">);</span>
<span class="mi">2</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Executor</span> <span class="n">executor</span><span class="p">;</span>
<span class="mi">3</span><span class="o">:</span>
<span class="mi">4</span><span class="o">:</span> <span class="c1">// define the maximum parallelism of the pipeline</span>
<span class="mi">5</span><span class="o">:</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_lines</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="mi">6</span><span class="o">:</span>
<span class="mi">7</span><span class="o">:</span> <span class="c1">// custom data storage</span>
<span class="mi">8</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer_1</span><span class="p">;</span>
<span class="mi">9</span><span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o"><</span><span class="kt">int</span><span class="p">,</span> <span class="n">num_lines</span><span class="o">></span> <span class="n">buffer_2</span><span class="p">;</span>
<span class="mi">10</span><span class="o">:</span>
<span class="mi">11</span><span class="o">:</span> <span class="c1">// the pipeline_1 consists of three pipes (serial-parallel-serial)</span>
<span class="mi">12</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">13</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl_1</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">14</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="k">mutable</span><span class="p">{</span>
<span class="mi">15</span><span class="o">:</span> <span class="c1">// generate only 5 scheduling tokens</span>
<span class="mi">16</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">()</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">17</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">18</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">19</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">20</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">21</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"pipeline 1, pipe 0: input token = %zu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">());</span>
<span class="mi">22</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">();</span>
<span class="mi">23</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">24</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">25</span><span class="o">:</span>
<span class="mi">26</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">27</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">28</span><span class="o">:</span> <span class="s">"pipeline 1, pipe 1: input buffer_1[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">29</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">30</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">31</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">32</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">33</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">34</span><span class="o">:</span>
<span class="mi">35</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_1</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">36</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">37</span><span class="o">:</span> <span class="s">"pipeline 1, pipe 2: input buffer_1[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">38</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">39</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">40</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by adding one</span>
<span class="mi">41</span><span class="o">:</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_1</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="mi">42</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">43</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">44</span><span class="o">:</span>
<span class="mi">45</span><span class="o">:</span> <span class="c1">// the pipeline_2 consists of three pipes (serial-parallel-serial)</span>
<span class="mi">46</span><span class="o">:</span> <span class="c1">// and up to four concurrent scheduling tokens</span>
<span class="mi">47</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipeline</span> <span class="n">pl_2</span><span class="p">(</span><span class="n">num_lines</span><span class="p">,</span>
<span class="mi">48</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="k">mutable</span><span class="p">{</span>
<span class="mi">49</span><span class="o">:</span> <span class="c1">// generate only 2 scheduling tokens</span>
<span class="mi">50</span><span class="o">:</span> <span class="k">if</span><span class="p">(</span><span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">()</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">51</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
<span class="mi">52</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">53</span><span class="o">:</span> <span class="c1">// save the result of this pipe into the buffer</span>
<span class="mi">54</span><span class="o">:</span> <span class="k">else</span> <span class="p">{</span>
<span class="mi">55</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span><span class="s">"pipeline 2, pipe 0: input token = %zu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">pf</span><span class="p">.</span><span class="n">token</span><span class="p">());</span>
<span class="mi">56</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="s">"pipeline"</span><span class="p">;</span>
<span class="mi">57</span><span class="o">:</span> <span class="p">}</span>
<span class="mi">58</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">59</span><span class="o">:</span>
<span class="mi">60</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">PARALLEL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">61</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">62</span><span class="o">:</span> <span class="s">"pipeline 2, pipe 1: input buffer_2[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">63</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">64</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">65</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by concatenating "_"</span>
<span class="mi">66</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()];</span>
<span class="mi">67</span><span class="o">:</span> <span class="p">}},</span>
<span class="mi">68</span><span class="o">:</span>
<span class="mi">69</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Pipe</span><span class="p">{</span><span class="n">tf</span><span class="o">::</span><span class="n">PipeType</span><span class="o">::</span><span class="n">SERIAL</span><span class="p">,</span> <span class="p">[</span><span class="o">&</span><span class="n">buffer_2</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">Pipeflow</span><span class="o">&</span> <span class="n">pf</span><span class="p">)</span> <span class="p">{</span>
<span class="mi">70</span><span class="o">:</span> <span class="n">printf</span><span class="p">(</span>
<span class="mi">71</span><span class="o">:</span> <span class="s">"pipeline 2, pipe 2: input buffer_2[%zu] = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="mi">72</span><span class="o">:</span> <span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">(),</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span>
<span class="mi">73</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">74</span><span class="o">:</span> <span class="c1">// propagate the previous result to this pipe by concatenating "2"</span>
<span class="mi">75</span><span class="o">:</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()]</span> <span class="o">=</span> <span class="n">buffer_2</span><span class="p">[</span><span class="n">pf</span><span class="p">.</span><span class="n">line</span><span class="p">()];</span>
<span class="mi">76</span><span class="o">:</span> <span class="p">}}</span>
<span class="mi">77</span><span class="o">:</span> <span class="p">);</span>
<span class="mi">78</span><span class="o">:</span>
<span class="mi">79</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline_1</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl_1</span><span class="p">)</span>
<span class="mi">80</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline_1"</span><span class="p">);</span>
<span class="mi">81</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">pipeline_2</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">composed_of</span><span class="p">(</span><span class="n">pl_2</span><span class="p">)</span>
<span class="mi">82</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"pipeline_2"</span><span class="p">);</span>
<span class="mi">83</span><span class="o">:</span> <span class="n">tf</span><span class="o">::</span><span class="n">Task</span> <span class="n">initial</span> <span class="o">=</span> <span class="n">taskflow</span><span class="p">.</span><span class="n">emplace</span><span class="p">([](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"initial"</span><span class="p">;</span> <span class="p">})</span>
<span class="mi">84</span><span class="o">:</span> <span class="p">.</span><span class="n">name</span><span class="p">(</span><span class="s">"initial"</span><span class="p">);</span>
<span class="mi">85</span><span class="o">:</span>
<span class="mi">86</span><span class="o">:</span> <span class="n">initial</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pipeline_1</span><span class="p">,</span> <span class="n">pipeline_2</span><span class="p">);</span>
<span class="mi">87</span><span class="o">:</span>
<span class="mi">88</span><span class="o">:</span> <span class="n">executor</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">taskflow</span><span class="p">).</span><span class="n">wait</span><span class="p">();</span></pre><p>Debrief:</p><ul><li>Line 8 defines the data storage (<code>num_lines</code> integers) for pipeline <code>pl_1</code></li><li>Line 9 defines the data storage (<code>num_lines</code> integers) for pipeline <code>pl_2</code></li><li>Lines 14-24 define the first serial pipe in <code>pl_1</code></li><li>Lines 26-33 define the second parallel pipe in <code>pl_1</code></li><li>Lines 35-42 define the third serial pipe in <code>pl_1</code></li><li>Lines 48-58 define the first serial pipe in <code>pl_2</code></li><li>Lines 60-67 define the second parallel pipe in <code>pl_2</code></li><li>Lines 69-76 define the third serial pipe in <code>pl_2</code></li><li>Lines 79-82 define the pipeline graphs using composition</li><li>Lines 83-84 define a static task.</li><li>Line 86 defines the task dependency</li><li>Line 88 runs the taskflow</li></ul><p>The taskflow graph of this pipeline example is illustrated as follows:</p><div class="m-graph"><svg style="width: 57.812rem; height: 15.375rem;" viewBox="0.00 0.00 925.00 246.00">
<g transform="scale(1 1) rotate(0) translate(4 242)">
<title>Taskflow</title>
<g class="m-cluster">
<title>cluster_p0x7ffe35bde158</title>
<polygon points="8,-8 8,-222.3848 321,-222.3848 321,-8 8,-8"/>
<text text-anchor="middle" x="164.5" y="-205.5848">Taskflow</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7ffe35bddd80</title>
<polygon points="329,-8 329,-230 615,-230 615,-8 329,-8"/>
<text text-anchor="middle" x="472" y="-213.2">m2</text>
</g>
<g class="m-cluster">
<title>cluster_p0x7ffe35bdde20</title>
<polygon points="623,-8 623,-230 909,-230 909,-8 623,-8"/>
<text text-anchor="middle" x="766" y="-213.2">m1</text>
</g>
<g class="m-node m-flat">
<title>p0x131af10</title>
<polygon points="155.5,-52 20.5,-52 16.5,-48 16.5,-16 151.5,-16 155.5,-20 155.5,-52"/>
<polyline points="151.5,-48 16.5,-48 "/>
<polyline points="151.5,-48 151.5,-16 "/>
<polyline points="151.5,-48 155.5,-52 "/>
<text text-anchor="middle" x="86" y="-30.2">pipeline_1 [m1]</text>
</g>
<g class="m-node m-flat">
<title>p0x131aff8</title>
<polygon points="312.5,-52 177.5,-52 173.5,-48 173.5,-16 308.5,-16 312.5,-20 312.5,-52"/>
<polyline points="308.5,-48 173.5,-48 "/>
<polyline points="308.5,-48 308.5,-16 "/>
<polyline points="308.5,-48 312.5,-52 "/>
<text text-anchor="middle" x="243" y="-30.2">pipeline_2 [m2]</text>
</g>
<g class="m-node m-flat">
<title>p0x131b0e0</title>
<ellipse cx="164" cy="-170" rx="42.3529" ry="18.2703"/>
<text text-anchor="middle" x="164" y="-166.2">initial</text>
</g>
<g class="m-edge">
<title>p0x131b0e0->p0x131af10</title>
<path d="M153.6422,-151.9403C140.2971,-128.6718 116.98,-88.0164 101.5144,-61.0507"/>
<polygon points="104.4119,-59.0677 96.4006,-52.1344 98.3397,-62.5503 104.4119,-59.0677"/>
</g>
<g class="m-edge">
<title>p0x131b0e0->p0x131aff8</title>
<path d="M174.4906,-151.9403C188.0068,-128.6718 211.6228,-88.0164 227.2867,-61.0507"/>
<polygon points="230.4695,-62.5395 232.466,-52.1344 224.4166,-59.0234 230.4695,-62.5395"/>
</g>
<g class="m-node">