std::experimental::parallel:: reduce
|
Определено в заголовочном файле
<experimental/numeric>
|
||
|
template
<
class
InputIt
>
typename
std::
iterator_traits
<
InputIt
>
::
value_type
reduce
(
|
(1) | (parallelism TS) |
|
template
<
class
ExecutionPolicy,
class
InputIterator
>
typename
std::
iterator_traits
<
InputIt
>
::
value_type
reduce
(
|
(2) | (parallelism TS) |
|
template
<
class
InputIt,
class
T
>
T reduce ( InputIt first, InputIt last, T init ) ; |
(3) | (parallelism TS) |
|
template
<
class
ExecutionPolicy,
class
InputIt,
class
T
>
T reduce ( ExecutionPolicy && policy, InputIt first, InputIt last, T init ) ; |
(4) | (parallelism TS) |
|
template
<
class
InputIt,
class
T,
class
BinaryOp
>
T reduce ( InputIt first, InputIt last, T init, BinaryOp binary_op ) ; |
(5) | (parallelism TS) |
|
template
<
class
ExecutionPolicy,
class
InputIt,
class
T,
class
BinaryOp
>
T reduce
(
ExecutionPolicy
&&
policy,
|
(6) | (parallelism TS) |
[
first
,
last
)
, возможно переставленный и агрегированный произвольным образом, вместе с начальным значением
init
с помощью операции
binary_op
.
Поведение недетерминировано, если binary_op не является ассоциативным или не коммутативно.
Поведение не определено, если
binary_op
изменяет любой элемент или делает недействительным любой итератор в диапазоне
[
first
,
last
)
.
Содержание |
Параметры
| first, last | - | диапазон элементов для применения алгоритма |
| init | - | начальное значение обобщённой суммы |
| policy | - | политика выполнения |
| binary_op | - | бинарный FunctionObject который будет применён в неопределённом порядке к результату разыменования входных итераторов, результатам других binary_op и init |
| Требования к типам | ||
-
InputIt
должен удовлетворять требованиям
LegacyInputIterator
.
|
||
Возвращаемое значение
Обобщенная сумма init и * first , * ( first + 1 ) , ... * ( 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
другими словами, элементы диапазона могут быть сгруппированы и переупорядочены в произвольном порядке.
Сложность
O(last - first) применений 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 выбрасывается.
Примечания
Если диапазон пуст, init возвращается без изменений.
-
Если
policyявляется экземпляромsequential_execution_policy, все операции выполняются в вызывающем потоке. -
Если
policyявляется экземпляромparallel_execution_policy, операции могут выполняться в неопределенном количестве потоков, недетерминированно упорядоченных друг относительно друга. -
Если
policyявляется экземпляромparallel_vector_execution_policy, выполнение может быть как распараллелено, так и векторизовано: границы тела функции не соблюдаются, а пользовательский код может перекрываться и комбинироваться произвольным образом (в частности, это означает, что предоставляемый пользователем Callable не должен захватывать мьютекс для доступа к разделяемому ресурсу).
Пример
reduce — это неупорядоченная версия std::accumulate :
#include <chrono> #include <experimental/execution_policy> #include <experimental/numeric> #include <iostream> #include <numeric> #include <vector> int main() { std::vector<double> v(10'000'007, 0.5); { auto t1 = std::chrono::high_resolution_clock::now(); double result = std::accumulate(v.begin(), v.end(), 0.0); auto t2 = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> ms = t2 - t1; std::cout << std::fixed << "std::accumulate result " << result << " took " << ms.count() << " ms\n"; } { auto t1 = std::chrono::high_resolution_clock::now(); double result = std::experimental::parallel::reduce( std::experimental::parallel::par, v.begin(), v.end()); auto t2 = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> ms = t2 - t1; std::cout << "parallel::reduce result " << result << " took " << ms.count() << " ms\n"; } }
Возможный вывод:
std::accumulate result 5000003.50000 took 12.7365 ms parallel::reduce result 5000003.50000 took 5.06423 ms
Смотрите также
|
суммирует или сворачивает диапазон элементов
(шаблон функции) |
|
|
применяет функцию к диапазону элементов, сохраняя результаты в целевом диапазоне
(шаблон функции) |
|
|
(parallelism TS)
|
применяет функтор, затем выполняет редукцию в произвольном порядке
(шаблон функции) |