Namespaces
Variants

std::experimental::parallel:: reduce

From cppreference.net
Определено в заголовочном файле <experimental/numeric>
template < class InputIt >

typename std:: iterator_traits < InputIt > :: value_type reduce (

InputIt first, InputIt last ) ;
(1) (parallelism TS)
template < class ExecutionPolicy, class InputIterator >

typename std:: iterator_traits < InputIt > :: value_type reduce (

ExecutionPolicy && policy, InputIt first, InputIt last ) ;
(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,

InputIt first, InputIt last, T init, BinaryOp binary_op ) ;
(6) (parallelism TS)
1) То же, что reduce ( first, last, typename std:: iterator_traits < InputIt > :: value_type { } ) .
3) То же, что reduce ( first, last, init, std:: plus <> ( ) ) .
5) Сокращает диапазон [ first , last ) , возможно переставленный и агрегированный произвольным образом, вместе с начальным значением init с помощью операции binary_op .
2,4,6) То же, что и (1,3,5) , но выполняется в соответствии с policy .

Поведение недетерминировано, если 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)
применяет функтор, затем выполняет редукцию в произвольном порядке
(шаблон функции)