forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParallelTransforms.xml
More file actions
63 lines (63 loc) · 11.6 KB
/
ParallelTransforms.xml
File metadata and controls
63 lines (63 loc) · 11.6 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
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.14">
<compounddef id="ParallelTransforms" kind="page">
<compoundname>ParallelTransforms</compoundname>
<title>Parallel Transforms</title>
<tableofcontents/>
<briefdescription>
</briefdescription>
<detaileddescription>
<para>Taskflow provides template functions for constructing tasks to perform parallel transforms over ranges of items.</para><sect1 id="ParallelTransforms_1ParallelTransformsInclude">
<title>Include the Header</title>
<para>You need to include the header file, <computeroutput>taskflow/algorithm/transform.hpp</computeroutput>, for creating a parallel-transform task.</para><para><programlisting filename=".cpp"><codeline><highlight class="preprocessor">#include<sp/><taskflow/algorithm/transform.hpp></highlight></codeline>
</programlisting></para></sect1>
<sect1 id="ParallelTransforms_1ParallelTransformsOverARange">
<title>Create a Unary Parallel-Transform Task</title>
<para>Parallel-transform transforms a range of items, possibly with a different type for the transformed data, and stores the result in another range. The task created by <ref refid="classtf_1_1FlowBuilder_1abd813bd7afcbd8e6f56dc67883917d1a" kindref="member">tf::Taskflow::transform(B first1, E last1, O d_first, C c)</ref> is equivalent to a parallel execution of the following loop:</para><para><programlisting filename=".cpp"><codeline><highlight class="keywordflow">while</highlight><highlight class="normal"><sp/>(first1<sp/>!=<sp/>last1)<sp/>{</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>*d_first++<sp/>=<sp/>c(*first1++);</highlight></codeline>
<codeline><highlight class="normal">}</highlight></codeline>
</programlisting></para><para>By default, <ref refid="classtf_1_1FlowBuilder_1abd813bd7afcbd8e6f56dc67883917d1a" kindref="member">tf::Taskflow::transform(B first1, E last1, O d_first, C c)</ref> creates a task to spawn a subflow (see <ref refid="DynamicTasking" kindref="compound">Dynamic Tasking</ref>) that simultaneously applies the callable <computeroutput>c</computeroutput> to the object obtained by dereferencing every iterator in the range <computeroutput>[first1, last1)</computeroutput> and stores the result in another range beginning at <computeroutput>d_first</computeroutput>. It is user's responsibility for ensuring the range is valid within the execution of the parallel-transform task. <ref refid="classtf_1_1Taskflow" kindref="compound">Taskflow</ref>'s parallel-transform tasks work on all iterable STL containers.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>src<sp/>=<sp/>{1,<sp/>2,<sp/>3,<sp/>4,<sp/>5};</highlight></codeline>
<codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>tgt(src.size());</highlight></codeline>
<codeline><highlight class="normal">taskflow.<ref refid="classtf_1_1FlowBuilder_1abd813bd7afcbd8e6f56dc67883917d1a" kindref="member">transform</ref>(src.begin(),<sp/>src.end(),<sp/>[](</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i){<sp/></highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/><ref refid="cpp/io/basic_ostream" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::cout</ref><sp/><<<sp/></highlight><highlight class="stringliteral">"transforming<sp/>item<sp/>"</highlight><highlight class="normal"><sp/><<<sp/>i<sp/><<<sp/></highlight><highlight class="stringliteral">"<sp/>to<sp/>"</highlight><highlight class="normal"><sp/><<<sp/>i<sp/>+<sp/>1<sp/><<<sp/></highlight><highlight class="charliteral">'\n'</highlight><highlight class="normal">;</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">return</highlight><highlight class="normal"><sp/>i<sp/>+<sp/>1;</highlight></codeline>
<codeline><highlight class="normal">});</highlight></codeline>
</programlisting></para><para>You can enable stateful iterators by creating a reference wrapper and pass the wrapped iterator to the argument of <ref refid="classtf_1_1FlowBuilder_1abd813bd7afcbd8e6f56dc67883917d1a" kindref="member">tf::Taskflow::transform</ref>. This is especially useful when the range is not known at the time of creating a parallel-transform task, but through another task.</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>src,<sp/>tgt;</highlight></codeline>
<codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int>::iterator</ref><sp/>first,<sp/>last,<sp/>d_first;</highlight></codeline>
<codeline><highlight class="normal"></highlight></codeline>
<codeline><highlight class="normal"><ref refid="classtf_1_1Task" kindref="compound">tf::Task</ref><sp/>init<sp/>=<sp/>taskflow.<ref refid="classtf_1_1FlowBuilder_1a60d7a666cab71ecfa3010b2efb0d6b57" kindref="member">emplace</ref>([&](){</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>src.resize(1000);</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>tgt.resize(1000);</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>first<sp/><sp/><sp/>=<sp/>src.begin();</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>last<sp/><sp/><sp/><sp/>=<sp/>src.end();</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>d_first<sp/>=<sp/>tgt.begin();</highlight></codeline>
<codeline><highlight class="normal">});</highlight></codeline>
<codeline><highlight class="normal"></highlight></codeline>
<codeline><highlight class="normal"><ref refid="classtf_1_1Task" kindref="compound">tf::Task</ref><sp/><ref refid="cpp/algorithm/transform" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">transform</ref><sp/>=<sp/>taskflow.<ref refid="classtf_1_1FlowBuilder_1ab405d7b10040530d8b04c11767b4960d" kindref="member">for_each</ref>(</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>std::ref(first),<sp/>std::ref(last),<sp/>std::ref(d_first),<sp/></highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>[&](</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i)<sp/>{</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/><ref refid="cpp/io/basic_ostream" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::cout</ref><sp/><<<sp/></highlight><highlight class="stringliteral">"transforming<sp/>item<sp/>"</highlight><highlight class="normal"><sp/><<<sp/>i<sp/><<<sp/></highlight><highlight class="stringliteral">"<sp/>to<sp/>"</highlight><highlight class="normal"><sp/><<<sp/>i<sp/>+<sp/>1<sp/><<<sp/></highlight><highlight class="charliteral">'\n'</highlight><highlight class="normal">;</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">return</highlight><highlight class="normal"><sp/>i+1;</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline>
<codeline><highlight class="normal">);</highlight></codeline>
<codeline><highlight class="normal"></highlight></codeline>
<codeline><highlight class="normal">init.<ref refid="classtf_1_1Task_1a8c78c453295a553c1c016e4062da8588" kindref="member">precede</ref>(transform);</highlight></codeline>
</programlisting></para><para>When <computeroutput>init</computeroutput> finishes, the parallel-transform task <computeroutput>transform</computeroutput> will see <computeroutput>first</computeroutput> pointing to the beginning of <computeroutput>src</computeroutput> and <computeroutput>last</computeroutput> pointing to the end of <computeroutput>src</computeroutput>. Then, it simultaneously transforms these 1000 items by adding one to each element and stores the result in another range starting at <computeroutput>d_first</computeroutput>.</para></sect1>
<sect1 id="ParallelTransforms_1ParallelBinaryTransformsOverARange">
<title>Create a Binary Parallel-Transform Task</title>
<para>You can use the overload, <ref refid="classtf_1_1FlowBuilder_1aa0b3271b34317710a1e32053a9abc3cf" kindref="member">tf::Taskflow::transform(B1 first1, E1 last1, B2 first2, O d_first, C c)</ref>, to perform parallel transforms on two source ranges pointed by <computeroutput>first1</computeroutput> and <computeroutput>first2</computeroutput> using the binary operator <computeroutput>c</computeroutput> and store the result in another range pointed by <computeroutput>d_first</computeroutput>. This method is equivalent to the parallel execution of the following loop:</para><para><programlisting filename=".cpp"><codeline><highlight class="keywordflow">while</highlight><highlight class="normal"><sp/>(first1<sp/>!=<sp/>last1)<sp/>{</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>*d_first++<sp/>=<sp/>c(*first1++,<sp/>*first2++);</highlight></codeline>
<codeline><highlight class="normal">}</highlight></codeline>
</programlisting></para><para>The following example creates a parallel-transform task that adds two ranges of elements one by one and stores the result in a target range:</para><para><programlisting filename=".cpp"><codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>src1<sp/>=<sp/>{1,<sp/>2,<sp/>3,<sp/>4,<sp/>5};</highlight></codeline>
<codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>src2<sp/>=<sp/>{5,<sp/>4,<sp/>3,<sp/>2,<sp/>1};</highlight></codeline>
<codeline><highlight class="normal"><ref refid="cpp/container/vector" kindref="compound" external="/home/twhuang/Code/taskflow/doxygen/cppreference-doxygen-web.tag.xml">std::vector<int></ref><sp/>tgt(src.size());</highlight></codeline>
<codeline><highlight class="normal">taskflow.<ref refid="classtf_1_1FlowBuilder_1abd813bd7afcbd8e6f56dc67883917d1a" kindref="member">transform</ref>(</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>src1.begin(),<sp/>src1.end(),<sp/>src2.begin(),<sp/>tgt.begin(),<sp/></highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>[](</highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>i,<sp/></highlight><highlight class="keywordtype">int</highlight><highlight class="normal"><sp/>j){<sp/></highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">return</highlight><highlight class="normal"><sp/>i<sp/>+<sp/>j;</highlight></codeline>
<codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline>
<codeline><highlight class="normal">);</highlight></codeline>
</programlisting> </para></sect1>
</detaileddescription>
</compounddef>
</doxygen>