Namespaces
Variants

std::reduce

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z. B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeänderungsoperationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum-/Maximumoperationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
 
Definiert im Header <numeric>
template< class InputIt >
typename std::iterator_traits<InputIt>::value_type
    reduce( InputIt first, InputIt last );
(1) (seit C++17)
(constexpr seit C++20)
template< class ExecutionPolicy, class ForwardIt >
typename std::iterator_traits<ForwardIt>::value_type
    reduce( ExecutionPolicy&& policy,
            ForwardIt first, ForwardIt last );
(2) (seit C++17)
template< class InputIt, class T >
T reduce( InputIt first, InputIt last, T init );
(3) (seit C++17)
(constexpr seit C++20)
template< class ExecutionPolicy, class ForwardIt, class T >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init );
(4) (seit C++17)
template< class InputIt, class T, class BinaryOp >
T reduce( InputIt first, InputIt last, T init, BinaryOp op );
(5) (seit C++17)
(constexpr seit C++20)
template< class ExecutionPolicy,
          class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
          ForwardIt first, ForwardIt last, T init, BinaryOp op );
(6) (seit C++17)
1) Äquivalent zu reduce(first, last, typename std::iterator_traits<InputIt>::value_type{}).
3) Äquivalent zu reduce(first, last, init, std::plus<>()).
5) Reduziert den Bereich [first, last), möglicherweise in nicht spezifizierter Weise permutiert und aggregiert, zusammen mit dem Anfangswert init über op.
2,4,6) Wie (1,3,5), aber ausgeführt gemäß policy.
Diese Überladungen nehmen nur an der Überladungsauflösung teil, wenn der Wert des folgenden Ausdrucks true ist:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(bis C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(seit C++20)

Gegeben binary_op als die tatsächliche binäre Operation:

  • Das Ergebnis ist nicht deterministisch, wenn der binary_op nicht assoziativ oder nicht kommutativ ist (wie z. B. Gleitkommaaddition).
  • Wenn einer der folgenden Werte nicht in T konvertierbar ist, ist das Programm fehlerhaft:
  • binary_op(init, *first)
  • binary_op(*first, init)
  • binary_op(init, init)
  • binary_op(*first, *first)
  • Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
  • T ist nicht MoveConstructible.
  • binary_op modifiziert ein Element von [first, last).
  • binary_op macht einen Iterator oder Teilbereich von [first, last] ungültig.

Parameter

first, last - das Paar von Iteratoren, das den Bereich der Elemente definiert, auf die der Algorithmus angewendet werden soll
init - der Anfangswert der generalisierten Summe
policy - die zu verwendende Ausführungsrichtlinie
op - binäres FunctionObject , das in nicht spezifizierter Reihenfolge auf das Ergebnis der Dereferenzierung der Eingabeiteratoren, die Ergebnisse anderer op und init angewendet wird.
Typanforderungen
-
InputIt muss die Anforderungen von LegacyInputIterator erfüllen.
-
ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen.

Rückgabewert

1-4) Die generalisierte Summe von init und den Elementen von [ first , last ) über std:: plus <> ( ) .
5,6) Die generalisierte Summe von init und den Elementen von [ first , last ) über op .

Die verallgemeinerte Summe einer Gruppe von Elementen über eine binäre Operation binary_op ist wie folgt definiert:

  • Wenn die Gruppe nur ein Element hat, ist die Summe der Wert des Elements.
  • Andernfalls werden die folgenden Operationen in dieser Reihenfolge ausgeführt:
  1. Nimmt zwei beliebige Elemente elem1 und elem2 aus der Gruppe.
  2. Berechnet binary_op ( elem1, elem2 ) und fügt das Ergebnis zurück in die Gruppe ein.
  3. Wiederholt die Schritte 1 und 2, bis nur noch ein Element in der Gruppe vorhanden ist.

Komplexität

Gegeben N als std:: distance ( first, last ) :

1-4) O(N) Anwendungen von std:: plus <> ( ) .
5,6) O(N) Anwendungen von op .

Ausnahmen

