std::experimental::parallel:: transform_reduce
|
Определено в заголовочном файле
<experimental/numeric>
|
||
|
template
<
class
InputIt,
class
UnaryOp,
class
T,
class
BinaryOp
>
T transform_reduce
(
InputIt first, InputIt last,
|
(1) | (parallelism TS) |
|
template
<
class
ExecutionPolicy,
class
InputIt,
class
UnaryOp,
class
T,
class
BinaryOp
>
|
(2) | (parallelism TS) |
Применяет
unary_op
к каждому элементу в диапазоне
[
first
,
last
)
и редуцирует результаты (возможно переставленные и агрегированные неопределённым образом) вместе с начальным значением
init
с помощью
binary_op
.
Поведение недетерминировано, если binary_op не является ассоциативным или не коммутативным.
Поведение не определено, если
unary_op
или
binary_op
изменяет любой элемент или делает недействительным любой итератор в диапазоне
[
first
,
last
)
.
Содержание |
Параметры
| first, last | - | диапазон элементов для применения алгоритма |
| init | - | начальное значение обобщённой суммы |
| policy | - | политика выполнения |
| unary_op | - | унарный FunctionObject , который будет применён к каждому элементу входного диапазона. Тип возвращаемого значения должен быть допустимым для ввода в binary_op |
| binary_op | - | бинарный FunctionObject , который будет применён в неопределённом порядке к результатам unary_op , результатам других binary_op и init |
| Требования к типам | ||
-
InputIt
должен удовлетворять требованиям
LegacyInputIterator
.
|
||
Возвращаемое значение
Обобщённая сумма init и unary_op ( * first ) , unary_op ( * ( first + 1 ) ) , ... unary_op ( * ( last - 1 ) ) через binary_op , где обобщённая сумма GSUM(op, a 1 , ..., a N ) определяется следующим образом:
- если N = 1 , a 1 ,
- если N > 1 , op(GSUM(op, b 1 , ..., b K ), GSUM(op, b M , ..., b N )) где
-
- b 1 , ..., b N может быть любой перестановкой a1, ..., aN и
- 1 < K + 1 = M ≤ N
другими словами, результаты unary_op могут быть сгруппированы и упорядочены произвольным образом.
Сложность
O(last - first) применений каждого из unary_op и binary_op .
Исключения
- Если выполнение функции, вызванной как часть алгоритма, вызывает исключение,
-
-
если
policyявляетсяparallel_vector_execution_policy, std::terminate вызывается. -
если
policyявляетсяsequential_execution_policyилиparallel_execution_policy, алгоритм завершается с exception_list , содержащей все неперехваченные исключения. Если было только одно неперехваченное исключение, алгоритм может повторно выбросить его без обёртки вexception_list. Не определено, какой объём работы алгоритм выполнит перед возвратом после обнаружения первого исключения. -
если
policyимеет другой тип, поведение определяется реализацией.
-
если
-
Если алгоритму не удается выделить память (либо для себя, либо для создания
exception_listпри обработке пользовательского исключения), std::bad_alloc выбрасывается.
Примечания
unary_op не применяется к init .
Если диапазон пуст, init возвращается без изменений.
-
Если
policyявляется экземпляромsequential_execution_policy, все операции выполняются в вызывающем потоке. -
Если
policyявляется экземпляромparallel_execution_policy, операции могут выполняться в неопределенном количестве потоков, недетерминированно упорядоченных друг относительно друга. -
Если
policyявляется экземпляромparallel_vector_execution_policy, выполнение может быть как распараллелено, так и векторизовано: границы тела функции не соблюдаются, а пользовательский код может перекрываться и комбинироваться произвольным образом (в частности, это означает, что предоставляемый пользователем Callable не должен захватывать мьютекс для доступа к разделяемому ресурсу).
Пример
transform_reduce может быть использована для распараллеливания std::inner_product :
#include <boost/iterator/zip_iterator.hpp> #include <boost/tuple.hpp> #include <experimental/execution_policy> #include <experimental/numeric> #include <functional> #include <iostream> #include <iterator> #include <vector> int main() { std::vector<double> xvalues(10007, 1.0), yvalues(10007, 1.0); double result = std::experimental::parallel::transform_reduce( std::experimental::parallel::par, boost::iterators::make_zip_iterator( boost::make_tuple(std::begin(xvalues), std::begin(yvalues))), boost::iterators::make_zip_iterator( boost::make_tuple(std::end(xvalues), std::end(yvalues))), [](auto r) { return boost::get<0>(r) * boost::get<1>(r); } 0.0, std::plus<>() ); std::cout << result << '\n'; }
Вывод:
10007
Смотрите также
|
суммирует или сворачивает диапазон элементов
(function template) |
|
|
применяет функцию к диапазону элементов, сохраняя результаты в целевом диапазоне
(function template) |
|
|
(parallelism TS)
|
аналогично
std::accumulate
, но без сохранения порядка
(function template) |