179 lines
5.6 KiB
Text
179 lines
5.6 KiB
Text
|
namespace tf {
|
||
|
|
||
|
/** @page ParallelScan Parallel Scan
|
||
|
|
||
|
%Taskflow provide template methods that construct tasks
|
||
|
to perform parallel scan over a range of items.
|
||
|
|
||
|
@tableofcontents
|
||
|
|
||
|
@section ParallelScanInclude Include the Header
|
||
|
|
||
|
You need to include the header file, <tt>taskflow/algorithm/scan.hpp</tt>,
|
||
|
for creating a parallel-scan task.
|
||
|
|
||
|
@code{.cpp}
|
||
|
#include <taskflow/algorithm/scan.hpp>
|
||
|
@endcode
|
||
|
|
||
|
@section WhatIsAScanOperation What is a Scan Operation?
|
||
|
|
||
|
A parallel scan task
|
||
|
performs the cumulative sum, also known as <i>prefix sum</i> or @em scan,
|
||
|
of the input range and writes the result to the output range.
|
||
|
Each element of the output range contains the
|
||
|
running total of all earlier elements using the given binary operator
|
||
|
for summation.
|
||
|
|
||
|
@image html images/scan.png
|
||
|
|
||
|
@section CreateAParallelInclusiveScanTask Create a Parallel Inclusive Scan Task
|
||
|
|
||
|
tf::Taskflow::inclusive_scan(B first, E last, D d_first, BOP bop)
|
||
|
generates an @em inclusive scan, meaning that the N-th element
|
||
|
of the output range is the sum of the first N input elements,
|
||
|
so the N-th input element is included.
|
||
|
For example, the code below performs an inclusive scan over five elements:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size())
|
||
|
taskflow.inclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), std::plus<int>{}
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {1, 3, 6, 10, 15}
|
||
|
@endcode
|
||
|
|
||
|
The output range may be the same as the input range, in which
|
||
|
the scan operation is @em in-place with results written to
|
||
|
the input range.
|
||
|
For example, the code below performs an in-place inclusive
|
||
|
scan over five elements:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
taskflow.inclusive_scan(
|
||
|
input.begin(), input.end(), input.begin(), std::plus<int>{}
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// input is {1, 3, 6, 10, 15}
|
||
|
@endcode
|
||
|
|
||
|
|
||
|
Similar to tf::Taskflow::inclusive_scan(B first, E last, D d_first, BOP bop),
|
||
|
tf::Taskflow::inclusive_scan(B first, E last, D d_first, BOP bop, T init)
|
||
|
performs an inclusive scan but with an additional initial value @c init.
|
||
|
For example, the code below performs an inclusive scan
|
||
|
over five elements plus an initial value:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size());
|
||
|
// performs inclusive scan with an initial value
|
||
|
taskflow.inclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), std::plus<int>{}, -1
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {0, 2, 5, 9, 14}
|
||
|
@endcode
|
||
|
|
||
|
@section CreateAParallelTransformInclusiveScanTask Create a Parallel Transform-Inclusive Scan Task
|
||
|
|
||
|
You can transform elements in the input range before running inclusive scan
|
||
|
using tf::Taskflow::transform_inclusive_scan(B first, E last, D d_first, BOP bop, UOP uop)
|
||
|
and tf::Taskflow::transform_inclusive_scan(B first, E last, D d_first, BOP bop, UOP uop, T init).
|
||
|
For example, the code below performs an inclusive scan over five
|
||
|
transformed elements:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size());
|
||
|
taskflow.transform_inclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), std::plus<int>{},
|
||
|
[] (int item) { return -item; }
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {-1, -3, -6, -10, -15}
|
||
|
@endcode
|
||
|
|
||
|
You can also associate the transform-inclusive scan with an initial value
|
||
|
using tf::Taskflow::transform_inclusive_scan(B first, E last, D d_first, BOP bop, UOP uop, T init).
|
||
|
Only elements in the input range will be transformed using @c uop,
|
||
|
i.e., the initial value @c init does not participate in @c uop.
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size());
|
||
|
taskflow.transform_inclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), std::plus<int>{},
|
||
|
[] (int item) { return -item; },
|
||
|
-1
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {-2, -4, -7, -11, -16}
|
||
|
@endcode
|
||
|
|
||
|
@section CreateAParallelExclusiveScanTask Create a Parallel Exclusive Scan Task
|
||
|
|
||
|
tf::Taskflow::exclusive_scan(B first, E last, D d_first, T init, BOP bop)
|
||
|
generates an @em exclusive scan with the given initial value.
|
||
|
The N-th element of the output range is the sum of the first N-1 input elements,
|
||
|
so the N-th input element is included.
|
||
|
For example, the code below performs an exclusive scan over five elements
|
||
|
with an initial value -1:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size())
|
||
|
taskflow.exclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), -1, std::plus<int>{}
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {-1, 0, 2, 5, 9}
|
||
|
@endcode
|
||
|
|
||
|
The output range may be the same as the input range, in which
|
||
|
the scan operation is @em in-place with results written to
|
||
|
the input range.
|
||
|
For example, the code below performs an in-place exclusive
|
||
|
scan over five elements with an initial -1:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size());
|
||
|
taskflow.exclusive_scan(
|
||
|
input.begin(), input.end(), output.begin(), -1, std::plus<int>{}
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {-1, 0, 2, 5, 9}
|
||
|
@endcode
|
||
|
|
||
|
@section CreateAParallelTransformExclusiveScanTask Create a Parallel Transform-Exclusive Scan Task
|
||
|
|
||
|
You can transform elements in the input range before running exclusive scan using
|
||
|
tf::Taskflow::transform_exclusive_scan(B first, E last, D d_first, T init, BOP bop, UOP uop).
|
||
|
For example, the code below performs an exclusive scan over five
|
||
|
transformed elements:
|
||
|
|
||
|
@code{.cpp}
|
||
|
std::vector<int> input = {1, 2, 3, 4, 5};
|
||
|
std::vector<int> output(input.size());
|
||
|
taskflow.transform_exclusive_scan(
|
||
|
input.begin(), input.end(), input.begin(), -1, std::plus<int>{},
|
||
|
[](int item) { return -item; }
|
||
|
);
|
||
|
executor.run(taskflow).wait();
|
||
|
// output is {-1, -2, -4, -7, -11}
|
||
|
@endcode
|
||
|
|
||
|
*/
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|