Die Überladungen mit einem Template-Parameter namens ExecutionPolicy melden Fehler wie folgt:

  • Wenn die Ausführung einer als Teil des Algorithmus aufgerufenen Funktion eine Exception wirft und ExecutionPolicy einer der Standard-Policies ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsdefiniert.
  • Wenn der Algorithmus keinen Speicher allokieren kann, wird std::bad_alloc geworfen.

Hinweise

std::reduce verhält sich wie std::accumulate , außer dass die Elemente des Bereichs in beliebiger Reihenfolge gruppiert und neu angeordnet werden können.

Beispiel

Gegenüberstellung von std::reduce und std::accumulate :

#if PARALLEL
#include <execution>
#define SEQ std::execution::seq,
#define PAR std::execution::par,
#else
#define SEQ
#define PAR
#endif
#include <chrono>
#include <iomanip>
#include <iostream>
#include <locale>
#include <numeric>
#include <utility>
#include <vector>
int main()
{
    std::cout.imbue(std::locale("en_US.UTF-8"));
    std::cout << std::fixed << std::setprecision(1);
    auto eval = [](auto fun)
    {
        const auto t1 = std::chrono::high_resolution_clock::now();
        const auto [name, result] = fun();
        const auto t2 = std::chrono::high_resolution_clock::now();
        const std::chrono::duration<double, std::milli> ms = t2 - t1;
        std::cout << std::setw(28) << std::left << name << "Summe: "
                  << result << '\t' << "Zeit: " << ms.count() << " ms\n";
    };
    {
        const std::vector<double> v(100'000'007, 0.1);
        eval([&v]{ return std::pair{"std::accumulate (double)",
            std::accumulate(v.cbegin(), v.cend(), 0.0)}; });
        eval([&v]{ return std::pair{"std::reduce (seq, double)",
            std::reduce(SEQ v.cbegin(), v.cend())}; });
        eval([&v]{ return std::pair{"std::reduce (par, double)",
            std::reduce(PAR v.cbegin(), v.cend())}; });
    }
    {
        const std::vector<long> v(100'000'007, 1);
        eval([&v]{ return std::pair{"std::accumulate (long)",
            std::accumulate(v.cbegin(), v.cend(), 0l)}; });
        eval([&v]{ return std::pair{"std::reduce (seq, long)",
            std::reduce(SEQ v.cbegin(), v.cend())}; });
        eval([&v]{ return std::pair{"std::reduce (par, long)",
            std::reduce(PAR v.cbegin(), v.cend())}; });
    }
}

Mögliche Ausgabe:

// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3; ./a.out
std::accumulate (double)    Summe: 10.000.000,7	Zeit: 356,9 ms
std::reduce (seq, double)   Summe: 10.000.000,7	Zeit: 140,1 ms
std::reduce (par, double)   Summe: 10.000.000,7	Zeit: 140,1 ms
std::accumulate (long)      Summe: 100.000.007	Zeit: 46,0 ms
std::reduce (seq, long)     Summe: 100.000.007	Zeit: 67,3 ms
std::reduce (par, long)     Summe: 100.000.007	Zeit: 63,3 ms
// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out
std::accumulate (double)    Summe: 10.000.000,7	Zeit: 353,4 ms
std::reduce (seq, double)   Summe: 10.000.000,7	Zeit: 140,7 ms
std::reduce (par, double)   Summe: 10.000.000,7	Zeit: 24,7 ms
std::accumulate (long)      Summe: 100.000.007	Zeit: 42,4 ms
std::reduce (seq, long)     Summe: 100.000.007	Zeit: 52,0 ms
std::reduce (par, long)     Summe: 100.000.007	Zeit: 23,1 ms

Siehe auch

summiert oder faltet einen Bereich von Elementen
(Funktionsschablone)
wendet eine Funktion auf einen Bereich von Elementen an und speichert die Ergebnisse in einem Zielbereich
(Funktionsschablone & Algorithmus-Funktionsobjekt)
wendet ein aufrufbares Objekt an und reduziert dann in beliebiger Reihenfolge
(Funktionsschablone)
faltet einen Bereich von Elementen von links
(Algorithmus-Funktionsobjekt)