forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParallelIterations.html
More file actions
332 lines (317 loc) · 38.4 KB
/
Copy pathParallelIterations.html
File metadata and controls
332 lines (317 loc) · 38.4 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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Taskflow Algorithms » Parallel Iterations | 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/x-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 Iterations
</h1>
<nav class="m-block m-default">
<h3>Contents</h3>
<ul>
<li><a href="#ParallelIterationsIncludeTheHeader">Include the Header</a></li>
<li><a href="#A1IndexBasedParallelFor">Create an Index-based Parallel-Iteration Task</a></li>
<li><a href="#ParallelForEachCaptureIndicesByReference">Capture Indices by Reference</a></li>
<li><a href="#A1IteratorBasedParallelFor">Create an Iterator-based Parallel-Iteration Task</a></li>
<li><a href="#ParallelForEachCaptureIteratorsByReference">Capture Iterators by Reference</a></li>
<li><a href="#ParallelIterationsConfigureAPartitioner">Configure a Partitioner</a></li>
</ul>
</nav>
<p>Taskflow provides template functions for constructing tasks to perform parallel iterations over ranges of items.</p><section id="ParallelIterationsIncludeTheHeader"><h2><a href="#ParallelIterationsIncludeTheHeader">Include the Header</a></h2><p>You need to include the header file, <code>taskflow/algorithm/for_each.hpp</code>, for using parallel-iteration algorithms.</p><pre class="m-code"><span class="cp">#include</span><span class="w"> </span><span class="cpf"><taskflow/algorithm/for_each.hpp></span></pre></section><section id="A1IndexBasedParallelFor"><h2><a href="#A1IndexBasedParallelFor">Create an Index-based Parallel-Iteration Task</a></h2><p>Index-based parallel-for performs parallel iterations over a range <code>[first, last)</code> with the given <code>step</code> size. The task created by <a href="classtf_1_1FlowBuilder.html#a3b132bd902331a11b04b4ad66cf8bf77" class="m-doc">tf::<wbr />Taskflow::<wbr />for_each_index(B first, E last, S step, C callable, P part)</a> represents parallel execution of the following loop:</p><pre class="m-code"><span class="c1">// positive step</span>
<span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">i</span><span class="o">=</span><span class="n">first</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o"><</span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">+=</span><span class="n">step</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">callable</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// negative step</span>
<span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">i</span><span class="o">=</span><span class="n">first</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">></span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">+=</span><span class="n">step</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">callable</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="p">}</span></pre><p>We support only integer-based range. The range can go positive or negative direction.</p><pre class="m-code"><span class="n">taskflow</span><span class="p">.</span><span class="n">for_each_index</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">});</span><span class="w"> </span><span class="c1">// 50 loops with a + step</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each_index</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">-2</span><span class="p">,</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">});</span><span class="w"> </span><span class="c1">// 50 loops with a - step</span></pre><p>Notice that either positive or negative direction is defined in terms of the range, <code>[first, last)</code>, where <code>end</code> is excluded. In the positive case, the 50 items are 0, 2, 4, 6, 8, ..., 96, 98. In the negative case, the 50 items are 100, 98, 96, 04, ... 4, 2. An example of the Taskflow graph for the positive case under 12 workers is depicted below:</p><div class="m-graph"><svg style="width: 85.400rem; height: 11.600rem;" viewBox="0.00 0.00 854.00 116.00">
<g transform="scale(1 1) rotate(0) translate(4 112)">
<title>Taskflow</title>
<g class="m-node m-flat">
<title>p0xce2720</title>
<ellipse cx="423" cy="-18" rx="88.01" ry="18"/>
<text text-anchor="middle" x="423" y="-14.12" font-family="Helvetica,sans-Serif" font-size="10.00">[0, 100) with the step size of 2</text>
</g>
<g class="m-node m-flat">
<title>p0x7f322c000b50</title>
<ellipse cx="27" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_0</text>
</g>
<g class="m-edge">
<title>p0x7f322c000b50->p0xce2720</title>
<path d="M47.53,-78.04C52.48,-75.75 57.84,-73.56 63,-72 151,-45.39 255.29,-31.9 328.91,-25.22"/>
<polygon points="328.83,-28.74 338.49,-24.38 328.22,-21.77 328.83,-28.74"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c000c58</title>
<ellipse cx="99" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_1</text>
</g>
<g class="m-edge">
<title>p0x7f322c000c58->p0xce2720</title>
<path d="M119.57,-78.17C124.52,-75.88 129.87,-73.65 135,-72 200.78,-50.81 277.91,-37.18 335.78,-29.06"/>
<polygon points="336.16,-32.54 345.59,-27.71 335.21,-25.6 336.16,-32.54"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c000d60</title>
<ellipse cx="171" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="171" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_2</text>
</g>
<g class="m-edge">
<title>p0x7f322c000d60->p0xce2720</title>
<path d="M192.02,-78.21C196.87,-75.97 202.05,-73.76 207,-72 253.27,-55.59 306.85,-42.4 349.08,-33.29"/>
<polygon points="349.58,-36.76 358.63,-31.26 348.12,-29.92 349.58,-36.76"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c000e68</title>
<ellipse cx="243" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="243" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_3</text>
</g>
<g class="m-edge">
<title>p0x7f322c000e68->p0xce2720</title>
<path d="M264.18,-78.62C269.01,-76.35 274.16,-74.03 279,-72 308.15,-59.78 341.21,-47.5 368.3,-37.85"/>
<polygon points="369.45,-41.15 377.7,-34.52 367.11,-34.56 369.45,-41.15"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c000f70</title>
<ellipse cx="315" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="315" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_4</text>
</g>
<g class="m-edge">
<title>p0x7f322c000f70->p0xce2720</title>
<path d="M333.81,-76.81C348.7,-67.16 369.91,-53.41 387.92,-41.74"/>
<polygon points="389.77,-44.71 396.26,-36.33 385.96,-38.84 389.77,-44.71"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c001078</title>
<ellipse cx="387" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="387" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_5</text>
</g>
<g class="m-edge">
<title>p0x7f322c001078->p0xce2720</title>
<path d="M395.35,-72.76C399.41,-64.87 404.4,-55.16 409.02,-46.18"/>
<polygon points="412.04,-47.96 413.5,-37.47 405.82,-44.76 412.04,-47.96"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c001180</title>
<ellipse cx="459" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="459" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_6</text>
</g>
<g class="m-edge">
<title>p0x7f322c001180->p0xce2720</title>
<path d="M450.65,-72.76C446.59,-64.87 441.6,-55.16 436.98,-46.18"/>
<polygon points="440.18,-44.76 432.5,-37.47 433.96,-47.96 440.18,-44.76"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c001288</title>
<ellipse cx="531" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="531" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_7</text>
</g>
<g class="m-edge">
<title>p0x7f322c001288->p0xce2720</title>
<path d="M512.19,-76.81C497.3,-67.16 476.09,-53.41 458.08,-41.74"/>
<polygon points="460.04,-38.84 449.74,-36.33 456.23,-44.71 460.04,-38.84"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c001390</title>
<ellipse cx="603" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="603" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_8</text>
</g>
<g class="m-edge">
<title>p0x7f322c001390->p0xce2720</title>
<path d="M581.82,-78.62C576.99,-76.35 571.84,-74.03 567,-72 537.85,-59.78 504.79,-47.5 477.7,-37.85"/>
<polygon points="478.89,-34.56 468.3,-34.52 476.55,-41.15 478.89,-34.56"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c001498</title>
<ellipse cx="675" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="675" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_9</text>
</g>
<g class="m-edge">
<title>p0x7f322c001498->p0xce2720</title>
<path d="M653.98,-78.21C649.13,-75.97 643.95,-73.76 639,-72 592.73,-55.59 539.15,-42.4 496.92,-33.29"/>
<polygon points="497.88,-29.92 487.37,-31.26 496.42,-36.76 497.88,-29.92"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c0015a0</title>
<ellipse cx="747" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="747" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_10</text>
</g>
<g class="m-edge">
<title>p0x7f322c0015a0->p0xce2720</title>
<path d="M726.43,-78.17C721.48,-75.88 716.13,-73.65 711,-72 645.22,-50.81 568.09,-37.18 510.22,-29.06"/>
<polygon points="510.79,-25.6 500.41,-27.71 509.84,-32.54 510.79,-25.6"/>
</g>
<g class="m-node m-flat">
<title>p0x7f322c0016a8</title>
<ellipse cx="819" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="819" y="-86.12" font-family="Helvetica,sans-Serif" font-size="10.00">pfg_11</text>
</g>
<g class="m-edge">
<title>p0x7f322c0016a8->p0xce2720</title>
<path d="M798.47,-78.04C793.52,-75.75 788.16,-73.56 783,-72 695,-45.39 590.71,-31.9 517.09,-25.22"/>
<polygon points="517.78,-21.77 507.51,-24.38 517.17,-28.74 517.78,-21.77"/>
</g>
</g>
</svg>
</div><p>Instead of explicitly specifying the index range and the callable for each index invocation, the overload <a href="classtf_1_1FlowBuilder.html#a2582a216d54dacca2b7022ea7e89452a" class="m-doc">tf::<wbr />Taskflow::<wbr />for_each_by_index(R range, C callable, P part)</a> provides you with a more flexible way to iterate over subranges of indices. This overload uses <a href="classtf_1_1IndexRange.html" class="m-doc">tf::<wbr />IndexRange</a> to partition the range into subranges, allowing finer control over how each subrange is processed. For instance, the code below does the same thing using two different approaches:</p><pre class="m-code"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">data1</span><span class="p">(</span><span class="mi">100</span><span class="p">),</span><span class="w"> </span><span class="n">data2</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
<span class="c1">// Approach 1: initialize data1 using explicit index range</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each_index</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">){</span><span class="w"> </span><span class="n">data1</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="c1">// Approach 2: initialize data2 using tf::IndexRange</span>
<span class="n">tf</span><span class="o">::</span><span class="n">IndexRange</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each_by_index</span><span class="p">(</span><span class="n">range</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">](</span><span class="n">tf</span><span class="o">::</span><span class="n">IndexRange</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">subrange</span><span class="p">){</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="o">=</span><span class="n">subrange</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span><span class="w"> </span><span class="n">i</span><span class="o"><</span><span class="n">subrange</span><span class="p">.</span><span class="n">end</span><span class="p">();</span><span class="w"> </span><span class="n">i</span><span class="o">+=</span><span class="n">subrange</span><span class="p">.</span><span class="n">step_size</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">data2</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">});</span></pre><p>Both approaches produce the same result, but the second approach offers more flexibility in terms of how each partitioned subrange is iterated. This is particularly useful for applications that benefit from SIMD optimizations or other range-based processing strategies.</p></section><section id="ParallelForEachCaptureIndicesByReference"><h2><a href="#ParallelForEachCaptureIndicesByReference">Capture Indices by Reference</a></h2><p>You can pass indices by reference using <a href="https://en.cppreference.com/w/cpp/utility/functional/ref">std::<wbr />ref</a> to marshal parameter update between dependent tasks. This is especially useful when the range indices are unknown at the time of creating a for-each-index task, but is initialized from another task.</p><pre class="m-code"><span class="kt">int</span><span class="o">*</span><span class="w"> </span><span class="n">vec</span><span class="p">;</span>
<span class="kt">int</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">init</span><span class="w"> </span><span class="o">=</span><span class="w"> </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="p">](){</span>
<span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1000</span><span class="p">;</span>
<span class="w"> </span><span class="n">vec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="p">[</span><span class="mi">1000</span><span class="p">];</span><span class="w"> </span>
<span class="p">});</span>
<span class="k">auto</span><span class="w"> </span><span class="n">pf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">for_each_index</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ref</span><span class="p">(</span><span class="n">first</span><span class="p">),</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">ref</span><span class="p">(</span><span class="n">last</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span>
<span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">]</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel iteration on index "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">vec</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">);</span>
<span class="c1">// wrong! must use std::ref, or first and last are captured by copy</span>
<span class="c1">// auto pf = taskflow.for_each_index(first, last, 1, [&](int i) {</span>
<span class="c1">// std::cout << "parallel iteration on index " << vec[i] << '\n';</span>
<span class="c1">// });</span>
<span class="n">init</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pf</span><span class="p">);</span></pre><p>When <code>init</code> finishes, the parallel-for task <code>pf</code> will see <code>first</code> as 0 and <code>last</code> as 1000 and performs parallel iterations over the 1000 items.</p></section><section id="A1IteratorBasedParallelFor"><h2><a href="#A1IteratorBasedParallelFor">Create an Iterator-based Parallel-Iteration Task</a></h2><p>Iterator-based parallel-for performs parallel iterations over a range specified by two <a href="https://en.cppreference.com/w/cpp/iterator/iterator">STL-styled iterators</a>, <code>first</code> and <code>last</code>. The task created by <a href="classtf_1_1FlowBuilder.html#aae3edfa278baa75b08414e083c14c836" class="m-doc">tf::<wbr />Taskflow::<wbr />for_each(B first, E last, C callable, P part)</a> represents a parallel execution of the following loop:</p><pre class="m-code"><span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">i</span><span class="o">=</span><span class="n">first</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o"><</span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">callable</span><span class="p">(</span><span class="o">*</span><span class="n">i</span><span class="p">);</span>
<span class="p">}</span></pre><p>tf::Taskflow::for_each(B first, E last, C callable, P&& part) simultaneously applies the callable to the object obtained by dereferencing every iterator in the range <code>[first, last)</code>. It is user's responsibility for ensuring the range is valid within the execution of the parallel-for task. Iterators must have the post-increment operator ++ defined.</p><pre class="m-code"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">vec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="p">};</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span><span class="n">vec</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">){</span><span class="w"> </span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel for on item "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span><span class="w"> </span>
<span class="p">});</span>
<span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">></span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">"hi"</span><span class="p">,</span><span class="w"> </span><span class="s">"from"</span><span class="p">,</span><span class="w"> </span><span class="s">"t"</span><span class="p">,</span><span class="w"> </span><span class="s">"a"</span><span class="p">,</span><span class="w"> </span><span class="s">"s"</span><span class="p">,</span><span class="w"> </span><span class="s">"k"</span><span class="p">,</span><span class="w"> </span><span class="s">"f"</span><span class="p">,</span><span class="w"> </span><span class="s">"low"</span><span class="p">};</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span><span class="n">list</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">list</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&</span><span class="w"> </span><span class="n">str</span><span class="p">){</span><span class="w"> </span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel for on item "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">str</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span><span class="w"> </span>
<span class="p">});</span></pre></section><section id="ParallelForEachCaptureIteratorsByReference"><h2><a href="#ParallelForEachCaptureIteratorsByReference">Capture Iterators by Reference</a></h2><p>Similar to <a href="classtf_1_1FlowBuilder.html#a3b132bd902331a11b04b4ad66cf8bf77" class="m-doc">tf::<wbr />Taskflow::<wbr />for_each_index</a>, iterators of <a href="classtf_1_1FlowBuilder.html#aae3edfa278baa75b08414e083c14c836" class="m-doc">tf::<wbr />Taskflow::<wbr />for_each</a> are templated to allow capturing range parameters by reference, such that one task can set up the range before another task performs the parallel-for algorithm. For example:</p><pre class="m-code"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">vec</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">>::</span><span class="n">iterator</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">;;</span>
<span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">init</span><span class="w"> </span><span class="o">=</span><span class="w"> </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="p">](){</span>
<span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span>
<span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">end</span><span class="p">();</span>
<span class="p">});</span>
<span class="n">tf</span><span class="o">::</span><span class="n">Task</span><span class="w"> </span><span class="n">pf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">taskflow</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ref</span><span class="p">(</span><span class="n">first</span><span class="p">),</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">ref</span><span class="p">(</span><span class="n">last</span><span class="p">),</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel iteration on item "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
<span class="p">});</span>
<span class="c1">// wrong! must use std::ref, or first and last are captured by copy</span>
<span class="c1">// tf::Task pf = taskflow.for_each(first, last, [&](int i) {</span>
<span class="c1">// std::cout << "parallel iteration on item " << i << '\n';</span>
<span class="c1">// });</span>
<span class="n">init</span><span class="p">.</span><span class="n">precede</span><span class="p">(</span><span class="n">pf</span><span class="p">);</span></pre><p>When <code>init</code> finishes, the parallel-for task <code>pf</code> will see <code>first</code> pointing to the beginning of <code>vec</code> and <code>last</code> pointing to the end of <code>vec</code> and performs parallel iterations over the 1000 items. The two tasks form an end-to-end task graph where the parameters of parallel-for are computed on the fly.</p></section><section id="ParallelIterationsConfigureAPartitioner"><h2><a href="#ParallelIterationsConfigureAPartitioner">Configure a Partitioner</a></h2><p>You can configure a partitioner for parallel-iteration tasks to run with different scheduling methods, such as guided partitioning, dynamic partitioning, and static partitioning. The following example creates two parallel-iteration tasks using two different partitioners, one with the static partitioning algorithm and another one with the guided partitioning algorithm:</p><pre class="m-code"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">vec</span><span class="p">(</span><span class="mi">1024</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="c1">// create two partitioners with a chunk size of 10</span>
<span class="n">tf</span><span class="o">::</span><span class="n">StaticPartitioner</span><span class="w"> </span><span class="nf">static_partitioner</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
<span class="n">tf</span><span class="o">::</span><span class="n">GuidedPartitioner</span><span class="w"> </span><span class="nf">guided_partitioner</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
<span class="c1">// create a parallel-iteration task with static partitioner</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span>
<span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel iteration on item "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="n">static_partitioner</span>
<span class="p">);</span>
<span class="c1">// create a parallel-iteration task with guided partitioner</span>
<span class="n">taskflow</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span>
<span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">vec</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="p">[</span><span class="o">&</span><span class="p">](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"parallel iteration on item "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="sc">'\n'</span><span class="p">;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="n">guided_partitioner</span>
<span class="p">);</span></pre><aside class="m-note m-warning"><h4>Attention</h4><p>By default, parallel-iteration tasks use <a href="namespacetf.html#ace2c5adcd5039483eebb6dbdbb6f33e3" class="m-doc">tf::<wbr />DefaultPartitioner</a> if no partitioner is specified.</p></aside></section>
</div>
</div>
</div>
</article></main>
<div class="m-doc-search" id="search">
<a href="#!" onclick="return hideSearch()"></a>
<div class="m-container">
<div class="m-row">
<div class="m-col-m-8 m-push-m-2">
<div class="m-doc-search-header m-text m-small">
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
<div id="search-symbolcount">…</div>
</div>
<div class="m-doc-search-content">
<form>
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
</form>
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
<div id="search-help" class="m-text m-dim m-text-center">
<p class="m-noindent">Search for symbols, directories, files, pages or
modules. You can omit any prefix from the symbol or file path; adding a
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
directory.</p>
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
/ <span class="m-label m-dim">↑</span> to navigate through the list,
<span class="m-label m-dim">Enter</span> to go.
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
copy a link to the result using <span class="m-label m-dim">⌘</span>
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
</div>
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
<ul id="search-results"></ul>
</div>
</div>
</div>
</div>
</div>
<script src="search-v2.js"></script>
<script src="searchdata-v2.js" async="async"></script>
<footer><nav>
<div class="m-container">
<div class="m-row">
<div class="m-col-l-10 m-push-l-1">
<p>Taskflow handbook is part of the <a href="https://taskflow.github.io">Taskflow project</a>, copyright © <a href="https://tsung-wei-huang.github.io/">Dr. Tsung-Wei Huang</a>, 2018–2025.<br />Generated by <a href="https://doxygen.org/">Doxygen</a> 1.12.0 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div>
</div>
</div>
</nav></footer>
</body>
</html>