Namespaces
Variants

std::experimental::parallel:: transform_reduce

From cppreference.net
Definiert im Header <experimental/numeric>
template < class InputIt, class UnaryOp, class T, class BinaryOp >

T transform_reduce ( InputIt first, InputIt last,

UnaryOp unary_op, T init, BinaryOp binary_op ) ;
(1) (Parallelism TS)
template < class ExecutionPolicy,

class InputIt, class UnaryOp, class T, class BinaryOp >
T transform_reduce ( ExecutionPolicy && policy,
InputIt first, InputIt last,

UnaryOp unary_op, T init, BinaryOp binary_op ) ;
(2) (Parallelism TS)

Wendet unary_op auf jedes Element im Bereich [ first , last ) an und reduziert die Ergebnisse (möglicherweise umgeordnet und auf nicht spezifizierte Weise aggregiert) zusammen mit dem Initialwert init über binary_op .

Das Verhalten ist nicht deterministisch, wenn binary_op nicht assoziativ oder nicht kommutativ ist.

Das Verhalten ist undefiniert, falls unary_op oder binary_op irgendein Element modifiziert oder irgendeinen Iterator im Bereich [ first , last ) ungültig macht.

Inhaltsverzeichnis

Parameter

first, last - der Bereich der Elemente, auf die der Algorithmus angewendet werden soll
init - der Anfangswert der generalisierten Summe
policy - die Ausführungsrichtlinie
unary_op - unärer FunctionObject , der auf jedes Element des Eingabebereichs angewendet wird. Der Rückgabetyp muss als Eingabe für binary_op akzeptabel sein
binary_op - binärer FunctionObject , der in nicht spezifizierter Reihenfolge auf die Ergebnisse von unary_op , die Ergebnisse anderer binary_op und init angewendet wird
Typanforderungen
-
InputIt muss die Anforderungen von LegacyInputIterator erfüllen.

Rückgabewert

Verallgemeinerte Summe von init und unary_op ( * first ) , unary_op ( * ( first + 1 ) ) , ... unary_op ( * ( last - 1 ) ) über binary_op , wobei die verallgemeinerte Summe GSUM(op, a 1 , ..., a N ) wie folgt definiert ist:

  • wenn N = 1 , a 1 ,
  • wenn N > 1 , op(GSUM(op, b 1 , ..., b K ), GSUM(op, b M , ..., b N )) wobei
  • b 1 , ..., b N kann eine beliebige Permutation von a1, ..., aN sein und
  • 1 < K + 1 = M ≤ N

mit anderen Worten, die Ergebnisse von unary_op können in beliebiger Reihenfolge gruppiert und angeordnet werden.

Komplexität

O(last - first) Anwendungen jeweils von unary_op und binary_op .

Ausnahmen

  • Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst,
  • falls policy gleich parallel_vector_execution_policy ist, wird std::terminate aufgerufen.
  • falls policy gleich sequential_execution_policy oder parallel_execution_policy ist, beendet sich der Algorithmus mit einer exception_list , die alle nicht abgefangenen Ausnahmen enthält. Falls es nur eine nicht abgefangene Ausnahme gab, darf der Algorithmus diese erneut werfen, ohne sie in exception_list zu verpacken. Es ist nicht spezifiziert, wie viel Arbeit der Algorithmus ausführt, bevor er nach der ersten aufgetretenen Ausnahme zurückkehrt.
  • falls policy einen anderen Typ hat, ist das Verhalten implementierungsdefiniert.
  • Wenn der Algorithmus keinen Speicher allokieren kann (entweder für sich selbst oder um eine exception_list bei der Behandlung einer Benutzerausnahme zu konstruieren), wird std::bad_alloc geworfen.

Hinweise

unary_op wird nicht auf init angewendet.

Wenn der Bereich leer ist, init wird unverändert zurückgegeben.

  • Wenn policy eine Instanz von sequential_execution_policy ist, werden alle Operationen im aufrufenden Thread ausgeführt.
  • Wenn policy eine Instanz von parallel_execution_policy ist, können Operationen in einer nicht spezifizierten Anzahl von Threads ausgeführt werden, in unbestimmter Reihenfolge zueinander.
  • Wenn policy eine Instanz von parallel_vector_execution_policy ist, kann die Ausführung sowohl parallelisiert als auch vektorisiert werden: Funktionskörpergrenzen werden nicht beachtet und Benutzercode kann auf beliebige Weise überlappt und kombiniert werden (dies impliziert insbesondere, dass ein benutzerdefiniertes Callable keinen Mutex zur Zugriff auf eine gemeinsam genutzte Ressource anfordern darf).

Beispiel

transform_reduce kann verwendet werden, um std::inner_product zu parallelisieren:

#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';
}

Ausgabe:

10007

Siehe auch

summiert oder faltet eine Reihe von Elementen
(Funktions-Template)
wendet eine Funktion auf eine Reihe von Elementen an und speichert Ergebnisse in einem Zielbereich
(Funktions-Template)
(parallelism TS)
ähnlich zu std::accumulate , jedoch außerhalb der Reihenfolge
(Funktions-Template)