Namensräume
Varianten
Aktionen

std::reduce

Von cppreference.com
< cpp‎ | algorithm
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
 
Definiert in der Header-Datei <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) Entspricht reduce(first, last, typename std::iterator_traits<InputIt>::value_type{}).
3) Entspricht reduce(first, last, init, std::plus<>()).
5) Reduziert den Bereich [firstlast), möglicherweise permutiert und aggregiert auf nicht spezifizierte Weise, zusammen mit dem Anfangswert init über op.
2,4,6) Dasselbe wie (1,3,5), aber gemäß policy ausgeführt.
Diese Überladungen nehmen an der Auflösungsauflösung teil, nur wenn alle folgenden Bedingungen erfüllt sind

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> ist true.

(bis C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> ist true.

(seit C++20)

Gegeben binary_op als die tatsächliche binäre Operation

  • Das Ergebnis ist nicht deterministisch, wenn binary_op nicht assoziativ oder nicht kommutativ ist (wie z. B. Gleitkomma-Addition).
  • Wenn einer der folgenden Werte nicht in T konvertierbar ist, ist das Programm schlecht geformt
  • 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 kein Element von [firstlast).
  • binary_op macht keinen Iterator oder Teilbereich von [firstlast] ungültig.

Inhalt

[bearbeiten] Parameter

first, last - das Iteratorenpaar, das den Bereich der Elemente definiert, auf die der Algorithmus angewendet werden soll
init - der Anfangswert der generalisierten Summe
policy - die Ausführungsrichtlinie, die verwendet werden soll
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.

[bearbeiten] Rückgabewert

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

Die *generalisierte 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 der Reihe nach ausgeführt
  1. Nimmt zwei beliebige Elemente elem1 und elem2 aus der Gruppe.
  2. Berechnet binary_op(elem1, elem2) und legt das Ergebnis zurück in die Gruppe.
  3. Wiederholt die Schritte 1 und 2, bis nur noch ein Element in der Gruppe ist.

[bearbeiten] Komplexität

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

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

[bearbeiten] Ausnahmen

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

  • Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und ExecutionPolicy eine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsabhängig.
  • Wenn dem Algorithmus der Speicher zur Neuzuweisung fehlt, wird std::bad_alloc ausgelöst.

[bearbeiten] 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.

[bearbeiten] Beispiel

Seitenvergleich zwischen 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 << "sum: "
                  << result << '\t' << "time: " << 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)    sum: 10,000,000.7	time: 356.9 ms
std::reduce (seq, double)   sum: 10,000,000.7	time: 140.1 ms
std::reduce (par, double)   sum: 10,000,000.7	time: 140.1 ms
std::accumulate (long)      sum: 100,000,007	time: 46.0 ms
std::reduce (seq, long)     sum: 100,000,007	time: 67.3 ms
std::reduce (par, long)     sum: 100,000,007	time: 63.3 ms
 
// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out
std::accumulate (double)    sum: 10,000,000.7	time: 353.4 ms
std::reduce (seq, double)   sum: 10,000,000.7	time: 140.7 ms
std::reduce (par, double)   sum: 10,000,000.7	time: 24.7 ms
std::accumulate (long)      sum: 100,000,007	time: 42.4 ms
std::reduce (seq, long)     sum: 100,000,007	time: 52.0 ms
std::reduce (par, long)     sum: 100,000,007	time: 23.1 ms

[bearbeiten] Siehe auch

summiert oder faltet eine Reihe von Elementen
(Funktionstemplate) [bearbeiten]
Wendet eine Funktion auf einen Elementbereich an und speichert die Ergebnisse in einem Zielbereich
(Funktionstempelat) [edit]
wendet eine aufrufbare Funktion an und reduziert dann nicht-sequenziell
(Funktionstemplate) [bearbeiten]
Faltet einen Elementbereich von links
(Algorithmus-Funktionsobjekt)[edit]