Skip to content
Navigation Menu
{{ message }}
forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchapter3.html
More file actions
163 lines (161 loc) · 23.7 KB
/
Copy pathchapter3.html
File metadata and controls
163 lines (161 loc) · 23.7 KB
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
<!-- HTML header for doxygen 1.8.13-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Cpp-Taskflow</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { init_search(); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname"><a href="https://github.com/cpp-taskflow/cpp-taskflow">Cpp-Taskflow</a>
 <span id="projectnumber">2.2.0</span>
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('chapter3.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="headertitle">
<div class="title">C3: Create a Parallel For-loop Graph </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Running a for-loop in parallel is the most fundamental building block in parallel programming. In this chapter, we are going to demonstrate how to use Cpp-Taskflow to create a task dependency graph of parallel for-loop.</p>
<h1><a class="anchor" id="RangeBasedForLoop"></a>
Range-based For-loop</h1>
<p>Cpp-Taskflow has a STL-style method <a class="el" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e" title="constructs a task dependency graph of range-based parallel_for ">tf::Taskflow::parallel_for(I beg, I end, C&& callable, size_t chunk)</a> that takes a range of items and applies a callable to each of the item in parallel. The method constructs a task dependency graph representing this workload and returns a task pair as two synchronization points to this task graph.</p>
<div class="fragment"><div class="line"> 1: <a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"> 2:</div><div class="line"> 3: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector<int></a> items {1, 2, 3, 4, 5, 6, 7, 8};</div><div class="line"> 4:</div><div class="line"> 5: <span class="keyword">auto</span> [S, T] = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(items.begin(), items.end(), [] (<span class="keywordtype">int</span> item) {</div><div class="line"> 6: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/get_id.html">std::this_thread::get_id</a>() << <span class="stringliteral">" runs "</span> << item << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line"> 7: });</div><div class="line"> 8:</div><div class="line"> 9: S.work([](){ <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"S\n"</span>; }).name(<span class="stringliteral">"S"</span>);</div><div class="line">10: T.work([](){ <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"T\n"</span>; }).name(<span class="stringliteral">"T"</span>);</div><div class="line">11:</div><div class="line">12: taskflow.<a class="code" href="classtf_1_1Taskflow.html#ac433018262e44b12c4cc9f0c4748d758">dump</a>(<a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a>);</div></div><!-- fragment --><p>The above code generates the following task dependency graph. The label 0x56* represents an internal task node to execute the callable object. By default (<code>chunk=0</code>), Cpp-Taskflow evenly partitions and distributes the workload to all threads. In our example of eight tasks and four workers, each internal node is responsible for two items.</p>
<div class="image">
<img src="parallel_for1.png" alt="parallel_for1.png" width="60%"/>
</div>
<p>Debrief: </p><ul>
<li>Line 1 creates a taskflow object of four worker threads </li>
<li>Line 3 creates a vector container of eight items </li>
<li>Line 5-7 creates a parallel execution graph using the method <code>parallel_for</code> </li>
<li>Line 9-10 names the synchronization tasks <code>S</code> and <code>T</code> </li>
<li>Line 12 dumps the graph to a dot format which can be visualized through <a href="https://dreampuf.github.io/GraphvizOnline/">GraphViz Online</a></li>
</ul>
<p>Here is one possible output of this program:</p>
<div class="fragment"><div class="line">S</div><div class="line">139931471636224 runs 1</div><div class="line">139931471636224 runs 2</div><div class="line">139931480028928 runs 7</div><div class="line">139931480028928 runs 8</div><div class="line">139931496814336 runs 3</div><div class="line">139931496814336 runs 4</div><div class="line">139931488421632 runs 5</div><div class="line">139931488421632 runs 6</div><div class="line">T</div></div><!-- fragment --><h1><a class="anchor" id="PartitionTheWorkloadExplicitly"></a>
Partition the Workload Explicitly</h1>
<p>By default, Cpp-Taskflow partitions the workload evenly across the workers. In some cases, it is useful to disable this feature and apply user-specified partition. The method <code>parallel_for</code> tasks an unsigned integer <code>chunk</code> as the number of items in each partition.</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> [S, T] = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(items.begin(), items.end(), [] (<span class="keywordtype">int</span> item) {</div><div class="line"> <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/get_id.html">std::this_thread::get_id</a>() << <span class="stringliteral">" runs "</span> << item << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line">}, 1);</div></div><!-- fragment --><p>The above example will force each partition to run exactly one item. This can be useful when you have unbalanced workload and would like to enable more efficient parallelization.</p>
<div class="image">
<img src="parallel_for2.png" alt="parallel_for2.png" width="100%"/>
</div>
<p>You can leave the chunk size to 0 to use our default partition strategy.</p>
<h1><a class="anchor" id="ConstructTheGraphExplicitly"></a>
Construct the Graph Explicitly</h1>
<p>You can explicitly construct a dependency graph that represents a parallel execution of a for-loop using only the basic methods <a class="el" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c" title="creates a task from a given callable object ">tf::Taskflow::emplace</a> and <a class="el" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588" title="adds precedence links from this to other tasks ">tf::Task::precede</a>.</p>
<div class="fragment"><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> S = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([](){}).name(<span class="stringliteral">"S"</span>);</div><div class="line"><a class="code" href="classtf_1_1Task.html">tf::Task</a> T = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([](){}).name(<span class="stringliteral">"T"</span>);</div><div class="line"></div><div class="line"><span class="keywordflow">for</span>(<span class="keyword">auto</span> item : items) {</div><div class="line"> <a class="code" href="classtf_1_1Task.html">tf::Task</a> task = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([item] () {</div><div class="line"> <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/thread/get_id.html">std::this_thread::get_id</a>() << <span class="stringliteral">" runs "</span> << item << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line"> });</div><div class="line"> S.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(task);</div><div class="line"> task.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(T);</div><div class="line">}</div></div><!-- fragment --><h1><a class="anchor" id="IndexBasedForLoop"></a>
Index-based For-loop</h1>
<p>Cpp-Taskflow provides an overload <a class="el" href="classtf_1_1FlowBuilder.html#abe18f8824cba16cde03e0dea8fae14ac" title="constructs a task dependency graph of index-based parallel_for ">tf::Taskflow::parallel_for(I beg, I end, I step, C&& callable, size_t chunk)</a> to parallelize an index-based for-loop. It takes three numbers <code>beg</code>, <code>end</code>, and <code>step</code> of the same type <code>I</code> and applies <code>callable</code> to each index in the range <code>[beg, end)</code> with the step size <code>step</code>.</p>
<div class="fragment"><div class="line">1: taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(0, 10, 2, [] (<span class="keywordtype">int</span> i) {</div><div class="line">2: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"parallel on "</span> << i << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line">3: });</div><div class="line">4: <span class="comment">// print 0, 2, 4, 6, 8</span></div></div><!-- fragment --><p>It also works on the opposite order with negative step size.</p>
<div class="fragment"><div class="line">1: taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(10, 0, -2, [] (<span class="keywordtype">int</span> i) {</div><div class="line">2: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"parallel on "</span> << i << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line">3: });</div><div class="line">4: <span class="comment">// print 10, 8, 6, 4, 2</span></div></div><!-- fragment --><p>Similarly, you can specify a chunk size to group the works per thread.</p>
<div class="fragment"><div class="line">1: taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(0, 10, 2, [] (<span class="keywordtype">int</span> i) {</div><div class="line">2: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"parallel on "</span> << i << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line">3: }, 2);</div><div class="line">4: <span class="comment">// print 0, 2, 4, 6, 8 (three groups {0, 2}, {4, 6}, {8})</span></div></div><!-- fragment --><p>By default, Cpp-Taskflow performs even partition across the number of available threads if no group size is given.</p>
<h1><a class="anchor" id="Chapter3Example1"></a>
Example 1: Parallel Map</h1>
<p>This example demonstrates how to use <a class="el" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e" title="constructs a task dependency graph of range-based parallel_for ">tf::Taskflow::parallel_for</a> to create a parallel map pattern. The map operator modifies each item in the container to one if it is an odd number, or zero if it is an even number.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include <taskflow/taskflow.hpp></span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() {</div><div class="line"> </div><div class="line"> <a class="code" href="classtf_1_1Executor.html">tf::Executor</a> executor;</div><div class="line"> <a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"></div><div class="line"> <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector<int></a> items{1, 2, 3, 4, 5, 6, 7, 8};</div><div class="line"></div><div class="line"> taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(items.begin(), items.end(), [] (<span class="keywordtype">int</span>& item) {</div><div class="line"> item = (item & 1) ? 1 : 0;</div><div class="line"> });</div><div class="line"></div><div class="line"> executor.<a class="code" href="classtf_1_1Executor.html#a93d3b5c6f5612c1b32033f2dcd27b2a5">run</a>(taskflow).get();</div><div class="line"></div><div class="line"> <span class="keywordflow">for</span>(<span class="keyword">auto</span> item : items) {</div><div class="line"> <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << item << <span class="stringliteral">" "</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><p>The program outputs the following:</p>
<div class="fragment"><div class="line">1 0 1 0 1 0 1 0 </div></div><!-- fragment --><h1><a class="anchor" id="Chapter3Example2"></a>
Example 2: Pipeline a Parallel For-loop</h1>
<p>This example demonstrates how to pipeline a parallel-for workload with other tasks.</p>
<div class="fragment"><div class="line"> 1: #include <taskflow/taskflow.hpp></div><div class="line"> 2:</div><div class="line"> 3: <span class="keywordtype">int</span> main() {</div><div class="line"> 4:</div><div class="line"> 5: <a class="code" href="classtf_1_1Taskflow.html">tf::Taskflow</a> taskflow;</div><div class="line"> 6:</div><div class="line"> 7: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/container/vector.html">std::vector<int></a> items(1024);</div><div class="line"> 8: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/atomic/atomic.html">std::atomic<int></a> sum {0};</div><div class="line"> 9:</div><div class="line">10: <a class="code" href="classtf_1_1Task.html">tf::Task</a> T1 = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () { <span class="comment">// create a modifier task</span></div><div class="line">11: <span class="keywordflow">for</span>(<span class="keyword">auto</span>& item : items) {</div><div class="line">12: item = 1;</div><div class="line">13: }</div><div class="line">14: }).name(<span class="stringliteral">"Create Items"</span>);</div><div class="line">15:</div><div class="line">16: <span class="keyword">auto</span> [S, T] = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a84d411f16939bc158c5a90256e5d210e">parallel_for</a>(items.begin(), items.end(), [&] (<span class="keywordtype">int</span> item) {</div><div class="line">17: sum.fetch_add(item, std::memory_order_relaxed);</div><div class="line">18: }, 128);</div><div class="line">19:</div><div class="line">20: <a class="code" href="classtf_1_1Task.html">tf::Task</a> T2 = taskflow.<a class="code" href="classtf_1_1FlowBuilder.html#a4d52a7fe2814b264846a2085e931652c">emplace</a>([&] () { <span class="comment">// create a output task</span></div><div class="line">21: <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/basic_ostream.html">std::cout</a> << <span class="stringliteral">"sum is: "</span> << sum << <a class="codeRef" doxygen="/home/twhuang/PhD/Code/cpp-taskflow/doxygen/cppreference-doxygen-web.tag.xml:http://en.cppreference.com/w/" href="http://en.cppreference.com/w/cpp/io/manip/endl.html">std::endl</a>;</div><div class="line">22: }).name(<span class="stringliteral">"Print Sum"</span>);</div><div class="line">23:</div><div class="line">24: T1.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(S); <span class="comment">// modifier precedes parallel-for</span></div><div class="line">25: T.<a class="code" href="classtf_1_1Task.html#a8c78c453295a553c1c016e4062da8588">precede</a>(T2); <span class="comment">// parallel-for precedes the output task</span></div><div class="line">26:</div><div class="line">27: <a class="code" href="classtf_1_1Executor.html">tf::Executor</a>().<a class="code" href="classtf_1_1Executor.html#a93d3b5c6f5612c1b32033f2dcd27b2a5">run</a>(taskflow);</div><div class="line">28:</div><div class="line">29: <span class="keywordflow">return</span> 0;</div><div class="line">30: }</div></div><!-- fragment --><div class="image">
<img src="parallel_for_example2.png" alt="parallel_for_example2.png" width="100%"/>
</div>
<p>The output of this programs is:</p>
<div class="fragment"><div class="line">sum is: 1024</div></div><!-- fragment --><p>Debrief: </p><ul>
<li>Line 5 creates a taskflow object </li>
<li>Line 7 creates a vector of 1024 uninitialized integers </li>
<li>Line 8 creates an atomic integer variable </li>
<li>Line 10-14 creates a task that captures the vector to initialize all items to one </li>
<li>Line 16-18 sums up all items with each thread running on a partition of 128 items (total 1024/128=8 partitions) </li>
<li>Line 20-22 creates a task that outputs the summation value </li>
<li>Line 24-25 pipelines the parallel-for workload with the two tasks </li>
<li>Line 27 dispatches the graph to threads and blocks until the execution completes </li>
</ul>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.13 </li>
</ul>
</div>
</body>
</html>
You can’t perform that action at this time.
